Skip to content

Commit 79c3762

Browse files
authored
Merge pull request #19198 from hrydgard/fifa-atrac-crash-fix
Prevent a buffer overflow at the end of Atrac tracks.
2 parents 1754fd1 + e5baebf commit 79c3762

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

Core/HLE/AtracCtx.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -959,13 +959,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
959959
if (off < first_.size) {
960960
uint8_t *indata = BufferStart() + off;
961961
int bytesConsumed = 0;
962-
int outSamples = 0;
963-
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, (int16_t *)outbuf, &outSamples)) {
964-
// Decode failed.
965-
*SamplesNum = 0;
966-
*finish = 1;
967-
return ATRAC_ERROR_ALL_DATA_DECODED;
968-
}
962+
int outSamples = track_.SamplesPerFrame();
969963
int outBytes = outSamples * outputChannels_ * sizeof(int16_t);
970964
gotFrame = true;
971965

@@ -978,6 +972,14 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
978972
// If we're at the end, clamp to samples we want. It always returns a full chunk.
979973
numSamples = std::min(maxSamples, numSamples);
980974

975+
outSamples = numSamples;
976+
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, (int16_t *)outbuf, &outSamples)) {
977+
// Decode failed.
978+
*SamplesNum = 0;
979+
*finish = 1;
980+
return ATRAC_ERROR_ALL_DATA_DECODED;
981+
}
982+
981983
if (packetAddr != 0 && MemBlockInfoDetailed()) {
982984
char tagData[128];
983985
size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "AtracDecode/", packetAddr, track_.bytesPerFrame);

Core/HW/Atrac3Standalone.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class Atrac3Audio : public AudioDecoder {
8282
*inbytesConsumed = result;
8383
}
8484
if (outSamples) {
85+
// Allow capping the output samples by setting *outSamples to non-zero.
86+
if (*outSamples != 0) {
87+
nb_samples = std::min(*outSamples, nb_samples);
88+
}
8589
*outSamples = nb_samples;
8690
}
8791
if (nb_samples > 0) {

Core/HW/SimpleAudioDec.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class AudioDecoder {
3838

3939
// inbytesConsumed can include skipping metadata.
4040
// outSamples is in stereo samples. So you have to multiply by 4 for 16-bit stereo audio to get bytes.
41+
// For Atrac3, if *outSamples != 0, it'll cap the number of samples to output. In this case, its value can only shrink.
42+
// TODO: Implement that in the other decoders too, if needed.
4143
virtual bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) = 0;
4244
virtual bool IsOK() const = 0;
4345

0 commit comments

Comments
 (0)