summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-09-21 14:24:50 +0200
committerMax Kellermann <max@musicpd.org>2020-09-21 14:43:58 +0200
commitc13fe63f105c7d0083020d305b947cd8c66bd4dc (patch)
treee6d4603e5bff192d709a298db02bd6e884f80357 /src
parent07842abcb04a13d9ae739b1b37c453a0510be0a5 (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.cxx26
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);