[FFmpeg-cvslog] tiff: add smarter checks if there is enough data left

Paul B Mahol git at videolan.org
Tue Jul 17 03:35:05 CEST 2012


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Jul 16 00:31:11 2012 +0000| [292850b634240045805e3c2001aed6f046034e93] | committer: Paul B Mahol

tiff: add smarter checks if there is enough data left

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=292850b634240045805e3c2001aed6f046034e93
---

 libavcodec/tiff.c |   42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 7547406..d3ec466 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;



More information about the ffmpeg-cvslog mailing list