]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/qtrle.c
avutil/mem: Also poison new av_realloc-allocated blocks
[ffmpeg] / libavcodec / qtrle.c
index 443dd88f71baad415c9a5ec29ac8b284d069c271..4ad224e37d3aac191dd087b28c7fb1f9228a7de7 100644 (file)
@@ -36,6 +36,7 @@
 #include <string.h>
 
 #include "avcodec.h"
+#include "decode.h"
 #include "bytestream.h"
 #include "internal.h"
 
@@ -452,15 +453,16 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
     int header, start_line;
     int height, row_ptr;
     int has_palette = 0;
+    int duplicate = 0;
     int ret, size;
 
     bytestream2_init(&s->g, avpkt->data, avpkt->size);
-    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
-        return ret;
 
     /* check if this frame is even supposed to change */
-    if (avpkt->size < 8)
+    if (avpkt->size < 8) {
+        duplicate = 1;
         goto done;
+    }
 
     /* start after the chunk size */
     size = bytestream2_get_be32(&s->g) & 0x3FFFFFFF;
@@ -473,18 +475,25 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
 
     /* if a header is present, fetch additional decoding parameters */
     if (header & 0x0008) {
-        if (avpkt->size < 14)
+        if (avpkt->size < 14) {
+            duplicate = 1;
             goto done;
+        }
         start_line = bytestream2_get_be16(&s->g);
         bytestream2_skip(&s->g, 2);
         height     = bytestream2_get_be16(&s->g);
         bytestream2_skip(&s->g, 2);
-        if (height > s->avctx->height - start_line)
+        if (height > s->avctx->height - start_line) {
+            duplicate = 1;
             goto done;
+        }
     } else {
         start_line = 0;
         height     = s->avctx->height;
     }
+    if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
+        return ret;
+
     row_ptr = s->frame->linesize[0] * start_line;
 
     switch (avctx->bits_per_coded_sample) {
@@ -531,21 +540,23 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
     }
 
     if(has_palette) {
-        int size;
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
-
-        if (pal && size == AVPALETTE_SIZE) {
-            s->frame->palette_has_changed = 1;
-            memcpy(s->pal, pal, AVPALETTE_SIZE);
-        } else if (pal) {
-            av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
-        }
+        s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
 
         /* make the palette available on the way out */
         memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE);
     }
 
 done:
+    if (!s->frame->data[0])
+        return AVERROR_INVALIDDATA;
+    if (duplicate) {
+        // ff_reget_buffer() isn't needed when frames don't change, so just update
+        // frame props.
+        ret = ff_decode_frame_props(avctx, s->frame);
+        if (ret < 0)
+            return ret;
+    }
+
     if ((ret = av_frame_ref(data, s->frame)) < 0)
         return ret;
     *got_frame      = 1;
@@ -558,7 +569,6 @@ static void qtrle_decode_flush(AVCodecContext *avctx)
 {
     QtrleContext *s = avctx->priv_data;
 
-    memset(s->pal, 0, sizeof(s->pal));
     av_frame_unref(s->frame);
 }
 
@@ -571,7 +581,7 @@ static av_cold int qtrle_decode_end(AVCodecContext *avctx)
     return 0;
 }
 
-AVCodec ff_qtrle_decoder = {
+const AVCodec ff_qtrle_decoder = {
     .name           = "qtrle",
     .long_name      = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
     .type           = AVMEDIA_TYPE_VIDEO,