diff --git a/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp b/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp index ef22d77d77..8781e0818b 100644 --- a/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp +++ b/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp @@ -413,9 +413,10 @@ static int ParseAtrac9Loop(const RiffChunks& chunks, Ngs2WaveformInfo& info) { return SCE_NGS2_OK; } -static int ParseAtrac9(const RiffChunks& chunks, Ngs2WaveformInfo& info) { +static int ParseAtrac9(const RiffChunks& chunks, std::size_t size, Ngs2WaveformInfo& info) { const auto* format = chunks.format; if (chunks.formatSize < FMT_ATRAC9_SIZE || chunks.fact == nullptr || chunks.factSize < FACT_ATRAC9_SIZE) return SCE_NGS2_ERROR_INVALID_WAVEFORM_FORMAT; + if (chunks.dataSize > size - chunks.dataOffset) return SCE_NGS2_ERROR_INVALID_WAVEFORM_DATA; std::uint8_t config[4]; std::memcpy(config, format + FMT_CONFIG_OFFSET, sizeof(config)); Atrac9CodecInfo codec{}; @@ -507,7 +508,7 @@ static int ParseWaveform(const RiffChunks& chunks, std::size_t size, Ngs2Wavefor if (chunks.formatSize < FMT_EXTENSIBLE_SIZE) return SCE_NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT; const auto* guid = chunks.format + FMT_GUID_OFFSET; if (std::memcmp(guid, PCM_GUID, sizeof(PCM_GUID)) == 0) return ParsePcm(chunks, size, info, false); - if (std::memcmp(guid, ATRAC9_GUID, sizeof(ATRAC9_GUID)) == 0) return ParseAtrac9(chunks, info); + if (std::memcmp(guid, ATRAC9_GUID, sizeof(ATRAC9_GUID)) == 0) return ParseAtrac9(chunks, size, info); if (chunks.formatSize == FMT_ATRAC9_SIZE) throw std::runtime_error("NGS2: parsing an extensible waveform of format size 0x34 without the ATRAC9 GUID is not implemented"); if (std::memcmp(guid, TYPE_43_GUID, sizeof(TYPE_43_GUID)) == 0) throw std::runtime_error("NGS2: parsing waveform type 0x43 is not implemented"); return SCE_NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT; diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp index 85e367f247..dd4201e64d 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp @@ -376,7 +376,7 @@ static void TestParseLoops() { } const auto file = LoopedFile(100, 700, 0); Ngs2WaveformInfo info{}; - Require(sceNgs2ParseWaveformData(file.data(), 168, &info) == SCE_NGS2_OK); + Require(sceNgs2ParseWaveformData(file.data(), file.size(), &info) == SCE_NGS2_OK); Require(info.block[1].num_repeats == UINT32_MAX); const auto system = CreateSystem(); const auto voice = Voice(CreateRack(system, SCE_NGS2_RACK_ID_SAMPLER)); @@ -743,6 +743,16 @@ static void TestStreamingReplay() { } } +static void TestDataChunkBeyondBuffer() { + const auto file = At9File(48000); + Ngs2WaveformInfo info{}; + Require(sceNgs2ParseWaveformData(file.data(), file.size(), &info) == SCE_NGS2_OK && info.data_size == SuperframeBytes); + auto truncated = file; + Set32(truncated, 4, static_cast(truncated.size() - 8 + 16)); + Set32(truncated, 96, SuperframeBytes + 16); + Require(sceNgs2ParseWaveformData(truncated.data(), truncated.size(), &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_DATA); +} + int main() { const auto reference = Reference(); TestSkipAndBlockEnd(reference); @@ -764,5 +774,6 @@ int main() { TestBlockOnEmptyAtrac9Voice(); TestEmptyAddsCloseLikePcm(); TestSilenceFlagRejected(); + TestDataChunkBeyondBuffer(); return 0; }