Merge remote-tracking branch 'qatar/master'
[ffmpeg.git] / libavcodec / sunrast.c
index 58bd2a2..36dfa98 100644 (file)
@@ -46,6 +46,7 @@ static av_cold int sunrast_init(AVCodecContext *avctx) {
 static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
                                 int *data_size, AVPacket *avpkt) {
     const uint8_t *buf = avpkt->data;
+    const uint8_t *buf_end = avpkt->data + avpkt->size;
     SUNRASTContext * const s = avctx->priv_data;
     AVFrame *picture = data;
     AVFrame * const p = &s->picture;
@@ -53,6 +54,9 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
     uint8_t *ptr;
     const uint8_t *bufstart = buf;
 
+    if (avpkt->size < 32)
+        return AVERROR_INVALIDDATA;
+
     if (AV_RB32(buf) != 0x59a66a95) {
         av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n");
         return -1;
@@ -64,13 +68,14 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
     type      = AV_RB32(buf+20);
     maptype   = AV_RB32(buf+24);
     maplength = AV_RB32(buf+28);
+    buf      += 32;
 
-    if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) {
-        av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n");
+    if (type < RT_OLD || type > RT_FORMAT_IFF) {
+        av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n");
         return -1;
     }
-    if (type > RT_FORMAT_IFF) {
-        av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n");
+    if (av_image_check_size(w, h, 0, avctx)) {
+        av_log(avctx, AV_LOG_ERROR, "invalid image size\n");
         return -1;
     }
     if (maptype & ~1) {
@@ -78,7 +83,10 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
         return -1;
     }
 
-    buf += 32;
+    if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) {
+        av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n");
+        return -1;
+    }
 
     switch (depth) {
         case 1:
@@ -98,8 +106,6 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
     if (p->data[0])
         avctx->release_buffer(avctx, p);
 
-    if (av_image_check_size(w, h, 0, avctx))
-        return -1;
     if (w != avctx->width || h != avctx->height)
         avcodec_set_dimensions(avctx, w, h);
     if (avctx->get_buffer(avctx, p) < 0) {
@@ -109,6 +115,9 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
 
     p->pict_type = AV_PICTURE_TYPE_I;
 
+    if (buf_end - buf < maplength)
+        return AVERROR_INVALIDDATA;
+
     if (depth != 8 && maplength) {
         av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n");
 
@@ -143,8 +152,11 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
         uint8_t *end = ptr + h*stride;
 
         x = 0;
-        while (ptr != end) {
+        while (ptr != end && buf < buf_end) {
             run = 1;
+            if (buf_end - buf < 1)
+                return AVERROR_INVALIDDATA;
+
             if ((value = *buf++) == 0x80) {
                 run = *buf++ + 1;
                 if (run != 1)
@@ -163,6 +175,8 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
         }
     } else {
         for (y=0; y<h; y++) {
+            if (buf_end - buf < len)
+                break;
             memcpy(ptr, buf, len);
             ptr += stride;
             buf += alen;