diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-04-13 03:01:03 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-04-13 03:20:09 +0200 |
commit | 94cf83ff91b2380e487211a0444bcd4ac9b58b75 (patch) | |
tree | 9f7b191c15551537eb2a446c738116b834bfbfb8 /libavcodec/tiff.c | |
parent | 31876ea620064b00c41ab87c3bb49cf9c6e098eb (diff) | |
parent | 0a467a9b594dd67aa96bad687d05f8845b009f18 (diff) | |
download | ffmpeg-94cf83ff91b2380e487211a0444bcd4ac9b58b75.tar.gz |
Merge commit '0a467a9b594dd67aa96bad687d05f8845b009f18'
* commit '0a467a9b594dd67aa96bad687d05f8845b009f18':
tiffdec: use bytestream2 to simplify overread/overwrite protection
Conflicts:
libavcodec/tiff.c
See: 1ec83d9a9e472f485897ac92bad9631d551a8c5b
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/tiff.c')
-rw-r--r-- | libavcodec/tiff.c | 72 |
1 files changed, 40 insertions, 32 deletions
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 53cdcd0e9f..69d1bb2381 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -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; |