[gdk-pixbuf] jpeg: Check for integer overflows in app1 EXIF tags



commit 5daadc0b44092ba53797b2629490e5ea223647f5
Author: Tobias Mueller <muelli cryptobitch de>
Date:   Mon Nov 28 11:46:15 2016 +0100

    jpeg: Check for integer overflows in app1 EXIF tags
    
    In jpeg_parse_exif_app1(), we would usually read offsets this way:
    
        /* read out the offset pointer to IFD0 */
        offset  = de_get32(&marker->data[i] + 4, endian);
        i = i + offset;
    
    "i" is then used to peek into the buffer and read bytes.
    
        tags = de_get16(&marker->data[i], endian);
        i = i + 2;
    
    But as the addition may overflow, we need to check whether the result of
    the addition would overflow and wrap-around.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=775218

 gdk-pixbuf/io-jpeg.c |   37 ++++++++++++++++++++++++++-----------
 1 files changed, 26 insertions(+), 11 deletions(-)
---
diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c
index a2adff1..81489c3 100644
--- a/gdk-pixbuf/io-jpeg.c
+++ b/gdk-pixbuf/io-jpeg.c
@@ -444,26 +444,36 @@ jpeg_parse_exif_app1 (JpegExifContext *context, jpeg_saved_marker_ptr marker)
        i = i + offset;
 
        /* check that we still are within the buffer and can read the tag count */
-       if ((i + 2) > marker->data_length) {
-               ret = FALSE;
-               goto out;
+       {
+           const size_t new_i = i + 2;
+           if (new_i < i || new_i > marker->data_length) {
+                   ret = FALSE;
+                   goto out;
+           }
+
+           /* find out how many tags we have in IFD0. As per the TIFF spec, the first
+              two bytes of the IFD contain a count of the number of tags. */
+           tags = de_get16(&marker->data[i], endian);
+           i = new_i;
        }
 
-       /* find out how many tags we have in IFD0. As per the TIFF spec, the first
-          two bytes of the IFD contain a count of the number of tags. */
-       tags = de_get16(&marker->data[i], endian);
-       i = i + 2;
-
        /* check that we still have enough data for all tags to check. The tags
           are listed in consecutive 12-byte blocks. The tag ID, type, size, and
           a pointer to the actual value, are packed into these 12 byte entries. */
-       if ((i + tags * 12) > marker->data_length) {
+       {
+           const size_t new_i = i + tags * 12;
+           if (new_i < i || new_i > marker->data_length) {
                ret = FALSE;
                goto out;
+           }
        }
 
        /* check through IFD0 for tags */
-       while (tags--){
+       while (tags--) {
+               size_t new_i;
+
+               /* We check for integer overflow before the loop and
+                * at the end of each iteration */
                guint tag   = de_get16(&marker->data[i + 0], endian);
                guint type  = de_get16(&marker->data[i + 2], endian);
                guint count = de_get32(&marker->data[i + 4], endian);
@@ -486,7 +496,12 @@ jpeg_parse_exif_app1 (JpegExifContext *context, jpeg_saved_marker_ptr marker)
                        }
                }
                /* move the pointer to the next 12-byte tag field. */
-               i = i + 12;
+               new_i = i + 12;
+               if (new_i < i || new_i > marker->data_length) {
+                       ret = FALSE;
+                       goto out;
+               }
+               i = new_i;
        }
 
 out:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]