diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc index 2d11e7c3b..6b9991f77 100644 --- a/src/xenia/apu/xma_context.cc +++ b/src/xenia/apu/xma_context.cc @@ -597,9 +597,19 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { std::memset(xma_frame_.data(), 0, xma_frame_.size()); { - auto offset = - stream.Copy(xma_frame_.data() + 1, - std::min(split_frame_len_, split_frame_len_partial_)); + int32_t bits_to_copy = + std::min(split_frame_len_, split_frame_len_partial_); + + if (!stream.IsOffsetValid(bits_to_copy)) { + XELOGAPU( + "XmaContext {}: Error - Invalid amount of bits to copy! " + "split_frame_len: {}, split_partial: {}, offset_bits: {}", + id(), split_frame_len_, split_frame_len_partial_, + stream.offset_bits()); + SwapInputBuffer(data); + return; + } + auto offset = stream.Copy(xma_frame_.data() + 1, bits_to_copy); assert_true(offset < 8); split_frame_padding_start_ = static_cast(offset); } diff --git a/src/xenia/base/bit_stream.cc b/src/xenia/base/bit_stream.cc index ced073907..e7f47fb3b 100644 --- a/src/xenia/base/bit_stream.cc +++ b/src/xenia/base/bit_stream.cc @@ -29,6 +29,16 @@ void BitStream::SetOffset(size_t offset_bits) { size_t BitStream::BitsRemaining() { return size_bits_ - offset_bits_; } +bool BitStream::IsOffsetValid(size_t num_bits) { + size_t offset_bytes = offset_bits_ >> 3; + size_t rel_offset_bits = offset_bits_ - (offset_bytes << 3); + + if (rel_offset_bits && int32_t(num_bits - 8 - rel_offset_bits) < 0) { + return false; + } + return true; +} + uint64_t BitStream::Peek(size_t num_bits) { // FYI: The reason we can't copy more than 57 bits is: // 57 = 7 * 8 + 1 - that can only span a maximum of 8 bytes. diff --git a/src/xenia/base/bit_stream.h b/src/xenia/base/bit_stream.h index def889a3e..1d7036188 100644 --- a/src/xenia/base/bit_stream.h +++ b/src/xenia/base/bit_stream.h @@ -28,6 +28,7 @@ class BitStream { void Advance(size_t num_bits); void SetOffset(size_t offset_bits); size_t BitsRemaining(); + bool IsOffsetValid(size_t num_bits); // Note: num_bits MUST be in the range 0-57 (inclusive) uint64_t Peek(size_t num_bits);