summaryrefslogtreecommitdiff
path: root/libavcodec/tiff.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2012-07-16 00:31:11 +0000
committerPaul B Mahol <onemda@gmail.com>2012-07-17 01:23:34 +0000
commit292850b634240045805e3c2001aed6f046034e93 (patch)
treeca232ae4a90643ca16ab62dd2e10e120b531f40e /libavcodec/tiff.c
parent1ec83d9a9e472f485897ac92bad9631d551a8c5b (diff)
tiff: add smarter checks if there is enough data left
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavcodec/tiff.c')
-rw-r--r--libavcodec/tiff.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 754740681a..d3ec466a59 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -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;