Commit Graph
14 Commits
Author SHA1 Message Date
Henrik Rydgård cd052ea640 Adjust the level of Claude-based paranoia here and there 2026-08-11 20:08:01 +02:00
Henrik Rydgård afbc73bb68 AtracTrack: fix OOB reads and unbounded allocation in header parsing
These parsers run on fully game-controlled buffers (reachable via the
various sceAtracSetData*/sceAtracSetHalfwayBuffer* HLE calls), so a
malicious/malformed game can supply arbitrary bytes here:

- AnalyzeAtracTrack's RIFF chunk-walking loop computed `offset +=
  chunk + (chunk & 1)` (all in 32-bit) and only bounds-checked
  afterwards. A crafted chunk size could wrap `offset` (and the
  `offset + 12` check itself) around, bypassing the bounds check
  entirely - Read32(), whose offset parameter is a plain `int`, would
  then read from a wild pointer far outside the buffer. Do the
  validation in 64-bit before mutating offset, mirroring the pattern
  already used by the newer ParseWaveAT3 parser.
- AnalyzeAA3Track validated `size >= tagSize + 36` but then read up to
  relative index 35 after rebasing by 10+tagSize - i.e. absolute index
  tagSize+45, 10 bytes past what was actually checked.
- The SMPL chunk's loop count (checkNumLoops) was only checked for
  being negative, not bounded against the chunk's actual size, so a
  crafted value near INT_MAX would drive an unbounded (up to ~2
  billion entry) vector::resize() - an easy crash/OOM. The same
  unclamped value also let the fill loop below run past the end of
  the chunk, since its bound compares the loop counter to chunkSize
  rather than the byte offset actually being advanced (24 bytes/loop).
  Clamping checkNumLoops to what the chunk can actually hold fixes
  both.
- ParseAA3Headers checked for at least 9 bytes but the "ea3"/"id3"
  branch it guards reads up through byte index 9, needing 10.
2026-08-11 08:43:52 +02:00
Henrik Rydgård edd968062a Correct the Atrac3 security check that broke music in GTA
See 4cd611b71f
2026-08-05 00:15:38 +02:00
Henrik Rydgård 4cd611b71f Fix out-of-bounds reads in ATRAC track parsing
AnalyzeAtracTrack used max(fileSize, size) as the chunk-parse bound with
fileSize taken from the file's RIFF header, so a crafted inflated RIFF
size could push reads past the end of the buffer. Keep the real-library
behavior of tolerating a too-low size, but clamp the parse bound to the
actual mapped guest memory at the buffer.

Also guard ParseWaveAT3's RIFF scan against a blockSize < 4 underflow
that could make the offset negative and bypass the loop bounds check, and
clamp readSize to the mapped region in Atrac2::SetData before parsing.
2026-08-01 11:57:27 +02:00
Henrik Rydgård 64c05a5ddf Atrac3: Allow sending 0xFFFFFFFF as data size. Death JR does this on audio loop for some reason. 2026-03-26 11:59:43 -06:00
Henrik Rydgård 9ff1cf3572 Remove bad assert (the function already checks for null later).
Fixes #20862
2025-10-09 12:43:43 -06:00
Henrik Rydgård b15b0c441e Make the checks for atrac size more lenient. Possible fix for #20834 2025-09-24 10:08:53 -06:00
Henrik Rydgård 4d7b51d8cb Reimplement AA3 header parsing 2025-07-22 17:48:20 +02:00
Henrik Rydgård 0fc7d430b4 Reimplement wave parsing more simply, for AtracCtx2. 2025-06-26 11:06:18 +02:00
Henrik Rydgård 3cd1f2f832 sceAudioCodec: Fix AT3 and AAC playback (possibly limited to certain bitrates) but fixes Kosmodrones 2025-04-13 15:48:11 +02:00
Henrik Rydgård f7ff2e2d20 Remove redundant constants 2025-04-12 11:35:55 +02:00
Henrik Rydgård 77e1c9dd69 Work on audiocodec 2025-04-02 13:30:34 +02:00
Henrik Rydgård 2b558eb545 Fix regression in Tomb Raider Legends
Need to make sure a buffer size check happens before the buffer is
accessed - since the game calls sceAtracSetDataAndGetID with both buffer
and bufferSize as 0, and it expects to receive TOO_SMALL and not a
memory exception.

Thanks to @sum2012 for quick investigationh help.
2025-03-23 07:11:01 +01:00
Henrik Rydgård e70dd3b2df Break out AtracTrack into its own file. Add a little atrac analysis tool to ImDebugger (for future use) 2025-03-19 16:15:51 +01:00