Skip to content

Commit

Permalink
Merge pull request #19198 from hrydgard/fifa-atrac-crash-fix
Browse files Browse the repository at this point in the history
Prevent a buffer overflow at the end of Atrac tracks.
  • Loading branch information
hrydgard authored May 27, 2024
2 parents 1754fd1 + e5baebf commit 79c3762
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 7 deletions.
16 changes: 9 additions & 7 deletions Core/HLE/AtracCtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -959,13 +959,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
if (off < first_.size) {
uint8_t *indata = BufferStart() + off;
int bytesConsumed = 0;
int outSamples = 0;
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, (int16_t *)outbuf, &outSamples)) {
// Decode failed.
*SamplesNum = 0;
*finish = 1;
return ATRAC_ERROR_ALL_DATA_DECODED;
}
int outSamples = track_.SamplesPerFrame();
int outBytes = outSamples * outputChannels_ * sizeof(int16_t);
gotFrame = true;

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

outSamples = numSamples;
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, (int16_t *)outbuf, &outSamples)) {
// Decode failed.
*SamplesNum = 0;
*finish = 1;
return ATRAC_ERROR_ALL_DATA_DECODED;
}

if (packetAddr != 0 && MemBlockInfoDetailed()) {
char tagData[128];
size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "AtracDecode/", packetAddr, track_.bytesPerFrame);
Expand Down
4 changes: 4 additions & 0 deletions Core/HW/Atrac3Standalone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ class Atrac3Audio : public AudioDecoder {
*inbytesConsumed = result;
}
if (outSamples) {
// Allow capping the output samples by setting *outSamples to non-zero.
if (*outSamples != 0) {
nb_samples = std::min(*outSamples, nb_samples);
}
*outSamples = nb_samples;
}
if (nb_samples > 0) {
Expand Down
2 changes: 2 additions & 0 deletions Core/HW/SimpleAudioDec.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class AudioDecoder {

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

Expand Down

0 comments on commit 79c3762

Please sign in to comment.