Commit 04a845ca authored by Laurent Aimar's avatar Laurent Aimar Committed by Janne Grunau

tiffdec: fix out of bound reads/writes

Signed-off-by: 's avatarJanne Grunau <janne-libav@jannau.net>
parent 46cb2f6a
...@@ -173,6 +173,8 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin ...@@ -173,6 +173,8 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin
} }
switch(s->compr){ switch(s->compr){
case TIFF_RAW: case TIFF_RAW:
if (ssrc + size - src < width)
return AVERROR_INVALIDDATA;
if (!s->fill_order) { if (!s->fill_order) {
memcpy(dst, src, width); memcpy(dst, src, width);
} else { } else {
...@@ -280,6 +282,8 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * ...@@ -280,6 +282,8 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *
uint32_t *pal; uint32_t *pal;
const uint8_t *rp, *gp, *bp; const uint8_t *rp, *gp, *bp;
if (end_buf - buf < 12)
return -1;
tag = tget_short(&buf, s->le); tag = tget_short(&buf, s->le);
type = tget_short(&buf, s->le); type = tget_short(&buf, s->le);
count = tget_long(&buf, s->le); count = tget_long(&buf, s->le);
...@@ -339,7 +343,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * ...@@ -339,7 +343,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *
case TIFF_SHORT: case TIFF_SHORT:
case TIFF_LONG: case TIFF_LONG:
s->bpp = 0; s->bpp = 0;
for(i = 0; i < count; i++) s->bpp += tget(&buf, type, s->le); for(i = 0; i < count && buf < end_buf; i++) s->bpp += tget(&buf, type, s->le);
break; break;
default: default:
s->bpp = -1; s->bpp = -1;
...@@ -453,6 +457,8 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * ...@@ -453,6 +457,8 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *
case TIFF_PAL: case TIFF_PAL:
pal = (uint32_t *) s->palette; pal = (uint32_t *) s->palette;
off = type_sizes[type]; off = type_sizes[type];
if (count / 3 > 256 || end_buf - buf < count / 3 * off * 3)
return -1;
rp = buf; rp = buf;
gp = buf + count / 3 * off; gp = buf + count / 3 * off;
bp = buf + count / 3 * off * 2; bp = buf + count / 3 * off * 2;
...@@ -495,12 +501,16 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -495,12 +501,16 @@ static int decode_frame(AVCodecContext *avctx,
AVFrame *picture = data; AVFrame *picture = data;
AVFrame * const p= (AVFrame*)&s->picture; AVFrame * const p= (AVFrame*)&s->picture;
const uint8_t *orig_buf = buf, *end_buf = buf + buf_size; const uint8_t *orig_buf = buf, *end_buf = buf + buf_size;
int id, le, off, ret; unsigned off;
int id, le, ret;
int i, j, entries; int i, j, entries;
int stride, soff, ssize; int stride;
unsigned soff, ssize;
uint8_t *dst; uint8_t *dst;
//parse image header //parse image header
if (end_buf - buf < 8)
return AVERROR_INVALIDDATA;
id = AV_RL16(buf); buf += 2; id = AV_RL16(buf); buf += 2;
if(id == 0x4949) le = 1; if(id == 0x4949) le = 1;
else if(id == 0x4D4D) le = 0; else if(id == 0x4D4D) le = 0;
...@@ -520,9 +530,9 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -520,9 +530,9 @@ static int decode_frame(AVCodecContext *avctx,
} }
/* parse image file directory */ /* parse image file directory */
off = tget_long(&buf, le); off = tget_long(&buf, le);
if(orig_buf + off + 14 >= end_buf){ if (off >= UINT_MAX - 14 || end_buf - orig_buf < off + 14) {
av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n"); av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n");
return -1; return AVERROR_INVALIDDATA;
} }
buf = orig_buf + off; buf = orig_buf + off;
entries = tget_short(&buf, le); entries = tget_short(&buf, le);
...@@ -546,23 +556,23 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -546,23 +556,23 @@ static int decode_frame(AVCodecContext *avctx,
stride = p->linesize[0]; stride = p->linesize[0];
dst = p->data[0]; dst = p->data[0];
for(i = 0; i < s->height; i += s->rps){ for(i = 0; i < s->height; i += s->rps){
if(s->stripsizes) if(s->stripsizes) {
if (s->stripsizes >= end_buf)
return AVERROR_INVALIDDATA;
ssize = tget(&s->stripsizes, s->sstype, s->le); ssize = tget(&s->stripsizes, s->sstype, s->le);
else } else
ssize = s->stripsize; ssize = s->stripsize;
if (ssize > buf_size) {
av_log(avctx, AV_LOG_ERROR, "Buffer size is smaller than strip size\n");
return -1;
}
if(s->stripdata){ if(s->stripdata){
if (s->stripdata >= end_buf)
return AVERROR_INVALIDDATA;
soff = tget(&s->stripdata, s->sot, s->le); soff = tget(&s->stripdata, s->sot, s->le);
}else }else
soff = s->stripoff; soff = s->stripoff;
if (soff < 0) {
av_log(avctx, AV_LOG_ERROR, "Invalid stripoff: %d\n", soff); if (soff > buf_size || ssize > buf_size - soff) {
return AVERROR(EINVAL); av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n");
return -1;
} }
if(tiff_unpack_strip(s, dst, stride, orig_buf + soff, ssize, FFMIN(s->rps, s->height - i)) < 0) if(tiff_unpack_strip(s, dst, stride, orig_buf + soff, ssize, FFMIN(s->rps, s->height - i)) < 0)
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment