PR #23477 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23477
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23477.patch

Hopefully resolving some of the issues seen recently.


>From 569fd55649a944d2b1147eb892f0f9da75b0a1ee Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 14 Jun 2026 12:27:58 +0200
Subject: [PATCH 1/5] avformat/http: properly re-set s->range_end before
 requests

Otherwise this could leak stale values from a previous response.

Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <[email protected]>
---
 libavformat/http.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index e0cf9e7424..a0d84e5b09 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -567,6 +567,7 @@ int ff_http_do_new_request2(URLContext *h, const char *uri, 
AVDictionary **opts)
 
     s->end_chunked_post = 0;
     s->chunkend      = 0;
+    s->range_end     = 0;
     s->off           = 0;
     s->icy_data_read = 0;
 
@@ -1663,6 +1664,7 @@ static int http_connect(URLContext *h, const char *path, 
const char *local_path,
     s->off              = 0;
     s->icy_data_read    = 0;
     s->filesize         = UINT64_MAX;
+    s->range_end        = 0;
     s->willclose        = 0;
     s->end_chunked_post = 0;
     s->end_header       = 0;
-- 
2.52.0


>From 5ddb7fe915e4c5085081659104beb70f5779c97e Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 14 Jun 2026 12:34:34 +0200
Subject: [PATCH 2/5] avformat/http: make short-seek logic more robust

This avoids an underflow if short_seek is negative, as well as a possible
underflow if the read position is somehow past range_end (e.g. if the HTTP
server malicously lied about the content range but gave us more bytes anyway)

Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <[email protected]>
---
 libavformat/http.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index a0d84e5b09..e0dac4f8f8 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -2143,8 +2143,14 @@ static int64_t http_seek_internal(URLContext *h, int64_t 
off, int whence, int fo
     memcpy(old_buf, s->buf_ptr, old_buf_size);
 
     /* try to reuse existing connection for small seeks */
-    uint64_t remaining = s->range_end - old_off - old_buf_size;
-    if (s->hd && !s->willclose && s->range_end && remaining <= 
ffurl_get_short_seek(h)) {
+    int short_seek = ffurl_get_short_seek(h);
+    uint64_t old_read_pos = old_off + old_buf_size;
+    if (s->hd && !s->willclose && s->range_end && short_seek > 0 &&
+        old_read_pos + short_seek >= s->range_end)
+    {
+        uint64_t remaining = s->range_end - old_read_pos;
+        av_assert1(remaining <= short_seek);
+
         /* drain remaining data left on the wire from previous request */
         av_log(h, AV_LOG_DEBUG, "Soft-seeking to offset %"PRIu64" by draining "
                "%"PRIu64" remaining byte(s)\n", s->off, remaining);
-- 
2.52.0


>From e06a89629e212726a49f6dc2152b6370d49c8671 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 14 Jun 2026 12:53:36 +0200
Subject: [PATCH 3/5] avformat/http: don't return EOF unless we actually read
 all bytes

Otherwise, this masquerades failure due to I/O as legitimate EOFs.

Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <[email protected]>
---
 libavformat/http.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index e0dac4f8f8..30748bb28d 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -1834,7 +1834,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, 
int size)
     int conn_attempts = 1;
 
     if (!s->hd)
-        return AVERROR_EOF;
+        return s->off < s->filesize ? AVERROR(EIO) : AVERROR_EOF;
 
     if (s->end_chunked_post && !s->end_header) {
         err = http_read_header(h);
-- 
2.52.0


>From 56eb5f53a29edafbf03cc1f4f86467c19ba2f1cf Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 14 Jun 2026 13:02:55 +0200
Subject: [PATCH 4/5] avformat/http: only re-use old connection if valid

Otherwise, this might leak stale bytes that were already drained by the
HTTP soft-seek attempt.

Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <[email protected]>
---
 libavformat/http.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 30748bb28d..ce98c01ae4 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -2169,14 +2169,16 @@ static int64_t http_seek_internal(URLContext *h, 
int64_t off, int whence, int fo
         s->hd = NULL;
     }
 
-    /* if it fails, continue on old connection */
     if ((ret = http_open_cnx(h, &options)) < 0) {
+        /* if it fails, continue on old connection if possible */
+        if (old_hd) {
+            memcpy(s->buffer, old_buf, old_buf_size);
+            s->buf_ptr = s->buffer;
+            s->buf_end = s->buffer + old_buf_size;
+            s->hd      = old_hd;
+            s->off     = old_off;
+        }
         av_dict_free(&options);
-        memcpy(s->buffer, old_buf, old_buf_size);
-        s->buf_ptr = s->buffer;
-        s->buf_end = s->buffer + old_buf_size;
-        s->hd      = old_hd;
-        s->off     = old_off;
         return ret;
     }
     av_dict_free(&options);
-- 
2.52.0


>From 640164fd2d1860694f28654bf6db08e3edee4327 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 14 Jun 2026 13:03:34 +0200
Subject: [PATCH 5/5] avformat/http: properly fall back on soft seek failure

If the HTTP server still has stale bytes in the TCP receive buffer, but
the underlying conection was already closed, then the http_open_cnx()
call might fail even though we successfully drained the previous request.

In this case, there is no proper fallback to a new connection, leading to
sudden truncation.

Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <[email protected]>
---
 libavformat/http.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index ce98c01ae4..28158db491 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -2163,6 +2163,13 @@ static int64_t http_seek_internal(URLContext *h, int64_t 
off, int whence, int fo
             }
             remaining -= ret;
         }
+
+        ret = http_open_cnx(h, &options);
+        if (ret < 0) {
+            /* fall back to normal reconnection */
+            ffurl_closep(&s->hd);
+            old_hd = NULL;
+        }
     } else {
         /* can't soft seek; always open new connection */
         old_hd = s->hd;
-- 
2.52.0

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

Reply via email to