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.
This commit is contained in:
Max Kellermann 2020-09-21 14:24:50 +02:00
parent 5acea014b0
commit 79b2366387
1 changed files with 25 additions and 1 deletions

View File

@ -182,10 +182,21 @@ class Iso9660InputStream final : public InputStream {
fill = nbytes; fill = nbytes;
position = 0; position = 0;
} }
void Clear() noexcept {
position = fill = 0;
}
}; };
BlockBuffer buffer; 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: public:
Iso9660InputStream(const std::shared_ptr<Iso9660> &_iso, Iso9660InputStream(const std::shared_ptr<Iso9660> &_iso,
const char *_uri, const char *_uri,
@ -208,7 +219,9 @@ public:
if (new_offset > size) if (new_offset > size)
throw std::runtime_error("Invalid seek offset"); throw std::runtime_error("Invalid seek offset");
offset = new_offset; skip = new_offset % ISO_BLOCKSIZE;
offset = new_offset - skip;
buffer.Clear();
} }
}; };
@ -273,9 +286,20 @@ Iso9660InputStream::Read(void *ptr, size_t read_size)
buffer.Append(nbytes); buffer.Append(nbytes);
r = buffer.Read(); 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(!r.empty());
assert(skip == 0);
size_t nbytes = std::min(read_size, r.size); size_t nbytes = std::min(read_size, r.size);
memcpy(ptr, r.data, nbytes); memcpy(ptr, r.data, nbytes);