CVE-2013-4263: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: libavfilter in FFmpeg before 2.0.1 has unspecified impact and remote vectors related to a crafted "plane," which triggers an out-of-bounds heap write.
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-11-23T17:55Z
Repository: https://github.com/FFmpeg/FFmpeg
Language: C
Files changed: libavfilter/vf_boxblur.c, libavfilter/vf_delogo.c, libavfilter/vf_fieldmatch.c, libavfilter/vf_fieldorder.c, libavfilter/vf_gradfun.c, libavfilter/vf_hflip.c, libavfilter/vf_kerndeint.c, libavfilter/vf_lut.c, libavfilter/vf_pad.c, libavfilter/vf_showinfo.c, libavfilter/vf_vignette.c
Commit date: 2013-08-03 19:15:46 +0200
Commit message: avfilter: fix plane validity checks

Fixes out of array accesses

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

Diff: diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c
index 8a59890452..bf4c42e674 100644
--- a/libavfilter/vf_boxblur.c
+++ b/libavfilter/vf_boxblur.c
@@ -311,17 +311,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         av_frame_free(&in);
         return AVERROR(ENOMEM);
     }
     av_frame_copy_props(out, in);
 
-    for (plane = 0; in->data[plane] && plane < 4; plane++)
+    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++)
         hblur(out->data[plane], out->linesize[plane],
               in ->data[plane], in ->linesize[plane],
               w[plane], h[plane], s->radius[plane], s->power[plane],
               s->temp);
 
-    for (plane = 0; in->data[plane] && plane < 4; plane++)
+    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++)
         vblur(out->data[plane], out->linesize[plane],
               out->data[plane], out->linesize[plane],
               w[plane], h[plane], s->radius[plane], s->power[plane],
               s->temp);
 
diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index 45a29cf00c..971e98670a 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -235,11 +235,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     sar = in->sample_aspect_ratio;
     /* Assume square pixels if SAR is unknown */
     if (!sar.num)
         sar.num = sar.den = 1;
 
-    for (plane = 0; plane < 4 && in->data[plane]; plane++) {
+    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
         int hsub = plane == 1 || plane == 2 ? hsub0 : 0;
         int vsub = plane == 1 || plane == 2 ? vsub0 : 0;
 
         apply_delogo(out->data[plane], out->linesize[plane],
                      in ->data[plane], in ->linesize[plane],
diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
index 3a6f806a8b..89c4909a3d 100644
--- a/libavfilter/vf_fieldmatch.c
+++ b/libavfilter/vf_fieldmatch.c
@@ -606,11 +606,11 @@ static int compare_fields(FieldMatchContext *fm, int match1, int match2, int fie
 
 static void copy_fields(const FieldMatchContext *fm, AVFrame *dst,
                         const AVFrame *src, int field)
 {
     int plane;
-    for (plane = 0; plane < 4 && src->data[plane]; plane++)
+    for (plane = 0; plane < 4 && src->data[plane] && src->linesize[plane]; plane++)
         av_image_copy_plane(dst->data[plane] + field*dst->linesize[plane], dst->linesize[plane] << 1,
                             src->data[plane] + field*src->linesize[plane], src->linesize[plane] << 1,
                             get_width(fm, src, plane), get_height(fm, src, plane) / 2);
 }
 
diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c
index 3a19500c13..7ff88418b4 100644
--- a/libavfilter/vf_fieldorder.c
+++ b/libavfilter/vf_fieldorder.c
@@ -104,11 +104,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
 
     av_dlog(ctx,
             "picture will move %s one line\n",
             s->dst_tff ? "up" : "down");
     h = frame->height;
-    for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
+    for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
         line_step = frame->linesize[plane];
         line_size = s->line_size[plane];
         data = frame->data[plane];
         if (s->dst_tff) {
             /** Move every line up one line, working from
diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c
index e615e1e592..b2e700742f 100644
--- a/libavfilter/vf_gradfun.c
+++ b/libavfilter/vf_gradfun.c
@@ -197,11 +197,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             return AVERROR(ENOMEM);
         }
         av_frame_copy_props(out, in);
     }
 
-    for (p = 0; p < 4 && in->data[p]; p++) {
+    for (p = 0; p < 4 && in->data[p] && in->linesize[p]; p++) {
         int w = inlink->w;
         int h = inlink->h;
         int r = s->radius;
         if (p) {
             w = s->chroma_w;
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index 7fc135fdfc..0a9bc2cc66 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -88,11 +88,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
     /* copy palette if required */
     if (av_pix_fmt_desc_get(inlink->format)->flags & AV_PIX_FMT_FLAG_PAL)
         memcpy(out->data[1], in->data[1], AVPALETTE_SIZE);
 
-    for (plane = 0; plane < 4 && in->data[plane]; plane++) {
+    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
         const int width  = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->w, s->hsub) : inlink->w;
         const int height = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, s->vsub) : inlink->h;
         step = s->max_step[plane];
 
         outrow = out->data[plane];
diff --git a/libavfilter/vf_kerndeint.c b/libavfilter/vf_kerndeint.c
index 5f99d88c2b..5f81525527 100644
--- a/libavfilter/vf_kerndeint.c
+++ b/libavfilter/vf_kerndeint.c
@@ -148,11 +148,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
         return AVERROR(ENOMEM);
     }
     av_frame_copy_props(outpic, inpic);
     outpic->interlaced_frame = 0;
 
-    for (plane = 0; inpic->data[plane] && plane < 4; plane++) {
+    for (plane = 0; plane < 4 && inpic->data[plane] && inpic->linesize[plane]; plane++) {
         h = plane == 0 ? inlink->h : FF_CEIL_RSHIFT(inlink->h, kerndeint->vsub);
         bwidth = kerndeint->tmp_bwidth[plane];
 
         srcp = srcp_saved = inpic->data[plane];
         src_linesize      = inpic->linesize[plane];
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index 68320d0b41..d2fd4a14bf 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -302,11 +302,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             inrow0  += in ->linesize[0];
             outrow0 += out->linesize[0];
         }
     } else {
         /* planar */
-        for (plane = 0; plane < 4 && in->data[plane]; plane++) {
+        for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
             int vsub = plane == 1 || plane == 2 ? s->vsub : 0;
             int hsub = plane == 1 || plane == 2 ? s->hsub : 0;
             int h = FF_CEIL_RSHIFT(inlink->h, vsub);
             int w = FF_CEIL_RSHIFT(inlink->w, hsub);
 
diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c
index 2e9aa56968..023ef7f863 100644
--- a/libavfilter/vf_pad.c
+++ b/libavfilter/vf_pad.c
@@ -212,11 +212,11 @@ static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h)
         return NULL;
 
     frame->width  = w;
     frame->height = h;
 
-    for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
+    for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
         int hsub = s->draw.hsub[plane];
         int vsub = s->draw.vsub[plane];
         frame->data[plane] += (s->x >> hsub) * s->draw.pixelstep[plane] +
                               (s->y >> vsub) * frame->linesize[plane];
     }
@@ -309,11 +309,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         av_frame_copy_props(out, in);
     } else {
         int i;
 
         out = in;
-        for (i = 0; i < 4 && out->data[i]; i++) {
+        for (i = 0; i < 4 && out->data[i] && out->linesize[i]; i++) {
             int hsub = s->draw.hsub[i];
             int vsub = s->draw.vsub[i];
             out->data[i] -= (s->x >> hsub) * s->draw.pixelstep[i] +
                             (s->y >> vsub) * out->linesize[i];
         }
diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index 336a870b17..82becc40f4 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -36,11 +36,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     AVFilterContext *ctx = inlink->dst;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     uint32_t plane_checksum[4] = {0}, checksum = 0;
     int i, plane, vsub = desc->log2_chroma_h;
 
-    for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
+    for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
         int64_t linesize = av_image_get_linesize(frame->format, frame->width, plane);
         uint8_t *data = frame->data[plane];
         int h = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h;
 
         if (linesize < 0)
@@ -66,11 +66,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
            frame->top_field_first   ? 'T' : 'B',    /* Top / Bottom */
            frame->key_frame,
            av_get_picture_type_char(frame->pict_type),
            checksum, plane_checksum[0]);
 
-    for (plane = 1; plane < 4 && frame->data[plane]; plane++)
+    for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++)
         av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]);
     av_log(ctx, AV_LOG_INFO, "]\n");
 
     return ff_filter_frame(inlink->dst->outputs[0], frame);
 }
diff --git a/libavfilter/vf_vignette.c b/libavfilter/vf_vignette.c
index 181999327a..b5fed65511 100644
--- a/libavfilter/vf_vignette.c
+++ b/libavfilter/vf_vignette.c
@@ -237,11 +237,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             fmap += fmap_linesize;
         }
     } else {
         int plane;
 
-        for (plane = 0; plane < 4 && in->data[plane]; plane++) {
+        for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
             uint8_t       *dst = out->data[plane];
             const uint8_t *src = in ->data[plane];
             const float *fmap = s->fmap;
             const int dst_linesize = out->linesize[plane];
             const int src_linesize = in ->linesize[plane];

Vulnerable code:     for (plane = 0; in->data[plane] && plane < 4; plane++)
    for (plane = 0; in->data[plane] && plane < 4; plane++)
    for (plane = 0; plane < 4 && in->data[plane]; plane++) {
    for (plane = 0; plane < 4 && src->data[plane]; plane++)
    for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
    for (p = 0; p < 4 && in->data[p]; p++) {
    for (plane = 0; plane < 4 && in->data[plane]; plane++) {
    for (plane = 0; inpic->data[plane] && plane < 4; plane++) {
        for (plane = 0; plane < 4 && in->data[plane]; plane++) {
    for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
        for (i = 0; i < 4 && out->data[i]; i++) {
    for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
    for (plane = 1; plane < 4 && frame->data[plane]; plane++)
        for (plane = 0; plane < 4 && in->data[plane]; plane++) {
Fixed code:     for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++)
    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++)
    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
    for (plane = 0; plane < 4 && src->data[plane] && src->linesize[plane]; plane++)
    for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
    for (p = 0; p < 4 && in->data[p] && in->linesize[p]; p++) {
    for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
    for (plane = 0; plane < 4 && inpic->data[plane] && inpic->linesize[plane]; plane++) {
        for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
    for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
        for (i = 0; i < 4 && out->data[i] && out->linesize[i]; i++) {
    for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
    for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++)
        for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {