CVE-2016-10190 (C, published 2017-02-09T15:59Z)
Description: value: Heap-based buffer overflow in libavformat/http.c in FFmpeg before 2.8.10, 3.0.x before 3.0.5, 3.1.x before 3.1.6, and 3.2.x before 3.2.2 allows remote web servers to execute arbitrary code via a negative chunk size in an HTTP response.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-119 \u2014 Improper Restriction of Operations within the Bounds of a Memory Buffer
The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
Repository: https://github.com/FFmpeg/FFmpeg
Files changed:
libavformat/http.c
Commit message: http: make length/offset-related variables unsigned.

Fixes #5992, reported and found by Paul Cher <paulcher@icloud.com>.


Vulnerable code:
    int64_t chunksize;
    int64_t off, end_off, filesize;
    int icy_data_read;
    int icy_metaint;
    s->filesize = -1;
        s->off = strtoll(p, NULL, 10);
            s->filesize = strtoll(slash + 1, NULL, 10);
        } else if (!av_strcasecmp(tag, "Content-Length") && s->filesize == -1) {
            s->filesize = strtoll(p, NULL, 10);
            s->filesize  = -1;
            s->icy_metaint = strtoll(p, NULL, 10);
    s->chunksize = -1;
    int64_t off = s->off;
                           "Range: bytes=%"PRId64"-", s->off);
    s->filesize         = -1;
        int64_t target_end = s->end_off ? s->end_off : s->filesize;
        if ((!s->willclose || s->chunksize < 0) &&
            target_end >= 0 && s->off >= target_end)
        if (!len && (!s->willclose || s->chunksize < 0) &&
            target_end >= 0 && s->off < target_end) {
                   "Stream ends prematurely at %"PRId64", should be %"PRId64"\n",
    if (s->chunksize >= 0) {
                s->chunksize = strtoll(line, NULL, 16);
                av_log(NULL, AV_LOG_TRACE, "Chunked encoding data size: %"PRId64"'\n",
        int64_t target = h->is_streamed ? 0 : s->off;
        av_log(h, AV_LOG_INFO, "Will reconnect at %"PRId64" error=%s.\n", s->off, av_err2str(read_ret));
            av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRId64".\n", target);
    int remaining = s->icy_metaint - s->icy_data_read;
    if (remaining < 0)
    int64_t old_off = s->off;
    else if ((s->filesize == -1 && whence == SEEK_END))
    s->filesize   = -1;

Fixed code:
    uint64_t chunksize;
    uint64_t off, end_off, filesize;
    uint64_t icy_data_read;
    uint64_t icy_metaint;
    s->filesize = UINT64_MAX;
        s->off = strtoull(p, NULL, 10);
            s->filesize = strtoull(slash + 1, NULL, 10);
        } else if (!av_strcasecmp(tag, "Content-Length") &&
                   s->filesize == UINT64_MAX) {
            s->filesize = strtoull(p, NULL, 10);
            s->filesize  = UINT64_MAX;
            s->icy_metaint = strtoull(p, NULL, 10);
    s->chunksize = UINT64_MAX;
    uint64_t off = s->off;
                           "Range: bytes=%"PRIu64"-", s->off);
    s->filesize         = UINT64_MAX;
        uint64_t target_end = s->end_off ? s->end_off : s->filesize;
        if ((!s->willclose || s->chunksize == UINT64_MAX) && s->off >= target_end)
        if (!len && (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) {
                   "Stream ends prematurely at %"PRIu64", should be %"PRIu64"\n",
    if (s->chunksize != UINT64_MAX) {
                s->chunksize = strtoull(line, NULL, 16);
                av_log(h, AV_LOG_TRACE,
                       "Chunked encoding data size: %"PRIu64"'\n",
                else if (s->chunksize == UINT64_MAX) {
                    av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n",
                           s->chunksize);
                    return AVERROR(EINVAL);
                }
        uint64_t target = h->is_streamed ? 0 : s->off;
        av_log(h, AV_LOG_INFO, "Will reconnect at %"PRIu64" error=%s.\n", s->off, av_err2str(read_ret));
            av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target);
    uint64_t remaining;
    if (s->icy_metaint < s->icy_data_read)
    remaining = s->icy_metaint - s->icy_data_read;
    uint64_t old_off = s->off;
    else if ((s->filesize == UINT64_MAX && whence == SEEK_END))
    s->filesize   = UINT64_MAX;