mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
SimpleAudioDec: fix unsigned underflow and unvalidated stream-data size
FindNextMp3Sync() computed `sourcebuff.size() - 2` as the loop bound; when size() is 0 or 1 this underflows to a huge size_t, turning the scan into an out-of-bounds read. Reachable via sceMp3NotifyAddStreamData followed by sceMp3Decode with as little as 1 pending byte. AuNotifyAddStreamData() trusted the game-supplied `size` outright: a negative value would make sourcebuff.resize() attempt a huge allocation (via size_t underflow), an unbounded positive value grows sourcebuff without limit, and the validated range didn't match the actual read range (checked [AuBuf, AuBuf+size) while reading from [AuBuf+offset, AuBuf+offset+size)). Validate size is positive and capped to the buffer's declared capacity, and validate the range actually read.
This commit is contained in:
1 parent
029066a977
commit
bfbe44ad1c
1 file changed
+11
-1
@@ -481,6 +481,11 @@ AuCtx::~AuCtx() {
|
||||
}
|
||||
|
||||
size_t AuCtx::FindNextMp3Sync() {
|
||||
// sourcebuff.size() - 2 underflows to a huge size_t when size() is 0 or 1,
|
||||
// turning this into an out-of-bounds scan - guard against that explicitly.
|
||||
if (sourcebuff.size() < 3) {
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < sourcebuff.size() - 2; ++i) {
|
||||
if ((sourcebuff[i] & 0xFF) == 0xFF && (sourcebuff[i + 1] & 0xC0) == 0xC0) {
|
||||
return i;
|
||||
@@ -603,7 +608,12 @@ u32 AuCtx::AuNotifyAddStreamData(int size) {
|
||||
AuBufAvailable += size;
|
||||
}
|
||||
|
||||
if (Memory::IsValidRange(AuBuf, size)) {
|
||||
// `size` is game-supplied and was previously trusted outright: a negative value
|
||||
// would make sourcebuff.resize() attempt a huge allocation (size_t underflow),
|
||||
// and an unbounded positive value would grow sourcebuff without limit (DoS).
|
||||
// The validated range also has to match what's actually read below - it was
|
||||
// checking [AuBuf, AuBuf+size) while the copy reads from [AuBuf+offset, ...).
|
||||
if (size > 0 && size <= (int)AuBufSize && Memory::IsValidRange(AuBuf + offset, size)) {
|
||||
sourcebuff.resize(sourcebuff.size() + size);
|
||||
Memory::MemcpyUnchecked(&sourcebuff[sourcebuff.size() - size], AuBuf + offset, size);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user