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

Found during triage of the security report
Found-by: Joshua Rogers


>From a14b790ece0e722a64e35242721b8c9d62b220ea Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 6 Oct 2026 23:06:02 +0200
Subject: [PATCH 1/4] avformat/async: Make abort_request atomic

The inner protocol calls async_check_interrupt() from the worker thread
without the mutex, while async_close() sets abort_request from the
caller thread.

Fixes: data race
Fixes: SkXYbNIKP9pL
Data race Replicated through UnModified FFmpeg with TSAN
Found during triage of the security report sYm8PagSr0m4
---
 libavformat/async.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/libavformat/async.c b/libavformat/async.c
index 5831b12bd5..ab63cce5db 100644
--- a/libavformat/async.c
+++ b/libavformat/async.c
@@ -28,6 +28,7 @@
  */
 
 #include <inttypes.h>
+#include <stdatomic.h>
 #include <string.h>
 
 #include "libavutil/avassert.h"
@@ -78,7 +79,7 @@ typedef struct AsyncContext {
     pthread_mutex_t mutex;
     pthread_t       async_buffer_thread;
 
-    int             abort_request;
+    atomic_int      abort_request;
     AVIOInterruptCB interrupt_callback;
 } AsyncContext;
 
@@ -174,13 +175,13 @@ static int async_check_interrupt(void *arg)
     URLContext *h   = arg;
     AsyncContext *c = h->priv_data;
 
-    if (c->abort_request)
+    if (atomic_load(&c->abort_request))
         return 1;
 
     if (ff_check_interrupt(&c->interrupt_callback))
-        c->abort_request = 1;
+        atomic_store(&c->abort_request, 1);
 
-    return c->abort_request;
+    return atomic_load(&c->abort_request);
 }
 
 static void *async_buffer_task(void *arg)
@@ -256,6 +257,7 @@ static int async_open(URLContext *h, const char *arg, int 
flags, AVDictionary **
     AVIOInterruptCB  interrupt_callback = {.callback = async_check_interrupt, 
.opaque = h};
 
     av_strstart(arg, "async:", &arg);
+    atomic_init(&c->abort_request, 0);
 
     ret = ring_init(&c->ring, BUFFER_CAPACITY, READ_BACK_CAPACITY);
     if (ret < 0)
@@ -322,7 +324,7 @@ static int async_close(URLContext *h)
     int      ret;
 
     pthread_mutex_lock(&c->mutex);
-    c->abort_request = 1;
+    atomic_store(&c->abort_request, 1);
     pthread_cond_signal(&c->cond_wakeup_background);
     pthread_mutex_unlock(&c->mutex);
 
-- 
2.52.0


>From e4f769e5e932318ab9850cd32adb5cd8331b2e06 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 6 Oct 2026 23:17:37 +0200
Subject: [PATCH 2/4] fftools/ffmpeg_mux: Avoid signed overflow in the invalid
 DTS fix-up

Fixes: signed integer overflow
Fixes: YK9ibCaczocG
Fixes: C041.heic
Signed integer overflow Replicated through UnModified FFmpeg with UBSAN
Found during triage of the security report GL61hVKFlOuU
---
 fftools/ffmpeg_mux.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 9e7ebd3016..a6991afd87 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -166,9 +166,7 @@ static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket 
*pkt)
             av_log(ost, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: 
%"PRId64", replacing by guess\n",
                    pkt->dts, pkt->pts);
             pkt->pts =
-            pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1
-                     - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1)
-                     - FFMAX3(pkt->pts, pkt->dts, ms->last_mux_dts + 1);
+            pkt->dts = av_clip64(ms->last_mux_dts, pkt->pts - 1, pkt->dts - 1) 
+ 1;
         }
         if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == 
AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) &&
             pkt->dts != AV_NOPTS_VALUE &&
-- 
2.52.0


>From 7922d0b06801d1cc1cf01f61b0e17042aa74d801 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 6 Oct 2026 23:18:48 +0200
Subject: [PATCH 3/4] avutil/hwcontext: Fail with ENOSYS when a transfer
 callback is missing

This is not a security issue, FFmpeg itself does not create such frames,
only an API user setting such a hw_frames_ctx on a frame can.

Reported in AISLE-2026-0100-00080 (F7BbuzcmJjqW), not replicated as no
OpenHarmony or Android build was available.
Found-by: Joshua Rogers <[email protected]>
Suggested-by: Joshua Rogers <[email protected]>
---
 libavutil/hwcontext.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 83bd7457e8..c9e7d99f1d 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -478,8 +478,10 @@ int av_hwframe_transfer_data(AVFrame *dst, const AVFrame 
*src, int flags)
             return AVERROR(ENOSYS);
         }
 
-        ret = src_ctx->hw_type->transfer_data_from(&src_ctx->p, dst, src);
-        if (ret == AVERROR(ENOSYS))
+        ret = AVERROR(ENOSYS);
+        if (src_ctx->hw_type->transfer_data_from)
+            ret = src_ctx->hw_type->transfer_data_from(&src_ctx->p, dst, src);
+        if (ret == AVERROR(ENOSYS) && dst_ctx->hw_type->transfer_data_to)
             ret = dst_ctx->hw_type->transfer_data_to(&dst_ctx->p, dst, src);
         if (ret < 0)
             return ret;
@@ -487,12 +489,18 @@ int av_hwframe_transfer_data(AVFrame *dst, const AVFrame 
*src, int flags)
         if (src->hw_frames_ctx) {
             FFHWFramesContext *ctx = 
(FFHWFramesContext*)src->hw_frames_ctx->data;
 
+            if (!ctx->hw_type->transfer_data_from)
+                return AVERROR(ENOSYS);
+
             ret = ctx->hw_type->transfer_data_from(&ctx->p, dst, src);
             if (ret < 0)
                 return ret;
         } else if (dst->hw_frames_ctx) {
             FFHWFramesContext *ctx = 
(FFHWFramesContext*)dst->hw_frames_ctx->data;
 
+            if (!ctx->hw_type->transfer_data_to)
+                return AVERROR(ENOSYS);
+
             ret = ctx->hw_type->transfer_data_to(&ctx->p, dst, src);
             if (ret < 0)
                 return ret;
-- 
2.52.0


>From b4492fd7233360ef46fc0fe14bb320b233f5a67b Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Wed, 7 Oct 2026 00:04:31 +0200
Subject: [PATCH 4/4] avutil/des: Do not advance a NULL source pointer

av_des_crypt() and av_des_mac() accept a NULL src, but the loop still
added 8 to it for every block, which is undefined behavior.

Pointer arithmetic on NULL Replicated through UnModified FFmpeg with UBSAN
Found during triage of the security report f3cEzuDEDwTL
---
 libavutil/des.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavutil/des.c b/libavutil/des.c
index e0e9a86660..ea4f63b9b0 100644
--- a/libavutil/des.c
+++ b/libavutil/des.c
@@ -313,7 +313,8 @@ static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const 
uint8_t *src,
             iv_val = iv ? dst_val : 0;
         }
         AV_WB64(dst, dst_val);
-        src += 8;
+        if (src)
+            src += 8;
         if (!mac)
             dst += 8;
     }
-- 
2.52.0

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

Reply via email to