DiscIO: Fix reading certain WIA chunks with many exceptions

The loop in WIARVZFileReader::Chunk::Read could terminate
prematurely if the size argument was smaller than the size
of an exception list which had only been partially loaded.
This commit is contained in:
JosJuice 2021-03-05 23:48:58 +01:00
parent de30559862
commit 14bfc0be78
2 changed files with 13 additions and 5 deletions

View File

@ -653,7 +653,7 @@ bool WIARVZFileReader<RVZ>::Chunk::Read(u64 offset, u64 size, u8* out_ptr)
return false; return false;
} }
while (offset + size > m_out.bytes_written - m_out_bytes_used_for_exceptions) while (offset + size > GetOutBytesWrittenExcludingExceptions())
{ {
u64 bytes_to_read; u64 bytes_to_read;
if (offset + size == m_out.data.size()) if (offset + size == m_out.data.size())
@ -663,13 +663,13 @@ bool WIARVZFileReader<RVZ>::Chunk::Read(u64 offset, u64 size, u8* out_ptr)
} }
else else
{ {
// Pick a suitable amount of compressed data to read. The std::min line has to // Pick a suitable amount of compressed data to read. We have to ensure that bytes_to_read
// be as it is, but the rest is a bit arbitrary and can be changed if desired. // is larger than 0 and smaller than or equal to the number of bytes available to read,
// but the rest is a bit arbitrary and could be changed.
// The compressed data is probably not much bigger than the decompressed data. // The compressed data is probably not much bigger than the decompressed data.
// Add a few bytes for possible compression overhead and for any hash exceptions. // Add a few bytes for possible compression overhead and for any hash exceptions.
bytes_to_read = bytes_to_read = offset + size - GetOutBytesWrittenExcludingExceptions() + 0x100;
offset + size - (m_out.bytes_written - m_out_bytes_used_for_exceptions) + 0x100;
// Align the access in an attempt to gain speed. But we don't actually know the // Align the access in an attempt to gain speed. But we don't actually know the
// block size of the underlying storage device, so we just use the Wii block size. // block size of the underlying storage device, so we just use the Wii block size.
@ -839,6 +839,12 @@ void WIARVZFileReader<RVZ>::Chunk::GetHashExceptions(
m_in_bytes_used_for_exceptions)); m_in_bytes_used_for_exceptions));
} }
template <bool RVZ>
size_t WIARVZFileReader<RVZ>::Chunk::GetOutBytesWrittenExcludingExceptions() const
{
return m_exception_lists == 0 ? m_out.bytes_written - m_out_bytes_used_for_exceptions : 0;
}
template <bool RVZ> template <bool RVZ>
bool WIARVZFileReader<RVZ>::ApplyHashExceptions( bool WIARVZFileReader<RVZ>::ApplyHashExceptions(
const std::vector<HashExceptionEntry>& exception_list, const std::vector<HashExceptionEntry>& exception_list,

View File

@ -202,6 +202,8 @@ private:
bool HandleExceptions(const u8* data, size_t bytes_allocated, size_t bytes_written, bool HandleExceptions(const u8* data, size_t bytes_allocated, size_t bytes_written,
size_t* bytes_used, bool align); size_t* bytes_used, bool align);
size_t GetOutBytesWrittenExcludingExceptions() const;
DecompressionBuffer m_in; DecompressionBuffer m_in;
DecompressionBuffer m_out; DecompressionBuffer m_out;
size_t m_in_bytes_read = 0; size_t m_in_bytes_read = 0;