Skip to content

Commit

Permalink
Properly open and work with large TIFF files.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
pelikan authored and mowgli committed Jun 19, 2016
1 parent 0b044d1 commit 9a24b29
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/filedata.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
24 changes: 13 additions & 11 deletions src/image_load_tiff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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)
{
Expand Down Expand Up @@ -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);
}
Expand Down
5 changes: 4 additions & 1 deletion src/pixbuf-renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 9a24b29

Please sign in to comment.