Merge commit '0a467a9b594dd67aa96bad687d05f8845b009f18'
[ffmpeg.git] / libavcodec / tiff.c
index 53cdcd0..69d1bb2 100644 (file)
@@ -383,9 +383,10 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride,
 static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
                              const uint8_t *src, int size, int lines)
 {
+    PutByteContext pb;
     int c, line, pixels, code, ret;
     const uint8_t *ssrc = src;
-    int width           = ((s->width * s->bpp) + 7) >> 3;
+    int width = ((s->width * s->bpp) + 7) >> 3;
 
     if (s->planar)
         width /= s->bppcount;
@@ -416,21 +417,42 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
             av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n");
             return ret;
         }
+        for (line = 0; line < lines; line++) {
+            pixels = ff_lzw_decode(s->lzw, dst, width);
+            if (pixels < width) {
+                av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n",
+                       pixels, width);
+                return AVERROR_INVALIDDATA;
+            }
+            if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
+                horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
+            dst += stride;
+        }
+        return 0;
     }
     if (s->compr == TIFF_CCITT_RLE ||
         s->compr == TIFF_G3        ||
         s->compr == TIFF_G4) {
         return tiff_unpack_fax(s, dst, stride, src, size, width, lines);
     }
+
+    bytestream2_init(&s->gb, src, size);
+    bytestream2_init_writer(&pb, dst, stride * lines);
+
     for (line = 0; line < lines; line++) {
         if (src - ssrc > size) {
             av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n");
             return AVERROR_INVALIDDATA;
         }
+
+        if (bytestream2_get_bytes_left(&s->gb) == 0 || bytestream2_get_eof(&pb))
+            break;
+        bytestream2_seek_p(&pb, stride * line, SEEK_SET);
         switch (s->compr) {
         case TIFF_RAW:
             if (ssrc + size - src < width)
                 return AVERROR_INVALIDDATA;
+
             if (!s->fill_order) {
                 horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
                                 dst, 1, src, 0, width, 0);
@@ -479,16 +501,6 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
                     dst[i] = ff_reverse[dst[i]];
             }
             break;
-        case TIFF_LZW:
-            pixels = ff_lzw_decode(s->lzw, dst, width);
-            if (pixels < width) {
-                av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n",
-                       pixels, width);
-                return AVERROR_INVALIDDATA;
-            }
-            if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
-                horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
-            break;
         }
         dst += stride;
     }
@@ -580,7 +592,8 @@ static void set_sar(TiffContext *s, unsigned tag, unsigned num, unsigned den)
 static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
 {
     unsigned tag, type, count, off, value = 0, value2 = 0;
-    int i, j, k, pos, start;
+    int i, start;
+    int j, k, pos;
     int ret;
     uint32_t *pal;
     double *dp;
@@ -702,35 +715,25 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
         break;
     case TIFF_STRIP_OFFS:
         if (count == 1) {
-            s->strippos  = 0;
-            s->stripoff  = value;
+            s->strippos = 0;
+            s->stripoff = value;
         } else
             s->strippos = off;
         s->strips = count;
         if (s->strips == 1)
             s->rps = s->height;
         s->sot = type;
-        if (s->strippos > bytestream2_size(&s->gb)) {
-            av_log(s->avctx, AV_LOG_ERROR,
-                   "Tag referencing position outside the image\n");
-            return AVERROR_INVALIDDATA;
-        }
         break;
     case TIFF_STRIP_SIZE:
         if (count == 1) {
             s->stripsizesoff = 0;
-            s->stripsize  = value;
-            s->strips     = 1;
+            s->stripsize     = value;
+            s->strips        = 1;
         } else {
             s->stripsizesoff = off;
         }
         s->strips = count;
         s->sstype = type;
-        if (s->stripsizesoff > bytestream2_size(&s->gb)) {
-            av_log(s->avctx, AV_LOG_ERROR,
-                   "Tag referencing position outside the image\n");
-            return AVERROR_INVALIDDATA;
-        }
         break;
     case TIFF_XRES:
     case TIFF_YRES:
@@ -771,11 +774,13 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
         }
         s->fill_order = value - 1;
         break;
-    case TIFF_PAL:
+    case TIFF_PAL: {
         pal = (uint32_t *) s->palette;
         off = type_sizes[type];
-        if (count / 3 > 256 || bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3)
+        if (count / 3 > 256 ||
+            bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3)
             return AVERROR_INVALIDDATA;
+
         off = (type_sizes[type] - 1) << 3;
         for (k = 2; k >= 0; k--) {
             for (i = 0; i < count / 3; i++) {
@@ -787,6 +792,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
         }
         s->palette_is_set = 1;
         break;
+    }
     case TIFF_PLANAR:
         s->planar = value == 2;
         break;
@@ -1019,12 +1025,14 @@ static int decode_frame(AVCodecContext *avctx,
     if (s->stripsizesoff) {
         if (s->stripsizesoff >= (unsigned)avpkt->size)
             return AVERROR_INVALIDDATA;
-        bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, avpkt->size - s->stripsizesoff);
+        bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff,
+                         avpkt->size - s->stripsizesoff);
     }
     if (s->strippos) {
         if (s->strippos >= (unsigned)avpkt->size)
             return AVERROR_INVALIDDATA;
-        bytestream2_init(&stripdata, avpkt->data + s->strippos, avpkt->size - s->strippos);
+        bytestream2_init(&stripdata, avpkt->data + s->strippos,
+                         avpkt->size - s->strippos);
     }
 
     if (s->rps <= 0) {
@@ -1038,12 +1046,12 @@ static int decode_frame(AVCodecContext *avctx,
         dst    = p->data[plane];
     for (i = 0; i < s->height; i += s->rps) {
         if (s->stripsizesoff)
-            ssize = ff_tget(&stripsizes, s->sstype, s->le);
+            ssize = ff_tget(&stripsizes, s->sstype, le);
         else
             ssize = s->stripsize;
 
         if (s->strippos)
-            soff = ff_tget(&stripdata, s->sot, s->le);
+            soff = ff_tget(&stripdata, s->sot, le);
         else
             soff = s->stripoff;