From 14bfc0be78c6eea825dacadf51dd1eaa4c64f4d9 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 5 Mar 2021 23:48:58 +0100 Subject: [PATCH] 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. --- Source/Core/DiscIO/WIABlob.cpp | 16 +++++++++++----- Source/Core/DiscIO/WIABlob.h | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Source/Core/DiscIO/WIABlob.cpp b/Source/Core/DiscIO/WIABlob.cpp index 8a76b9bd77..80baf6c677 100644 --- a/Source/Core/DiscIO/WIABlob.cpp +++ b/Source/Core/DiscIO/WIABlob.cpp @@ -653,7 +653,7 @@ bool WIARVZFileReader::Chunk::Read(u64 offset, u64 size, u8* out_ptr) return false; } - while (offset + size > m_out.bytes_written - m_out_bytes_used_for_exceptions) + while (offset + size > GetOutBytesWrittenExcludingExceptions()) { u64 bytes_to_read; if (offset + size == m_out.data.size()) @@ -663,13 +663,13 @@ bool WIARVZFileReader::Chunk::Read(u64 offset, u64 size, u8* out_ptr) } else { - // Pick a suitable amount of compressed data to read. The std::min line has to - // be as it is, but the rest is a bit arbitrary and can be changed if desired. + // Pick a suitable amount of compressed data to read. We have to ensure that bytes_to_read + // 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. // Add a few bytes for possible compression overhead and for any hash exceptions. - bytes_to_read = - offset + size - (m_out.bytes_written - m_out_bytes_used_for_exceptions) + 0x100; + bytes_to_read = offset + size - GetOutBytesWrittenExcludingExceptions() + 0x100; // 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. @@ -839,6 +839,12 @@ void WIARVZFileReader::Chunk::GetHashExceptions( m_in_bytes_used_for_exceptions)); } +template +size_t WIARVZFileReader::Chunk::GetOutBytesWrittenExcludingExceptions() const +{ + return m_exception_lists == 0 ? m_out.bytes_written - m_out_bytes_used_for_exceptions : 0; +} + template bool WIARVZFileReader::ApplyHashExceptions( const std::vector& exception_list, diff --git a/Source/Core/DiscIO/WIABlob.h b/Source/Core/DiscIO/WIABlob.h index d6e54df7ac..8458ac95ee 100644 --- a/Source/Core/DiscIO/WIABlob.h +++ b/Source/Core/DiscIO/WIABlob.h @@ -202,6 +202,8 @@ private: bool HandleExceptions(const u8* data, size_t bytes_allocated, size_t bytes_written, size_t* bytes_used, bool align); + size_t GetOutBytesWrittenExcludingExceptions() const; + DecompressionBuffer m_in; DecompressionBuffer m_out; size_t m_in_bytes_read = 0;