From d2476bfd2b0ab683f24ff92cb2b206549f0a1659 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 31 Jul 2026 20:45:49 -0300 Subject: [PATCH] avformat/iamf_parse: bound the output mix gain duration by the audio elements Based on a patch by Michael Niedermayer Fixes: unbounded allocation Fixes: poc_output_mix_config_dos.iamf Fixes: 387qWpjUgeKH Found-by: Duong Tran Thai (CyStack) Signed-off-by: James Almer --- libavformat/iamf_parse.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavformat/iamf_parse.c b/libavformat/iamf_parse.c index 3b4170b16c..892145cd87 100644 --- a/libavformat/iamf_parse.c +++ b/libavformat/iamf_parse.c @@ -609,6 +609,7 @@ static int ambisonics_config(void *s, AVIOContext *pb, static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, unsigned int type, const IAMFAudioElement *audio_element, + const IAMFCodecConfig *codec_config, AVIAMFParamDefinition **out_param_definition) { IAMFParamDefinition *param_definition = NULL; @@ -631,14 +632,10 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, if (mode == 0) { duration = ffio_read_leb(pb); - if (!duration) + if (!duration || duration > av_rescale(codec_config->nb_samples, + codec_config->sample_rate, parameter_rate)) { + av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id); return AVERROR_INVALIDDATA; - if (audio_element) { - const IAMFCodecConfig *codec_config = ff_iamf_get_codec_config(c, audio_element->codec_config_id); - if (duration > av_rescale(codec_config->nb_samples, codec_config->sample_rate, parameter_rate)) { - av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id); - return AVERROR_INVALIDDATA; - } } constant_subblock_duration = ffio_read_leb(pb); if (constant_subblock_duration == 0) @@ -899,13 +896,17 @@ static int audio_element_obu(void *s, IAMFContext *c, AVIOContext *pb, int len) ret = AVERROR_INVALIDDATA; goto fail; } - ret = param_parse(s, c, pbc, type, audio_element, &element->demixing_info); + ret = param_parse(s, c, pbc, type, + audio_element, codec_config, + &element->demixing_info); } else if (type == AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) { if (element->recon_gain_info) { ret = AVERROR_INVALIDDATA; goto fail; } - ret = param_parse(s, c, pbc, type, audio_element, &element->recon_gain_info); + ret = param_parse(s, c, pbc, type, + audio_element, codec_config, + &element->recon_gain_info); } else { unsigned param_definition_size = ffio_read_leb(pbc); avio_skip(pbc, param_definition_size); @@ -960,6 +961,7 @@ static int label_string(AVIOContext *pb, char **label) static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int len) { AVIAMFMixPresentation *mix; + const IAMFCodecConfig *codec_config = NULL; IAMFMixPresentation **tmp, *mix_presentation = NULL; FFIOContext b; AVIOContext *pbc; @@ -1067,6 +1069,7 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le for (int j = 0; j < nb_elements; j++) { AVIAMFSubmixElement *submix_element; IAMFAudioElement *audio_element = NULL; + const IAMFCodecConfig *config = NULL; unsigned int rendering_config_extension_size; submix_element = av_iamf_submix_add_element(sub_mix); @@ -1089,6 +1092,7 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le ret = AVERROR_INVALIDDATA; goto fail; } + config = ff_iamf_get_codec_config(c, audio_element->codec_config_id); for (int k = 0; k < mix_presentation->count_label; k++) { char *annotation = NULL; @@ -1107,14 +1111,22 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le avio_skip(pbc, rendering_config_extension_size); ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, - audio_element, + audio_element, config, &submix_element->element_mix_config); if (ret < 0) goto fail; submix_element->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8); + + if (!codec_config || (config->nb_samples > + av_rescale(codec_config->nb_samples, + codec_config->sample_rate, + config->sample_rate))) + codec_config = config; } - ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, NULL, &sub_mix->output_mix_config); + ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, + NULL, codec_config, + &sub_mix->output_mix_config); if (ret < 0) goto fail; sub_mix->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);