mss2: prevent potential uninitialized reads
[ffmpeg.git] / libavcodec / mss2.c
index 2a0bf47..bec3f45 100644 (file)
@@ -106,7 +106,7 @@ static int arith2_get_number(ArithCoder *c, int n)
     return val;
 }
 
-static int arith2_get_prob(ArithCoder *c, int *probs)
+static int arith2_get_prob(ArithCoder *c, int16_t *probs)
 {
     int range = c->high - c->low + 1, n = *probs;
     int scale = av_log2(range) - av_log2(n);
@@ -161,7 +161,7 @@ static int decode_pal_v2(MSS12Context *ctx, const uint8_t *buf, int buf_size)
         return 0;
 
     ncol = *buf++;
-    if (buf_size < 2 + ncol * 3)
+    if (ncol > ctx->free_colours || buf_size < 2 + ncol * 3)
         return -1;
     for (i = 0; i < ncol; i++)
         *pal++ = AV_RB24(buf + 3 * i);
@@ -335,8 +335,7 @@ static int decode_rle(GetBitContext *gb, uint8_t *pal_dst, int pal_stride,
                     else
                         repeat = get_bits(gb, b);
 
-                    while (b--)
-                        repeat += 1 << b;
+                    repeat += (1 << b) - 1;
 
                     if (last_symbol == -2) {
                         int skip = FFMIN(repeat, pal_dst + w - pp);
@@ -397,11 +396,11 @@ static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size,
         return AVERROR_INVALIDDATA;
     }
 
-    avctx->pix_fmt = PIX_FMT_YUV420P;
+    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
 
     if (ff_MPV_frame_start(s, avctx) < 0) {
         av_log(v->s.avctx, AV_LOG_ERROR, "ff_MPV_frame_start error\n");
-        avctx->pix_fmt = PIX_FMT_RGB24;
+        avctx->pix_fmt = AV_PIX_FMT_RGB24;
         return -1;
     }
 
@@ -449,7 +448,7 @@ static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size,
                                 f->data[1], f->data[2], f->linesize[1],
                                 w, h);
 
-    avctx->pix_fmt = PIX_FMT_RGB24;
+    avctx->pix_fmt = AV_PIX_FMT_RGB24;
 
     return 0;
 }
@@ -475,7 +474,7 @@ static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
     int keyframe, has_wmv9, has_mv, is_rle, is_555, ret;
 
     Rectangle wmv9rects[MAX_WMV9_RECTANGLES], *r;
-    int used_rects = 0, i, implicit_rect, av_uninit(wmv9_mask);
+    int used_rects = 0, i, implicit_rect = 0, av_uninit(wmv9_mask);
 
     av_assert0(FF_INPUT_BUFFER_PADDING_SIZE >=
                ARITH2_PADDING + (MIN_CACHE_BITS + 7) / 8);
@@ -520,7 +519,7 @@ static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
     if (is_555 && (has_wmv9 || has_mv || c->slice_split && ctx->split_position))
         return AVERROR_INVALIDDATA;
 
-    avctx->pix_fmt = is_555 ? PIX_FMT_RGB555 : PIX_FMT_RGB24;
+    avctx->pix_fmt = is_555 ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_RGB24;
     if (ctx->pic.data[0] && ctx->pic.format != avctx->pix_fmt)
         avctx->release_buffer(avctx, &ctx->pic);
 
@@ -651,54 +650,61 @@ static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
             return AVERROR_INVALIDDATA;
 
         buf_size -= bytestream2_tell(&gB);
-    } else if (is_rle) {
-        init_get_bits(&gb, buf, buf_size * 8);
-        if (ret = decode_rle(&gb, c->pal_pic, c->pal_stride,
-                             c->rgb_pic, c->rgb_stride, c->pal, keyframe,
-                             ctx->split_position, 0,
-                             avctx->width, avctx->height))
-            return ret;
-        align_get_bits(&gb);
-
-        if (c->slice_split)
+    } else {
+        if (keyframe) {
+            c->corrupted = 0;
+            ff_mss12_slicecontext_reset(&ctx->sc[0]);
+            if (c->slice_split)
+                ff_mss12_slicecontext_reset(&ctx->sc[1]);
+        }
+        if (is_rle) {
+            init_get_bits(&gb, buf, buf_size * 8);
             if (ret = decode_rle(&gb, c->pal_pic, c->pal_stride,
                                  c->rgb_pic, c->rgb_stride, c->pal, keyframe,
-                                 ctx->split_position, 1,
+                                 ctx->split_position, 0,
                                  avctx->width, avctx->height))
                 return ret;
+            align_get_bits(&gb);
 
-        align_get_bits(&gb);
-        buf      += get_bits_count(&gb) >> 3;
-        buf_size -= get_bits_count(&gb) >> 3;
-    } else {
-        if (keyframe)
-            ff_mss12_codec_reset(c);
-        else if (c->corrupted)
-            return AVERROR_INVALIDDATA;
-        bytestream2_init(&gB, buf, buf_size + ARITH2_PADDING);
-        arith2_init(&acoder, &gB);
-        c->keyframe = keyframe;
-        if (c->corrupted = ff_mss12_decode_rect(&c->sc[0], &acoder, 0, 0,
-                                                avctx->width,
-                                                ctx->split_position))
-            return AVERROR_INVALIDDATA;
+            if (c->slice_split)
+                if (ret = decode_rle(&gb, c->pal_pic, c->pal_stride,
+                                     c->rgb_pic, c->rgb_stride, c->pal, keyframe,
+                                     ctx->split_position, 1,
+                                     avctx->width, avctx->height))
+                    return ret;
 
-        buf      += arith2_get_consumed_bytes(&acoder);
-        buf_size -= arith2_get_consumed_bytes(&acoder);
-        if (c->slice_split) {
-            if (buf_size < 1)
+            align_get_bits(&gb);
+            buf      += get_bits_count(&gb) >> 3;
+            buf_size -= get_bits_count(&gb) >> 3;
+        } else if (!implicit_rect || wmv9_mask != -1) {
+            if (c->corrupted)
                 return AVERROR_INVALIDDATA;
             bytestream2_init(&gB, buf, buf_size + ARITH2_PADDING);
             arith2_init(&acoder, &gB);
-            if (c->corrupted = ff_mss12_decode_rect(&c->sc[1], &acoder, 0,
-                                                    ctx->split_position,
+            c->keyframe = keyframe;
+            if (c->corrupted = ff_mss12_decode_rect(&ctx->sc[0], &acoder, 0, 0,
                                                     avctx->width,
-                                                    avctx->height - ctx->split_position))
+                                                    ctx->split_position))
                 return AVERROR_INVALIDDATA;
 
             buf      += arith2_get_consumed_bytes(&acoder);
             buf_size -= arith2_get_consumed_bytes(&acoder);
-        }
+            if (c->slice_split) {
+                if (buf_size < 1)
+                    return AVERROR_INVALIDDATA;
+                bytestream2_init(&gB, buf, buf_size + ARITH2_PADDING);
+                arith2_init(&acoder, &gB);
+                if (c->corrupted = ff_mss12_decode_rect(&ctx->sc[1], &acoder, 0,
+                                                        ctx->split_position,
+                                                        avctx->width,
+                                                        avctx->height - ctx->split_position))
+                    return AVERROR_INVALIDDATA;
+
+                buf      += arith2_get_consumed_bytes(&acoder);
+                buf_size -= arith2_get_consumed_bytes(&acoder);
+            }
+        } else
+            memset(c->pal_pic, 0, c->pal_stride * avctx->height);
     }
 
     if (has_wmv9) {
@@ -830,11 +836,11 @@ static av_cold int mss2_decode_init(AVCodecContext *avctx)
     int ret;
     c->avctx = avctx;
     avctx->coded_frame = &ctx->pic;
-    if (ret = ff_mss12_decode_init(c, 1))
+    if (ret = ff_mss12_decode_init(c, 1, &ctx->sc[0], &ctx->sc[1]))
         return ret;
     c->pal_stride   = c->mask_stride;
-    c->pal_pic      = av_malloc(c->pal_stride * avctx->height);
-    c->last_pal_pic = av_malloc(c->pal_stride * avctx->height);
+    c->pal_pic      = av_mallocz(c->pal_stride * avctx->height);
+    c->last_pal_pic = av_mallocz(c->pal_stride * avctx->height);
     if (!c->pal_pic || !c->last_pal_pic) {
         mss2_decode_end(avctx);
         return AVERROR(ENOMEM);
@@ -845,8 +851,8 @@ static av_cold int mss2_decode_init(AVCodecContext *avctx)
     }
     ff_mss2dsp_init(&ctx->dsp);
 
-    avctx->pix_fmt = c->free_colours == 127 ? PIX_FMT_RGB555
-                                            : PIX_FMT_RGB24;
+    avctx->pix_fmt = c->free_colours == 127 ? AV_PIX_FMT_RGB555
+                                            : AV_PIX_FMT_RGB24;
 
     return 0;
 }