Properly open and work with large TIFF files.
authorMartin Pelikán <mpel@google.com>
Sun, 19 Jun 2016 15:32:00 +0000 (01:32 +1000)
committerKlaus Ethgen <Klaus@Ethgen.de>
Sun, 19 Jun 2016 16:10:40 +0000 (17:10 +0100)
Any file between 2^31 and 2^32 bytes shouldn't have its size displayed
as a negative number. Viewing more than 32768 pixels in each dimension
is only a matter of using 64bit arithmetic when calculating allocation
sizes and pointers into that memory. Multiplying is always suspicious.

While there, make the error messages clearer about what went wrong.

Signed-off-by: Klaus Ethgen <Klaus@Ethgen.de>
src/filedata.c
src/image_load_tiff.c
src/pixbuf-renderer.c

index 33433c0..54de50f 100644 (file)
@@ -64,7 +64,7 @@ gchar *text_from_size(gint64 size)
        /* what I would like to use is printf("%'d", size)
         * BUT: not supported on every libc :(
         */
-       if (size > G_MAXUINT)
+       if (size > G_MAXINT)
                {
                /* the %lld conversion is not valid in all libcs, so use a simple work-around */
                a = g_strdup_printf("%d%09d", (guint)(size / 1000000000), (guint)(size % 1000000000));
index 33f238f..a3c8ce6 100644 (file)
@@ -141,7 +141,8 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
 
        TIFF *tiff;
        guchar *pixels = NULL;
-       gint width, height, rowstride, bytes;
+       gint width, height, rowstride;
+       size_t bytes;
        uint32 rowsperstrip;
 
        lt->buffer = buf;
@@ -186,15 +187,15 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
        rowstride = width * 4;
        if (rowstride / 4 != width)
                { /* overflow */
-               DEBUG_1("Dimensions of TIFF image too large");
+               DEBUG_1("Dimensions of TIFF image too large: width %d", width);
                TIFFClose(tiff);
                return FALSE;
                }
 
-       bytes = height * rowstride;
-       if (bytes / rowstride != height)
+       bytes = (size_t) height * rowstride;
+       if (bytes / rowstride != (size_t) height)
                { /* overflow */
-               DEBUG_1("Dimensions of TIFF image too large");
+               DEBUG_1("Dimensions of TIFF image too large: height %d", height);
                TIFFClose(tiff);
                return FALSE;
                }
@@ -207,7 +208,7 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
 
        if (!pixels)
                {
-               DEBUG_1("Insufficient memory to open TIFF file");
+               DEBUG_1("Insufficient memory to open TIFF file: need %zu", bytes);
                TIFFClose(tiff);
                return FALSE;
                }
@@ -228,8 +229,9 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
        if (TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
                {
                /* read by strip */
-               int row;
-               guchar *wrk_line = (guchar *)g_malloc(width * sizeof (uint32));
+               ptrdiff_t row;
+               const size_t line_bytes = width * sizeof(uint32);
+               guchar *wrk_line = (guchar *)g_malloc(line_bytes);
 
                for (row = 0; row < height; row += rowsperstrip)
                        {
@@ -263,9 +265,9 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
                                top_line = pixels + (row + i_row) * rowstride;
                                bottom_line = pixels + (row + rows_to_write - i_row - 1) * rowstride;
 
-                               memcpy(wrk_line, top_line, 4*width);
-                               memcpy(top_line, bottom_line, 4*width);
-                               memcpy(bottom_line, wrk_line, 4*width);
+                               memcpy(wrk_line, top_line, line_bytes);
+                               memcpy(top_line, bottom_line, line_bytes);
+                               memcpy(bottom_line, wrk_line, line_bytes);
                                }
                        lt->area_updated_cb(loader, 0, row, width, rows_to_write, lt->data);
                        }
index 8074e26..327e398 100644 (file)
@@ -2769,6 +2769,7 @@ gboolean pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint
        gint p_alpha, prs;
        guchar *p_pix, *pp;
        gint map_x, map_y, map_w, map_h;
+       size_t xoff, yoff;
 
        g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
        g_return_val_if_fail(r_mouse != NULL && g_mouse != NULL && b_mouse != NULL, FALSE);
@@ -2797,7 +2798,9 @@ gboolean pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint
        prs = gdk_pixbuf_get_rowstride(pb);
        p_pix = gdk_pixbuf_get_pixels(pb);
 
-       pp = p_pix + map_y * prs + (map_x * (p_alpha ? 4 : 3));
+       xoff = (size_t)map_x * (p_alpha ? 4 : 3);
+       yoff = (size_t)map_y * prs;
+       pp = p_pix + yoff + xoff;
        *r_mouse = *pp;
        pp++;
        *g_mouse = *pp;