ajm mp3: check frame size on every frame (#3995)
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled

This commit is contained in:
Vladislav Mikhalin 2026-02-06 00:16:22 +03:00 committed by GitHub
parent 1fe72cfe1f
commit b88ec484ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 14 additions and 15 deletions

View File

@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "ajm_error.h"
#include "ajm_mp3.h"
#include "ajm_result.h"
#include "common/assert.h"
#include "core/libraries/ajm/ajm_error.h"
#include "core/libraries/ajm/ajm_mp3.h"
#include "core/libraries/error_codes.h"
extern "C" {
@ -122,7 +124,6 @@ void AjmMp3Decoder::Reset() {
avcodec_flush_buffers(m_codec_context);
m_header.reset();
m_frame_samples = 0;
m_frame_size = 0;
}
void AjmMp3Decoder::GetInfo(void* out_info) const {
@ -141,7 +142,7 @@ void AjmMp3Decoder::GetInfo(void* out_info) const {
u32 AjmMp3Decoder::GetMinimumInputSize() const {
// 4 bytes is for mp3 header that contains frame_size
return std::max<u32>(m_frame_size, 4);
return 4;
}
DecoderResult AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuffer& output,
@ -149,12 +150,11 @@ DecoderResult AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuff
DecoderResult result{};
AVPacket* pkt = av_packet_alloc();
if ((!m_header.has_value() || m_frame_samples == 0) && in_buf.size() >= 4) {
m_header = std::byteswap(*reinterpret_cast<u32*>(in_buf.data()));
AjmDecMp3ParseFrame info{};
ParseMp3Header(in_buf.data(), in_buf.size(), true, &info);
m_frame_samples = info.samples_per_channel;
m_frame_size = info.frame_size;
m_header = std::byteswap(*reinterpret_cast<u32*>(in_buf.data()));
AjmDecMp3ParseFrame info{};
ParseMp3Header(in_buf.data(), in_buf.size(), true, &info);
m_frame_samples = info.samples_per_channel;
if (info.total_samples != 0 || info.encoder_delay != 0) {
gapless.init = {
.total_samples = info.total_samples,
.skip_samples = static_cast<u16>(info.encoder_delay),
@ -163,6 +163,10 @@ DecoderResult AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuff
gapless.current = gapless.init;
}
if (in_buf.size() < info.frame_size) {
result.result |= ORBIS_AJM_RESULT_PARTIAL_INPUT;
}
int ret = av_parser_parse2(m_parser, m_codec_context, &pkt->data, &pkt->size, in_buf.data(),
in_buf.size(), AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
ASSERT_MSG(ret >= 0, "Error while parsing {}", ret);
@ -424,11 +428,7 @@ int AjmMp3Decoder::ParseMp3Header(const u8* p_begin, u32 stream_size, int parse_
frame->encoder_delay = std::byteswap(*reinterpret_cast<const u16*>(p_fgh + 1));
frame->total_samples = std::byteswap(*reinterpret_cast<const u32*>(p_fgh + 3));
frame->ofl_type = AjmDecMp3OflType::Fgh;
} else {
LOG_ERROR(Lib_Ajm, "FGH header CRC is incorrect.");
}
} else {
LOG_ERROR(Lib_Ajm, "Could not find vendor header.");
}
}

View File

@ -99,7 +99,6 @@ private:
SwrContext* m_swr_context = nullptr;
std::optional<u32> m_header;
u32 m_frame_samples = 0;
u32 m_frame_size = 0;
};
} // namespace Libraries::Ajm