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

Git pushed a commit to branch release/8.1
in repository ffmpeg.

commit 1c871a90bf75399f646674a382fc3b89f6724c0f
Author:     Michael Niedermayer <[email protected]>
AuthorDate: Thu May 21 21:59:01 2026 +0200
Commit:     Michael Niedermayer <[email protected]>
CommitDate: Sun Jun 14 04:40:55 2026 +0200

    avformat/dashdec: bound manifest reloads and fragment-open retries
    
    Mirror the HLS demuxer's max_reload pattern
    
    Reported as a DoS finding by Xueqing. Verified with the supplied PoC
    server: a 30s ffmpeg run that previously generated ~10000 requests
    without termination now exits in ~100ms after exactly max_reload
    fragment-open failures.
    
    (cherry picked from commit 4945e33e987ea17e4bc0571e3e5ffde606ac5961)
    Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/dashdec.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index afb63ba859..4bca53fd8f 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -109,6 +109,7 @@ struct representation {
     int64_t cur_seg_offset;
     int64_t cur_seg_size;
     struct fragment *cur_seg;
+    int n_open_failures;            /* consecutive open_input failures since 
last good read */
 
     /* Currently active Media Initialization Section */
     struct fragment *init_section;
@@ -153,6 +154,7 @@ typedef struct DASHContext {
     char *allowed_extensions;
     AVDictionary *avio_opts;
     int max_url_size;
+    int max_reload;
     char *cenc_decryption_key;
     char *cenc_decryption_keys;
 
@@ -1619,6 +1621,7 @@ static struct fragment *get_current_fragment(struct 
representation *pls)
     struct fragment *seg = NULL;
     struct fragment *seg_ptr = NULL;
     DASHContext *c = pls->parent->priv_data;
+    int reload_count = 0;
 
     while (( !ff_check_interrupt(c->interrupt_callback)&& pls->n_fragments > 
0)) {
         if (pls->cur_seq_no < pls->n_fragments) {
@@ -1636,6 +1639,12 @@ static struct fragment *get_current_fragment(struct 
representation *pls)
             seg->url_offset = seg_ptr->url_offset;
             return seg;
         } else if (c->is_live) {
+            if (reload_count++ >= c->max_reload) {
+                av_log(pls->parent, AV_LOG_ERROR,
+                       "Reached max manifest reloads (%d) at seq %"PRId64"\n",
+                       c->max_reload, pls->cur_seq_no);
+                return NULL;
+            }
             refresh_manifest(pls->parent);
         } else {
             break;
@@ -1826,9 +1835,17 @@ restart:
                 goto end;
             }
             av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of 
playlist\n");
+            if (++v->n_open_failures > c->max_reload) {
+                av_log(v->parent, AV_LOG_ERROR,
+                       "Reached max consecutive fragment open failures (%d), 
giving up\n",
+                       c->max_reload);
+                ret = AVERROR_EOF;
+                goto end;
+            }
             v->cur_seq_no++;
             goto restart;
         }
+        v->n_open_failures = 0;
     }
 
     if (v->init_sec_buf_read_offset < v->init_sec_data_len) {
@@ -2379,6 +2396,8 @@ static const AVOption dash_options[] = {
         INT_MIN, INT_MAX, FLAGS},
     { "cenc_decryption_key", "Media default decryption key (hex)", 
OFFSET(cenc_decryption_key), AV_OPT_TYPE_STRING, {.str = NULL}, INT_MIN, 
INT_MAX, .flags = FLAGS },
     { "cenc_decryption_keys", "Media decryption keys by KID (hex)", 
OFFSET(cenc_decryption_keys), AV_OPT_TYPE_STRING, {.str = NULL}, INT_MIN, 
INT_MAX, .flags = FLAGS },
+    { "max_reload", "Maximum number of manifest reloads in 
get_current_fragment() before giving up",
+        OFFSET(max_reload), AV_OPT_TYPE_INT, { .i64 = 100 }, 0, INT_MAX, FLAGS 
},
     {NULL}
 };
 

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

Reply via email to