Merge pull request #19198 from hrydgard/fifa-atrac-crash-fix

Prevent a buffer overflow at the end of Atrac tracks.
This commit is contained in:
Henrik Rydgård 2024-05-27 13:50:57 +02:00 committed by GitHub
commit 79c3762938
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 15 additions and 7 deletions

View file

@ -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;
@ -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);

View file

@ -82,6 +82,10 @@ public:
*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) {

View file

@ -38,6 +38,8 @@ public:
// 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;