Commit bd653acbf5 for ffmpeg

commit bd653acbf518452f2c4228e2da5946f26e004d85
Author: Niklas Haas <git@haasn.dev>
Date:   Fri Sep 4 17:31:52 2026 +0200

    avformat/libcurl: harden Content-Range parsing

    Reject out-of-range values, non-numeric leading characters (e.g. extra
    whitespace), and extra unexpected bytes; which the previous code
    implicitly skipped over by way of using strchr() to find delimiters.

    Signed-off-by: Niklas Haas <git@haasn.dev>

diff --git a/libavformat/libcurl.c b/libavformat/libcurl.c
index 183eeb9709..d8dc44d652 100644
--- a/libavformat/libcurl.c
+++ b/libavformat/libcurl.c
@@ -22,6 +22,7 @@
 #include "config_components.h"

 #include <curl/curl.h>
+#include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdlib.h>
@@ -256,31 +257,55 @@ static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdat
     return bytes;
 }

-static int64_t parse_offset(const char *s)
+/* Return 1 if an offset was successfully parsed, 0 otherwise */
+static int parse_offset(const char *str, int64_t *out, const char **ptr)
 {
-    int64_t v = strtoll(s, NULL, 10);
-    return v < 0 ? -1 : v;
+    if (!av_isdigit(str[0]))
+        return 0;
+
+    errno = 0;
+    char *end;
+    int64_t val = strtoll(str, &end, 10);
+    if (errno == ERANGE)
+        return 0;
+
+    *out = val;
+    *ptr = end;
+    return 1;
 }

 /* "bytes $from-$to/$document_size" */
 static void parse_content_range(CurlContext *c, const char *v)
 {
+    int64_t start = -1, end = -1, total = -1;
     while (av_isspace(*v))
         v++;

-    if (av_strncasecmp(v, "bytes ", 6))
+    if (!av_stristart(v, "bytes ", &v))
         return;

-    const char *range = v + 6, *end;
-    if (range[0] != '*') {
-        c->hdr_content_start = parse_offset(range);
-        if ((end = strchr(range, '-')))
-            c->hdr_content_end = parse_offset(end + 1);
+    if (!av_strstart(v, "*", &v)) {
+        if (!parse_offset(v, &start, &v) ||
+            !av_strstart(v, "-", &v) ||
+            !parse_offset(v, &end, &v))
+            return;
     }

-    const char *slash = strchr(range, '/');
-    if (slash && slash[1] != '*')
-        c->hdr_content_total = parse_offset(slash + 1);
+    if (!av_strstart(v, "/", &v))
+        return;
+    if (!av_strstart(v, "*", &v) && !parse_offset(v, &total, &v))
+        return;
+
+    while (av_isspace(*v))
+        v++;
+
+    if (v[0] || (total < 0 && start < 0))
+        return; // reject trailing bytes or "*/*"
+
+    /* only set these fields if the header was recognized; ignore otherwise */
+    c->hdr_content_start = start;
+    c->hdr_content_end   = end;
+    c->hdr_content_total = total;
 }

 /* Parse a decimal header value, bounded by len since curl does not promise a