]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/yop.c
Merge commit 'd2a25c4032ce6ceabb0f51b5c1e6ca865395a793'
[ffmpeg] / libavcodec / yop.c
index c47f5ec14fc53d79173a7629560db995c54911a0..234868abbfd41f6e2396a532189f13d131f741fd 100644 (file)
@@ -39,6 +39,7 @@ typedef struct YopDecContext {
 
     uint8_t *low_nibble;
     uint8_t *srcptr;
+    uint8_t *src_end;
     uint8_t *dstptr;
     uint8_t *dstbuf;
 } YopDecContext;
@@ -89,8 +90,8 @@ static av_cold int yop_decode_init(AVCodecContext *avctx)
         return AVERROR_INVALIDDATA;
     }
 
-    if (!avctx->extradata) {
-        av_log(avctx, AV_LOG_ERROR, "extradata missing\n");
+    if (avctx->extradata_size < 3) {
+        av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata.\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -124,8 +125,13 @@ static av_cold int yop_decode_close(AVCodecContext *avctx)
  * @param s codec context
  * @param tag the tag that was in the nibble
  */
-static void yop_paint_block(YopDecContext *s, int tag)
+static int yop_paint_block(YopDecContext *s, int tag)
 {
+    if (s->src_end - s->srcptr < paint_lut[tag][3]) {
+        av_log(s->avctx, AV_LOG_ERROR, "Packet too small.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     s->dstptr[0]                        = s->srcptr[0];
     s->dstptr[1]                        = s->srcptr[paint_lut[tag][0]];
     s->dstptr[s->frame.linesize[0]]     = s->srcptr[paint_lut[tag][1]];
@@ -133,6 +139,7 @@ static void yop_paint_block(YopDecContext *s, int tag)
 
     // The number of src bytes consumed is in the last part of the lut entry.
     s->srcptr += paint_lut[tag][3];
+    return 0;
 }
 
 /**
@@ -185,23 +192,27 @@ static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     int ret, i, x, y;
     uint32_t *palette;
 
-    if (s->frame.data[0])
-        avctx->release_buffer(avctx, &s->frame);
-
-    if (avpkt->size < 4 + 3*s->num_pal_colors) {
-        av_log(avctx, AV_LOG_ERROR, "packet of size %d too small\n", avpkt->size);
+    if (avpkt->size < 4 + 3 * s->num_pal_colors) {
+        av_log(avctx, AV_LOG_ERROR, "Packet too small.\n");
         return AVERROR_INVALIDDATA;
     }
 
+    if (s->frame.data[0])
+        avctx->release_buffer(avctx, &s->frame);
+
     ret = ff_get_buffer(avctx, &s->frame);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
 
+    if (!avctx->frame_number)
+        memset(s->frame.data[1], 0, AVPALETTE_SIZE);
+
     s->dstbuf     = s->frame.data[0];
     s->dstptr     = s->frame.data[0];
     s->srcptr     = avpkt->data + 4;
+    s->src_end    = avpkt->data + avpkt->size;
     s->low_nibble = NULL;
 
     is_odd_frame = avpkt->data[0];
@@ -232,7 +243,9 @@ static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             tag = yop_get_next_nibble(s);
 
             if (tag != 0xf) {
-                yop_paint_block(s, tag);
+                ret = yop_paint_block(s, tag);
+                if (ret < 0)
+                    return ret;
             } else {
                 tag = yop_get_next_nibble(s);
                 ret = yop_copy_previous_block(s, tag);