PR #24691 opened by ArthurVasseur-Kyber
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24691
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24691.patch

`av_hwframe_map()` decides whether a call is really an "unmap" of a prior 
mapping purely by comparing src/dst `hw_frames_ctx` and formats. That heuristic 
doesn't verify `src->buf[0]` was actually produced by a prior 
`ff_hwframe_map_create()` call - only that the formats happen to line up. This 
misfires for callers that attach their own `hw_frames_ctx` to an 
independently-allocated software frame before calling `av_hwframe_map()` (e.g. 
`vf_hwmap`'s reverse mode does this unconditionally, with no check that the 
frame came from its own `get_buffer` hook). When it misfires, 
`src->buf[0]->data` is read as a `HWMapDescriptor*` and dereferenced, but it's 
actually plain pixel data  a wild pointer read that crashes.

This tightens the check: `src->buf[0]`'s underlying `AVBuffer` must have been 
created by `ff_hwframe_map_create()` (identified by its `free` callback) before 
it's trusted as a `HWMapDescriptor`. Otherwise it falls through to the normal 
`map_from`/`map_to` path.

**Note this hardens `av_hwframe_map()` defensively but doesn't fix the actual 
misuse in `vf_hwmap.c` (it still attaches a `hw_frames_ctx` to frames it 
doesn't own) filing that separately since it needs a proper design decision, 
not just a crash guard.**



>From 562171f28d2f0702b73bfe16ddeed026953b997f Mon Sep 17 00:00:00 2001
From: Arthur Vasseur <[email protected]>
Date: Wed, 9 Sep 2026 00:00:00 +0000
Subject: [PATCH] avutil/hwcontext: fix bogus unmap detection in av_hwframe_map

av_hwframe_map() treats a call as an "unmap" purely by matching
src/dst hw_frames_ctx and pixel formats, without checking that
src->buf[0] actually came from ff_hwframe_map_create(). A caller that
attaches its own hw_frames_ctx to an independently allocated frame
(e.g. vf_hwmap's reverse mode) can satisfy that match by coincidence,
so src->buf[0]->data gets misread as a HWMapDescriptor* and
dereferenced as garbage - crashes with an XCB capture through
"hwmap,scale_vaapi=format=nv12" on VAAPI/Intel Arc. Require
src->buf[0]'s AVBuffer to actually be one before trusting it, or fall
through to the normal map_from/map_to path.

Signed-off-by: Arthur Vasseur <[email protected]>
---
 libavutil/hwcontext.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 83bd7457e8..61fc067ca6 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -20,6 +20,7 @@
 
 #include "avassert.h"
 #include "buffer.h"
+#include "buffer_internal.h"
 #include "common.h"
 #include "hwcontext.h"
 #include "hwcontext_internal.h"
@@ -807,17 +808,25 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int 
flags)
             (src_frames->source_frames &&
              src_frames->source_frames->data ==
              (uint8_t*)dst_frames)) {
-            // This is an unmap operation.  We don't need to directly
-            // do anything here other than fill in the original frame,
-            // because the real unmap will be invoked when the last
-            // reference to the mapped frame disappears.
+            // This looks like an unmap, but that alone doesn't prove src
+            // came from a prior av_hwframe_map() call - a plain frame
+            // that merely has dst's hw_frames_ctx/sw_format attached
+            // (e.g. by vf_hwmap's reverse mode) matches the same
+            // condition. Require src->buf[0] to have actually been
+            // created by ff_hwframe_map_create() before trusting it.
             if (!src->buf[0]) {
                 av_log(src_frames, AV_LOG_ERROR, "Invalid mapping "
                        "found when attempting unmap.\n");
                 return AVERROR(EINVAL);
             }
-            hwmap = (HWMapDescriptor*)src->buf[0]->data;
-            return av_frame_replace(dst, hwmap->source);
+            if (src->buf[0]->buffer->free == &ff_hwframe_unmap) {
+                // This is an unmap operation.  We don't need to directly
+                // do anything here other than fill in the original frame,
+                // because the real unmap will be invoked when the last
+                // reference to the mapped frame disappears.
+                hwmap = (HWMapDescriptor*)src->buf[0]->data;
+                return av_frame_replace(dst, hwmap->source);
+            }
         }
     }
 
-- 
2.52.0

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

Reply via email to