mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 16:30:30 +02:00
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.