GNOME Bugzilla – Bug 703220
(CVE-2013-7447) Memory allocation integer overflow in gdk_cairo_set_source_pixbuf on large pixbufs
Last modified: 2016-04-05 17:30:07 UTC
When supplying large pixbufs to gdk_cairo_set_source_pixbuf, gdkcairo tries to allocate an immense number of bytes due to an integer overflow. I first encountered this trying to open a 22,568 x 25,994 pixels RGB image in EOG, later reproduced it by a generated 25,000 x 25,000 pixel RGB PNG: (eog:18754): GLib-ERROR **: /build/buildd/glib2.0-2.36.0/./glib/gmem.c:165: failed to allocate 18446744071914584320 bytes I traced the problem down to gdk/gdkcairo.c: gint height; int cairo_stride; [...] cairo_pixels = g_malloc (height * cairo_stride); Since the width and height of my image are 25,000 pixels, the stride turns out to be 100,000 bytes. 25,000 * 100,000 is more than 2^31, leaving us with a negative result, which is then cast to a gsize (unsigned long int) to be passed to g_malloc, resulting in the aforementioned huge number. By casting cairo_stride to gsize before the multiplication we avoid this problem (and my images seem to open just fine). The patch attached does just this.
Created attachment 247937 [details] [review] Proposed patch to fix the integer overflow
Created attachment 247938 [details] A generated (and strictly speaking invalid) RGB PNG file containing 23,171 x 23,171 pixels, triggering this bug when opened in EOG. Find attached a minimal test case. To reproduce this bug, just open the attached file in EOG (or any other program that uses gdk_cairo_set_source_pixbuf accordingly) - it will crash trying to allocate about 2^64 bytes of memory. The attached PNG is quite likely not a valid file (it contains way too little data for its dimensions), but it works.
Should use g_malloc_n instead of casting.
Review of attachment 247937 [details] [review]: set state according to comment
This is still affecting to gtk2: $ grep -r "cairo_pixels" -- * gdk/gdkcairo.c: guchar *cairo_pixels; gdk/gdkcairo.c: cairo_pixels = g_malloc (height * cairo_stride); gdk/gdkcairo.c: surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels, gdk/gdkcairo.c: cairo_pixels, (cairo_destroy_func_t)g_free); gdk/gdkcairo.c: g_free (cairo_pixels); gdk/gdkcairo.c: guchar *q = cairo_pixels; gdk/gdkcairo.c: cairo_pixels += cairo_stride; Thanks :)
Commit was cherry-picked by Matthias to the gtk-2-24 branch: 407c89863d08780861d120f8ccfc8e13582a2fda
Ah, I see it was committed just after 2.34.30 release... then, it will be solved in .31 Thanks! :)