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

### Description:

`ffurl_connect()` creates a temporary dictionary (tmp_opts) when the caller 
passes NULL for the options parameter (lines **211-212**):
``` c
if (!options)
    options = &tmp_opts;
```
The function then inserts `protocol_whitelist` and `protocol_blacklist` entries 
into this dictionary using `av_dict_set()`.

If one of these av_dict_set() calls fails after an entry has already been 
inserted, the function returns immediately without freeing the temporary 
dictionary (**239-242**). Since  `tmp_opts` is only used internally in this 
case, this may result in a memory leak on the error path.

### Fix:

Redirect error paths to a cleanup section and free tmp_opts when it is created 
internally. The fix is included in this commit.


>From c809d8435efac88c88a4f7c8b26aa9459eb4e712 Mon Sep 17 00:00:00 2001
From: huanghuihui0904 <[email protected]>
Date: Mon, 16 Mar 2026 17:07:48 +0800
Subject: [PATCH] avformat: avoid potential tmp_opts leak in ffurl_connect()

When options is NULL, ffurl_connect() creates a temporary dictionary 
(tmp_opts). If av_dict_set() fails after inserting entries, the function may 
return without freeing this dictionary.

Ensure tmp_opts is freed on error paths.

Signed-off-by: Huihui_Huang <[email protected]>
---
 libavformat/avio.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/libavformat/avio.c b/libavformat/avio.c
index c685e0ab71..3d723c1c09 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -237,9 +237,9 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
         av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should 
be an error once all declare a default whitelist
 
     if ((err = av_dict_set(options, "protocol_whitelist", 
uc->protocol_whitelist, 0)) < 0)
-        return err;
+        goto fail;
     if ((err = av_dict_set(options, "protocol_blacklist", 
uc->protocol_blacklist, 0)) < 0)
-        return err;
+        goto fail;
 
     err =
         uc->prot->url_open2 ? uc->prot->url_open2(uc,
@@ -252,14 +252,23 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
     av_dict_set(options, "protocol_blacklist", NULL, 0);
 
     if (err)
-        return err;
+        goto fail;
     uc->is_connected = 1;
     /* We must be careful here as ffurl_seek() could be slow,
      * for example for http */
     if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))
         if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)
             uc->is_streamed = 1;
+
+    if (options == &tmp_opts)
+        av_dict_free(&tmp_opts);
+
     return 0;
+
+fail:
+    if (options == &tmp_opts)
+        av_dict_free(&tmp_opts);
+    return err;    
 }
 
 int ffurl_accept(URLContext *s, URLContext **c)
-- 
2.52.0

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

Reply via email to