Files
AnyPS5/core/libs/prx/libSceAjm.native/PatchLibAtrac9.cmake
T
Muhammad Wasif Ali WasifandClaude Opus 5.5 f3a44a9be2 fix(libSceAjm.native): reject ATRAC9 config data with a reserved channel configuration
LibAtrac9 defines six channel configurations but indexed the table with all eight values of the 3-bit field, so indices 6 and 7 read past it and initialized a decoder from the bytes that follow. The config data check now fails for them, which sceAjmDecAt9ParseConfigData, AJM initialization, libSceAudiodec and NGS2 already report as invalid config data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 13:34:21 +02:00

31 lines
2.5 KiB
CMake

file(READ ${LIBATRAC9_DIR}/unpack.c libatrac9Unpack)
set(libatrac9OldGuard "block->GradientEndUnit < 0 || block->GradientEndUnit >= 48")
set(libatrac9NewGuard "block->GradientEndUnit < 0 || block->GradientEndUnit > 31")
string(FIND "${libatrac9Unpack}" "${libatrac9OldGuard}" libatrac9GuardPosition)
if(libatrac9GuardPosition EQUAL -1)
message(FATAL_ERROR "LibAtrac9 gradient guard has changed; review the local bounds fix")
endif()
string(REPLACE "${libatrac9OldGuard}" "${libatrac9NewGuard}" libatrac9Unpack "${libatrac9Unpack}")
file(MAKE_DIRECTORY ${LIBATRAC9_PATCHED_DIR})
file(WRITE ${LIBATRAC9_PATCHED_DIR}/unpack.c "${libatrac9Unpack}")
file(READ ${LIBATRAC9_DIR}/bit_reader.c libatrac9BitReader)
set(libatrac9OldPeek "\tconst int byteIndex = br->Position / 8;\n\tconst int bitIndex = br->Position % 8;\n\tconst int numBytes = (bitIndex + bits - 1) / 8 + 1;\n\tconst unsigned char* buffer = br->Buffer;\n\n\tint value;\n\tswitch (numBytes) {")
string(FIND "${libatrac9BitReader}" "${libatrac9OldPeek}" libatrac9PeekPosition)
if(libatrac9PeekPosition EQUAL -1)
message(FATAL_ERROR "LibAtrac9 PeekInt has changed; review the local fast path")
endif()
set(libatrac9NewPeek "\tconst int byteIndex = br->Position >> 3;\n\tconst int bitIndex = br->Position & 7;\n\tconst unsigned char* buffer = br->Buffer;\n\tif (bits > 0 && bits <= 24 && byteIndex + 4 <= (br->LengthBits >> 3)) {\n\t\tconst unsigned raw = ((unsigned)buffer[byteIndex] << 24) | ((unsigned)buffer[byteIndex + 1] << 16) | ((unsigned)buffer[byteIndex + 2] << 8) | (unsigned)buffer[byteIndex + 3];\n\t\treturn (int)((raw << bitIndex) >> (32 - bits));\n\t}\n\tconst int numBytes = (bitIndex + bits - 1) / 8 + 1;\n\tint value;\n\tswitch (numBytes) {")
string(REPLACE "${libatrac9OldPeek}" "${libatrac9NewPeek}" libatrac9BitReader "${libatrac9BitReader}")
file(WRITE ${LIBATRAC9_PATCHED_DIR}/bit_reader.c "${libatrac9BitReader}")
file(READ ${LIBATRAC9_DIR}/decinit.c libatrac9Decinit)
set(libatrac9OldConfigGuard "header != 0xFE || validationBit != 0")
set(libatrac9NewConfigGuard "header != 0xFE || validationBit != 0 || config->ChannelConfigIndex > 5")
string(FIND "${libatrac9Decinit}" "${libatrac9OldConfigGuard}" libatrac9ConfigGuardPosition)
if(libatrac9ConfigGuardPosition EQUAL -1)
message(FATAL_ERROR "LibAtrac9 config data guard has changed; review the local bounds fix")
endif()
string(REPLACE "${libatrac9OldConfigGuard}" "${libatrac9NewConfigGuard}" libatrac9Decinit "${libatrac9Decinit}")
file(WRITE ${LIBATRAC9_PATCHED_DIR}/decinit.c "${libatrac9Decinit}")