This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 1c2794eb2225948a29275bd2cc16108e966bd0a0
Author:     Julius Bairaktaris <[email protected]>
AuthorDate: Sun Aug 30 15:15:28 2026 +0200
Commit:     ArazIusubov <[email protected]>
CommitDate: Wed Sep 16 22:05:28 2026 +0000

    avfilter/amf: fix leaks and a NULL dereference in the filter frame path
    
    amf_filter_filter_frame() overwrote out->hw_frames_ctx with a second
    reference to the output frames context. av_hwframe_get_buffer(), called
    from amf_amfsurface_to_avframe() for every output, has already attached
    one, so each frame leaked a reference and the frames context never
    reached zero. Its AMF surface pool therefore survived filter teardown,
    which matters to anything that rebuilds a filter graph. vf_frc_amf.c had
    the same line.
    
    The function also takes ownership of the input frame but returned without
    freeing it on two paths, the QueryInterface() failure after QueryOutput()
    and the case with no output, and it passed the result of
    amf_amfsurface_to_avframe() to av_frame_copy_props() unchecked, so an
    allocation failure or an unsupported surface memory type dereferenced
    NULL. Route those through the existing fail label.
    
    amf_amfsurface_to_avframe() only takes ownership of the surface once it
    is attached to the frame, so its fail path and its frame allocation
    failure leaked the surface for both callers; release it in both, and
    check the av_buffer_create() that performs the attach.
    
    amf_setup_input_output_formats() leaked the input list when allocating
    the output list failed, and the output list when referencing the input
    list failed.
    
    Assisted-by: Claude Opus 5
    Signed-off-by: Julius Bairaktaris <[email protected]>
---
 libavfilter/vf_amf_common.c | 28 +++++++++++++++-------------
 libavfilter/vf_frc_amf.c    |  8 +-------
 2 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/libavfilter/vf_amf_common.c b/libavfilter/vf_amf_common.c
index f7cd680cbe..5700c6e2a4 100644
--- a/libavfilter/vf_amf_common.c
+++ b/libavfilter/vf_amf_common.c
@@ -143,12 +143,14 @@ int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame 
*in)
         AMFGuid guid = IID_AMFSurface();
         res = data_out->pVtbl->QueryInterface(data_out, &guid, 
(void**)&surface_out); // query for buffer interface
         data_out->pVtbl->Release(data_out);
-        AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
+        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
     } else {
-        return AVERROR(EAGAIN);
+        ret = AVERROR(EAGAIN);
+        goto fail;
     }
 
     out = amf_amfsurface_to_avframe(avctx, surface_out);
+    AMF_GOTO_FAIL_IF_FALSE(avctx, out != NULL, AVERROR(ENOMEM), "Failed to 
convert AMFSurface to AVFrame\n");
 
     ret = av_frame_copy_props(out, in);
     av_frame_unref(in);
@@ -197,12 +199,6 @@ int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame 
*in)
     if (ret < 0)
         goto fail;
 
-    out->hw_frames_ctx = av_buffer_ref(ctx->hwframes_out_ref);
-    if (!out->hw_frames_ctx) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
     av_frame_free(&in);
     return ff_filter_frame(outlink, out);
 fail:
@@ -266,15 +262,16 @@ int amf_setup_input_output_formats(AVFilterContext *avctx,
     }
     output_formats = ff_make_pixel_format_list(output_pix_fmts);
     if (!output_formats) {
+        ff_formats_unref(&input_formats);
         return AVERROR(ENOMEM);
     }
 
-    if ((err = ff_formats_ref(input_formats, 
&avctx->inputs[0]->outcfg.formats)) < 0)
+    if ((err = ff_formats_ref(input_formats, 
&avctx->inputs[0]->outcfg.formats)) < 0) {
+        ff_formats_unref(&output_formats);
         return err;
+    }
 
-    if ((err = ff_formats_ref(output_formats, 
&avctx->outputs[0]->incfg.formats)) < 0)
-        return err;
-    return 0;
+    return ff_formats_ref(output_formats, &avctx->outputs[0]->incfg.formats);
 }
 
 int amf_copy_surface(AVFilterContext *avctx, const AVFrame *frame,
@@ -427,8 +424,10 @@ AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, 
AMFSurface* pSurface)
     AVFrame *frame = av_frame_alloc();
     AMFFilterContext  *ctx = avctx->priv;
 
-    if (!frame)
+    if (!frame) {
+        pSurface->pVtbl->Release(pSurface);
         return NULL;
+    }
 
     if (ctx->hwframes_out_ref) {
         AVHWFramesContext *hwframes_out = (AVHWFramesContext 
*)ctx->hwframes_out_ref->data;
@@ -443,6 +442,8 @@ AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, 
AMFSurface* pSurface)
                                             amf_free_amfsurface,
                                             (void*)avctx,
                                             AV_BUFFER_FLAG_READONLY);
+            if (!frame->buf[1])
+                goto fail;
         } else { // FIXME: add processing of other hw formats
             av_log(ctx, AV_LOG_ERROR, "Unknown pixel format\n");
             goto fail;
@@ -491,6 +492,7 @@ AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, 
AMFSurface* pSurface)
 
     return frame;
 fail:
+    pSurface->pVtbl->Release(pSurface);
     av_frame_free(&frame);
     return NULL;
 }
diff --git a/libavfilter/vf_frc_amf.c b/libavfilter/vf_frc_amf.c
index f5ea93619b..1b914908a0 100644
--- a/libavfilter/vf_frc_amf.c
+++ b/libavfilter/vf_frc_amf.c
@@ -227,7 +227,7 @@ static int amf_frc_filter_avframe(AVFilterLink *inlink, 
AVFrame *in)
         res = AMF_IFACE_CALL(data_out, QueryInterface, &guid, 
(void**)&surface_out);
         AMF_IFACE_CALL(data_out, Release);
         data_out = NULL;
-        AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
+        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
 
         out = amf_amfsurface_to_avframe(avctx, surface_out);
         AMF_GOTO_FAIL_IF_FALSE(avctx, out != NULL, AVERROR(ENOMEM), "Failed to 
convert AMFSurface to AVFrame\n");
@@ -240,12 +240,6 @@ static int amf_frc_filter_avframe(AVFilterLink *inlink, 
AVFrame *in)
         if (frc_ctx->enable)
             out->duration /= 2;
 
-        out->hw_frames_ctx = av_buffer_ref(amf_ctx->hwframes_out_ref);
-        if (!out->hw_frames_ctx) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-
         ret = ff_filter_frame(outlink, out);
         out = NULL;
         if (ret < 0)

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to