diff mbox series

[FFmpeg-devel,11/21] avfilter/af_amix: Fix double-free of AVFilterChannelLayouts on error

Message ID 20200809155748.30092-5-andreas.rheinhardt@gmail.com
State Accepted
Commit 44e376500fd0a5e6b9ca1611e645feeb50de1ac5
Headers show
Series [FFmpeg-devel,1/6] avfilter/formats: Remove ff_make_formatu64_list() | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Andreas Rheinhardt Aug. 9, 2020, 3:57 p.m. UTC
The query_formats function of the amix filter tries to allocate a list
of channel layouts which are attached to more permanent objects
(an AVFilter's links) for storage afterwards on success. If attaching
a list to a link succeeds, the link becomes one of the common owners
of the list. Yet if a list has been successfully attached to links (or if
there were no links to attach it to in which case
ff_set_common_channel_layouts() already frees the list) and an error
happens lateron, the list was manually freed, which is wrong, because
the list has either already been freed or it is owned by its links in
which case these links' pointers to their list will become dangling and
there will be double-frees/uses-after-free when these links are cleaned
up automatically.

This commit fixes this by removing the custom freeing code; this is made
possible by using the list in ff_set_common_channel_layouts() directly
after its allocation (without anything that can fail in between).

Notice that ff_set_common_channel_layouts() is buggy itself which can
lead to double-frees on error. This is not fixed in this commit.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavfilter/af_amix.c | 18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index 6a4ef8d944..cae9d4585a 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -593,25 +593,13 @@  static int query_formats(AVFilterContext *ctx)
         AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
         AV_SAMPLE_FMT_NONE
     };
-    AVFilterChannelLayouts *layouts;
     int ret;
 
-    layouts = ff_all_channel_counts();
-    if (!layouts) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
     if ((ret = ff_set_common_formats(ctx, ff_make_format_list(sample_fmts))) < 0 ||
-        (ret = ff_set_common_channel_layouts(ctx, layouts))          < 0 ||
         (ret = ff_set_common_samplerates(ctx, ff_all_samplerates())) < 0)
-        goto fail;
-    return 0;
-fail:
-    if (layouts)
-        av_freep(&layouts->channel_layouts);
-    av_freep(&layouts);
-    return ret;
+        return ret;
+
+    return ff_set_common_channel_layouts(ctx, ff_all_channel_counts());
 }
 
 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,