tiff: add smarter checks if there is enough data left

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol 2012-07-16 00:31:11 +00:00
parent 1ec83d9a9e
commit 292850b634
1 changed files with 29 additions and 13 deletions

View File

@ -65,26 +65,26 @@ typedef struct TiffContext {
static unsigned tget_short(GetByteContext *gb, int le)
{
unsigned v = le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb);
unsigned v = le ? bytestream2_get_le16u(gb) : bytestream2_get_be16u(gb);
return v;
}
static unsigned tget_long(GetByteContext *gb, int le)
{
unsigned v = le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb);
unsigned v = le ? bytestream2_get_le32u(gb) : bytestream2_get_be32u(gb);
return v;
}
static double tget_double(GetByteContext *gb, int le)
{
av_alias64 i = { .u64 = le ? bytestream2_get_le64(gb) : bytestream2_get_be64(gb)};
av_alias64 i = { .u64 = le ? bytestream2_get_le64u(gb) : bytestream2_get_be64u(gb)};
return i.f64;
}
static unsigned tget(GetByteContext *gb, int type, int le)
{
switch (type) {
case TIFF_BYTE : return bytestream2_get_byte(gb);
case TIFF_BYTE : return bytestream2_get_byteu(gb);
case TIFF_SHORT: return tget_short(gb, le);
case TIFF_LONG : return tget_long(gb, le);
default : return UINT_MAX;
@ -246,8 +246,10 @@ static int add_doubles_metadata(int count,
int i;
double *dp;
if (count >= INT_MAX / sizeof(int64_t))
return AVERROR_INVALIDDATA;
if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t))
return -1;
return AVERROR_INVALIDDATA;
dp = av_malloc(count * sizeof(double));
if (!dp)
@ -270,8 +272,10 @@ static int add_shorts_metadata(int count, const char *name,
int i;
int16_t *sp;
if (count >= INT_MAX / sizeof(int16_t))
return AVERROR_INVALIDDATA;
if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int16_t))
return -1;
return AVERROR_INVALIDDATA;
sp = av_malloc(count * sizeof(int16_t));
if (!sp)
@ -590,8 +594,6 @@ static int tiff_decode_tag(TiffContext *s)
uint32_t *pal;
double *dp;
if (bytestream2_get_bytes_left(&s->gb) < 12)
return -1;
tag = tget_short(&s->gb, s->le);
type = tget_short(&s->gb, s->le);
count = tget_long(&s->gb, s->le);
@ -657,7 +659,9 @@ static int tiff_decode_tag(TiffContext *s)
case TIFF_SHORT:
case TIFF_LONG:
s->bpp = 0;
for (i = 0; i < count && bytestream2_get_bytes_left(&s->gb) > 0; i++)
if (bytestream2_get_bytes_left(&s->gb) < type_sizes[type] * count)
return -1;
for (i = 0; i < count; i++)
s->bpp += tget(&s->gb, type, s->le);
break;
default:
@ -836,6 +840,8 @@ static int tiff_decode_tag(TiffContext *s)
s->geotag_count = count / 4 - 1;
av_log(s->avctx, AV_LOG_WARNING, "GeoTIFF key directory buffer shorter than specified\n");
}
if (bytestream2_get_bytes_left(&s->gb) < s->geotag_count * sizeof(int16_t) * 4)
return -1;
s->geotags = av_mallocz(sizeof(TiffGeoTag) * s->geotag_count);
if (!s->geotags) {
av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
@ -853,6 +859,10 @@ static int tiff_decode_tag(TiffContext *s)
}
break;
case TIFF_GEO_DOUBLE_PARAMS:
if (count >= INT_MAX / sizeof(int64_t))
return AVERROR_INVALIDDATA;
if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t))
return AVERROR_INVALIDDATA;
dp = av_malloc(count * sizeof(double));
if (!dp) {
av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
@ -886,13 +896,17 @@ static int tiff_decode_tag(TiffContext *s)
|| s->geotags[i].offset + s->geotags[i].count > count) {
av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key);
} else {
char *ap = av_malloc(s->geotags[i].count);
char *ap;
bytestream2_seek(&s->gb, pos + s->geotags[i].offset, SEEK_SET);
if (bytestream2_get_bytes_left(&s->gb) < s->geotags[i].count)
return -1;
ap = av_malloc(s->geotags[i].count);
if (!ap) {
av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
return AVERROR(ENOMEM);
}
bytestream2_seek(&s->gb, pos + s->geotags[i].offset, SEEK_SET);
bytestream2_get_buffer(&s->gb, ap, s->geotags[i].count);
bytestream2_get_bufferu(&s->gb, ap, s->geotags[i].count);
ap[s->geotags[i].count - 1] = '\0'; //replace the "|" delimiter with a 0 byte
s->geotags[i].val = ap;
}
@ -927,7 +941,7 @@ static int decode_frame(AVCodecContext *avctx,
//parse image header
if (avpkt->size < 8)
return AVERROR_INVALIDDATA;
id = bytestream2_get_le16(&s->gb);
id = bytestream2_get_le16u(&s->gb);
if (id == 0x4949)
le = 1;
else if (id == 0x4D4D)
@ -961,6 +975,8 @@ static int decode_frame(AVCodecContext *avctx,
}
bytestream2_seek(&s->gb, off, SEEK_SET);
entries = tget_short(&s->gb, le);
if (bytestream2_get_bytes_left(&s->gb) < entries * 12)
return AVERROR_INVALIDDATA;
for (i = 0; i < entries; i++) {
if (tiff_decode_tag(s) < 0)
return -1;