CVE-2013-7011: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: The read_header function in libavcodec/ffv1dec.c in FFmpeg before 2.1 does not prevent changes to global parameters, which allows remote attackers to cause a denial of service (out-of-bounds array access) or possibly have unspecified other impact via crafted FFV1 data.
CWE description: 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.
Published: 2013-12-09T16:36Z
Repository: https://github.com/FFmpeg/FFmpeg
Language: C
Files changed: libavcodec/ffv1dec.c
Commit date: 2013-08-30 05:27:51 +0200
Commit message: ffv1dec: check that global parameters dont change in version 0/1

Such changes are not allowed nor supported

Fixes Ticket2906

Found-by: ami_stuff
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Diff: diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 76cbee7f23b..3081207a049 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -578,10 +578,11 @@ static int read_header(FFV1Context *f)
     RangeCoder *const c = &f->slice_context[0]->c;
 
     memset(state, 128, sizeof(state));
 
     if (f->version < 2) {
+        int chroma_planes, chroma_h_shift, chroma_v_shift, transparency;
         unsigned v= get_symbol(c, state, 0);
         if (v >= 2) {
             av_log(f->avctx, AV_LOG_ERROR, "invalid version %d in ver01 header\n", v);
             return AVERROR_INVALIDDATA;
         }
@@ -595,14 +596,30 @@ static int read_header(FFV1Context *f)
         f->colorspace = get_symbol(c, state, 0); //YUV cs type
 
         if (f->version > 0)
             f->avctx->bits_per_raw_sample = get_symbol(c, state, 0);
 
-        f->chroma_planes  = get_rac(c, state);
-        f->chroma_h_shift = get_symbol(c, state, 0);
-        f->chroma_v_shift = get_symbol(c, state, 0);
-        f->transparency   = get_rac(c, state);
+        chroma_planes  = get_rac(c, state);
+        chroma_h_shift = get_symbol(c, state, 0);
+        chroma_v_shift = get_symbol(c, state, 0);
+        transparency   = get_rac(c, state);
+
+        if (f->plane_count) {
+            if (   chroma_planes != f->chroma_planes
+                || chroma_h_shift!= f->chroma_h_shift
+                || chroma_v_shift!= f->chroma_v_shift
+                || transparency  != f->transparency) {
+                av_log(f->avctx, AV_LOG_ERROR, "Invalid change of global parameters\n");
+                return AVERROR_INVALIDDATA;
+            }
+        }
+
+        f->chroma_planes  = chroma_planes;
+        f->chroma_h_shift = chroma_h_shift;
+        f->chroma_v_shift = chroma_v_shift;
+        f->transparency   = transparency;
+
         f->plane_count    = 2 + f->transparency;
     }
 
     if (f->colorspace == 0) {
         if (!f->transparency && !f->chroma_planes) {

Vulnerable code:         f->chroma_planes  = get_rac(c, state);
        f->chroma_h_shift = get_symbol(c, state, 0);
        f->chroma_v_shift = get_symbol(c, state, 0);
        f->transparency   = get_rac(c, state);
Fixed code:         int chroma_planes, chroma_h_shift, chroma_v_shift, transparency;
        chroma_planes  = get_rac(c, state);
        chroma_h_shift = get_symbol(c, state, 0);
        chroma_v_shift = get_symbol(c, state, 0);
        transparency   = get_rac(c, state);

        if (f->plane_count) {
            if (   chroma_planes != f->chroma_planes
                || chroma_h_shift!= f->chroma_h_shift
                || chroma_v_shift!= f->chroma_v_shift
                || transparency  != f->transparency) {
                av_log(f->avctx, AV_LOG_ERROR, "Invalid change of global parameters\n");
                return AVERROR_INVALIDDATA;
            }
        }

        f->chroma_planes  = chroma_planes;
        f->chroma_h_shift = chroma_h_shift;
        f->chroma_v_shift = chroma_v_shift;
        f->transparency   = transparency;