aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-04-21 17:06:03 +0200
committerMichael Niedermayer <michaelni@gmx.at>2014-04-21 17:06:03 +0200
commit63b38d4a91818c6aa6e842c9df7f27362b1223fa (patch)
treefa474d47316827c74fd9c1301e01b9cca4b10d7a
parent260f37ee4d036f61633ccaf03e5d96f448d723ea (diff)
parent85b8b169175a55fc862e01ecc96f649374bc14d2 (diff)
downloadffmpeg-63b38d4a91818c6aa6e842c9df7f27362b1223fa.tar.gz
Merge commit '85b8b169175a55fc862e01ecc96f649374bc14d2' into release/1.1
* commit '85b8b169175a55fc862e01ecc96f649374bc14d2': tiffdec: use bytestream2 to simplify overread/overwrite protection Conflicts: libavcodec/tiff.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--libavcodec/tiff.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 0824934025..7394655c8e 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -409,6 +409,7 @@ static void av_always_inline horizontal_fill(unsigned int bpp, uint8_t* dst,
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;
const uint8_t *ssrc = src;
int width = ((s->width * s->bpp) + 7) >> 3;
@@ -479,6 +480,18 @@ 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 -1;
}
+ 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) {
@@ -520,15 +533,24 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
av_free(src2);
return ret;
}
+
+ 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 -1;
}
+
+ 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);
@@ -572,16 +594,6 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
}
}
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 -1;
- }
- 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;
}
@@ -655,7 +667,8 @@ static int init_image(TiffContext *s)
static int tiff_decode_tag(TiffContext *s)
{
unsigned tag, type, count, off, value = 0;
- int i, j, k, pos, start;
+ int i, start;
+ int j, k, pos;
int ret;
uint32_t *pal;
double *dp;
@@ -797,27 +810,17 @@ static int tiff_decode_tag(TiffContext *s)
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 -1;
- }
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 -1;
- }
break;
case TIFF_TILE_BYTE_COUNTS:
case TIFF_TILE_LENGTH:
@@ -854,11 +857,13 @@ static int tiff_decode_tag(TiffContext *s)
}
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 -1;
+
off = (type_sizes[type] - 1) << 3;
for (k = 2; k >= 0; k--) {
for (i = 0; i < count / 3; i++) {
@@ -870,6 +875,7 @@ static int tiff_decode_tag(TiffContext *s)
}
s->palette_is_set = 1;
break;
+ }
case TIFF_PLANAR:
if (value == 2) {
av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n");
@@ -1119,12 +1125,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) {
@@ -1134,12 +1142,12 @@ static int decode_frame(AVCodecContext *avctx,
for (i = 0; i < s->height; i += s->rps) {
if (s->stripsizesoff)
- ssize = tget(&stripsizes, s->sstype, s->le);
+ ssize = tget(&stripsizes, s->sstype, le);
else
ssize = s->stripsize;
if (s->strippos)
- soff = tget(&stripdata, s->sot, s->le);
+ soff = tget(&stripdata, s->sot, le);
else
soff = s->stripoff;