PR #23350 opened by Kery
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23350
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23350.patch

Release dynamic AVIO buffers before returning from IAMF writer
error paths after avio_open_dyn_buf() succeeds.

Fixes leaks in iamf_write_mixing_presentation() and
write_parameter_block() error handling.

Found-by: Kery
Signed-off-by: Kery <[email protected]>

# Summary of changes

Briefly describe what this PR does and why.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



>From 5d0a32dfe7a31076387a9e6aedf8895f8d6ff9da Mon Sep 17 00:00:00 2001
From: Kery <[email protected]>
Date: Fri, 5 Jun 2026 05:58:55 +0800
Subject: [PATCH] avformat/iamf_writer: free dynamic buffers on errors

Release dynamic AVIO buffers before returning from IAMF writer
error paths after avio_open_dyn_buf() succeeds.

Fixes leaks in iamf_write_mixing_presentation() and
write_parameter_block() error handling.

Found-by: Kery
Signed-off-by: Kery <[email protected]>
---
 libavformat/iamf_writer.c | 52 +++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 16 deletions(-)

diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c
index 3014f0daa1..4368900971 100644
--- a/libavformat/iamf_writer.c
+++ b/libavformat/iamf_writer.c
@@ -517,9 +517,9 @@ static int iamf_write_codec_config(const IAMFContext *iamf,
     AVIOContext *dyn_bc;
     uint8_t *dyn_buf = NULL;
     PutBitContext pbc;
-    int dyn_size;
+    int dyn_size, ret;
 
-    int ret = avio_open_dyn_buf(&dyn_bc);
+    ret = avio_open_dyn_buf(&dyn_bc);
     if (ret < 0)
         return ret;
 
@@ -534,7 +534,8 @@ static int iamf_write_codec_config(const IAMFContext *iamf,
         avio_write(dyn_bc, codec_config->extradata, 
codec_config->extradata_size);
         break;
     case AV_CODEC_ID_AAC:
-        return AVERROR_PATCHWELCOME;
+        ret = AVERROR_PATCHWELCOME;
+        goto fail;
     case AV_CODEC_ID_FLAC:
         avio_w8(dyn_bc, 0x80);
         avio_wb24(dyn_bc, codec_config->extradata_size);
@@ -586,6 +587,9 @@ static int iamf_write_codec_config(const IAMFContext *iamf,
     ffio_free_dyn_buf(&dyn_bc);
 
     return 0;
+fail:
+    ffio_free_dyn_buf(&dyn_bc);
+    return ret;
 }
 
 static inline int rescale_rational(AVRational q, int b)
@@ -784,7 +788,8 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
                 av_log(log_ctx, AV_LOG_ERROR, "expanded_loudspeaker_layout 
present when using more than one layer in "
                                               "Stream Group #%u\n",
                        audio_element->audio_element_id);
-                return AVERROR(EINVAL);
+                ret = AVERROR(EINVAL);
+                goto fail;
             }
         }
         /* When the loudspeaker_layout of the (non-)scalable channel audio 
(i.e., num_layers = 1) is less than or equal to 3.1.2ch,
@@ -806,7 +811,8 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
                 if (layout == 3 || layout == 4 || layout == 6 || layout == 7) {
                     av_log(log_ctx, AV_LOG_ERROR, "demixing_info needed but 
not set in Stream Group #%u\n",
                            audio_element->audio_element_id);
-                    return AVERROR(EINVAL);
+                    ret = AVERROR(EINVAL);
+                    goto fail;
                 }
             }
             param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
@@ -826,7 +832,7 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
         param_def = ff_iamf_get_param_definition(iamf, param->parameter_id);
         ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
         if (ret < 0)
-            return ret;
+            goto fail;
 
         avio_w8(dyn_bc, demix->dmixp_mode << 5); // dmixp_mode
         avio_w8(dyn_bc, element->default_w << 4); // default_w
@@ -838,24 +844,25 @@ static int iamf_write_audio_element(const IAMFContext 
*iamf,
         if (!param) {
             av_log(log_ctx, AV_LOG_ERROR, "recon_gain_info needed but not set 
in Stream Group #%u\n",
                    audio_element->audio_element_id);
-            return AVERROR(EINVAL);
+            ret = AVERROR(EINVAL);
+            goto fail;
         }
         ffio_write_leb(dyn_bc, AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN); // 
type
 
         param_def = ff_iamf_get_param_definition(iamf, param->parameter_id);
         ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
         if (ret < 0)
-            return ret;
+            goto fail;
     }
 
     if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
         ret = scalable_channel_layout_config(audio_element, dyn_bc);
         if (ret < 0)
-            return ret;
+            goto fail;
     } else {
         ret = ambisonics_config(audio_element, dyn_bc);
         if (ret < 0)
-            return ret;
+            goto fail;
     }
 
     init_put_bits(&pbc, header, sizeof(header));
@@ -870,6 +877,9 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
     ffio_free_dyn_buf(&dyn_bc);
 
     return 0;
+fail:
+    ffio_free_dyn_buf(&dyn_bc);
+    return ret;
 }
 
 static int iamf_write_mixing_presentation(const IAMFContext *iamf,
@@ -918,7 +928,8 @@ static int iamf_write_mixing_presentation(const IAMFContext 
*iamf,
             if (av_dict_count(submix_element->annotations) != 
av_dict_count(mix->annotations)) {
                 av_log(log_ctx, AV_LOG_ERROR, "Inconsistent amount of labels 
in submix %d from Mix Presentation id #%u\n",
                        j, audio_element->audio_element_id);
-                return AVERROR(EINVAL);
+                ret = AVERROR(EINVAL);
+                goto fail;
             }
             while ((tag = av_dict_iterate(submix_element->annotations, tag)))
                 avio_put_str(dyn_bc, tag->value);
@@ -933,7 +944,7 @@ static int iamf_write_mixing_presentation(const IAMFContext 
*iamf,
             param_def = ff_iamf_get_param_definition(iamf, 
submix_element->element_mix_config->parameter_id);
             ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
             if (ret < 0)
-                return ret;
+                goto fail;
 
             avio_wb16(dyn_bc, 
rescale_rational(submix_element->default_mix_gain, 1 << 8));
         }
@@ -941,7 +952,7 @@ static int iamf_write_mixing_presentation(const IAMFContext 
*iamf,
         param_def = ff_iamf_get_param_definition(iamf, 
sub_mix->output_mix_config->parameter_id);
         ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
         if (ret < 0)
-            return ret;
+            goto fail;
         avio_wb16(dyn_bc, rescale_rational(sub_mix->default_mix_gain, 1 << 8));
 
         ffio_write_leb(dyn_bc, sub_mix->nb_layouts); // nb_layouts
@@ -960,11 +971,13 @@ static int iamf_write_mixing_presentation(const 
IAMFContext *iamf,
                 }
                 if (layout == FF_ARRAY_ELEMS(ff_iamf_sound_system_map)) {
                     av_log(log_ctx, AV_LOG_ERROR, "Invalid Sound System value 
in a submix\n");
-                    return AVERROR(EINVAL);
+                    ret = AVERROR(EINVAL);
+                    goto fail;
                 }
             } else if (submix_layout->layout_type != 
AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL) {
                 av_log(log_ctx, AV_LOG_ERROR, "Unsupported Layout Type value 
in a submix\n");
-                return AVERROR(EINVAL);
+                ret = AVERROR(EINVAL);
+                goto fail;
             }
             init_put_bits(&pbc, header, sizeof(header));
             put_bits(&pbc, 2, submix_layout->layout_type); // layout_type
@@ -1009,6 +1022,9 @@ static int iamf_write_mixing_presentation(const 
IAMFContext *iamf,
     ffio_free_dyn_buf(&dyn_bc);
 
     return 0;
+fail:
+    ffio_free_dyn_buf(&dyn_bc);
+    return ret;
 }
 
 int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void 
*log_ctx)
@@ -1130,7 +1146,8 @@ static int write_parameter_block(const IAMFContext *iamf, 
AVIOContext *pb,
 
             if (!audio_element) {
                 av_log(log_ctx, AV_LOG_ERROR, "Invalid Parameter Definition 
with ID %u referenced by a packet\n", param->parameter_id);
-                return AVERROR(EINVAL);
+                ret = AVERROR(EINVAL);
+                goto fail;
             }
 
             for (int j = 0; j < audio_element->nb_layers; j++) {
@@ -1167,6 +1184,9 @@ static int write_parameter_block(const IAMFContext *iamf, 
AVIOContext *pb,
     ffio_free_dyn_buf(&dyn_bc);
 
     return 0;
+fail:
+    ffio_free_dyn_buf(&dyn_bc);
+    return ret;
 }
 
 int ff_iamf_write_parameter_blocks(const IAMFContext *iamf, AVIOContext *pb,
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to