diff options
author | Max Kellermann <max@musicpd.org> | 2020-09-21 14:24:50 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-09-21 14:43:58 +0200 |
commit | c13fe63f105c7d0083020d305b947cd8c66bd4dc (patch) | |
tree | e6d4603e5bff192d709a298db02bd6e884f80357 /src | |
parent | 07842abcb04a13d9ae739b1b37c453a0510be0a5 (diff) |
archive/iso9660: fix odd seeking bug (assertion failure)
Skip the beginning of a sector if the last seek was odd, and clear the
buffer on seek.
Diffstat (limited to 'src')
-rw-r--r-- | src/archive/plugins/Iso9660ArchivePlugin.cxx | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index 540da0e3f..0217faddc 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -184,10 +184,21 @@ class Iso9660InputStream final : public InputStream { fill = nbytes; position = 0; } + + void Clear() noexcept { + position = fill = 0; + } }; BlockBuffer buffer; + /** + * Skip this number of bytes of the first sector after filling + * the buffer next time. This is used for seeking into the + * middle of a sector. + */ + size_t skip = 0; + public: Iso9660InputStream(std::shared_ptr<Iso9660> _iso, const char *_uri, @@ -211,7 +222,9 @@ public: if (new_offset > size) throw std::runtime_error("Invalid seek offset"); - offset = new_offset; + skip = new_offset % ISO_BLOCKSIZE; + offset = new_offset - skip; + buffer.Clear(); } }; @@ -277,9 +290,20 @@ Iso9660InputStream::Read(std::unique_lock<Mutex> &, buffer.Append(nbytes); r = buffer.Read(); + + if (skip > 0) { + if (skip >= r.size) + throw std::runtime_error("Premature end of ISO9660 track"); + + buffer.Consume(skip); + skip = 0; + + r = buffer.Read(); + } } assert(!r.empty()); + assert(skip == 0); size_t nbytes = std::min(read_size, r.size); memcpy(ptr, r.data, nbytes); |