1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
--- a/gdk-pixbuf/io-gif.c
+++ b/gdk-pixbuf/io-gif.c
@@ -817,6 +817,35 @@
context->user_data);
}
+/* Available in glib since 2.48 */
+static inline gboolean _g_uint64_checked_mul (guint64 *dest, guint64 a, guint64 b) {
+ *dest = a * b; return !a || *dest / a == b; }
+
+/* Available in gdk-pixbuf 2.36.8 */
+static gint
+_gdk_pixbuf_calculate_rowstride (GdkColorspace colorspace,
+ gboolean has_alpha,
+ int bits_per_sample,
+ int width,
+ int height)
+{
+ unsigned int channels;
+
+ g_return_val_if_fail (colorspace == GDK_COLORSPACE_RGB, -1);
+ g_return_val_if_fail (bits_per_sample == 8, -1);
+ g_return_val_if_fail (width > 0, -1);
+ g_return_val_if_fail (height > 0, -1);
+
+ channels = has_alpha ? 4 : 3;
+
+ /* Overflow? */
+ if (width > (G_MAXINT - 3) / channels)
+ return -1;
+
+ /* Always align rows to 32-bit boundaries */
+ return (width * channels + 3) & ~3;
+}
+
static int
gif_get_lzw (GifContext *context)
{
@@ -850,13 +879,29 @@
pixels[2] = 0;
pixels[3] = 0;
}
- } else
- context->frame->pixbuf =
- gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- TRUE,
- 8,
- context->frame_len,
- context->frame_height);
+ } else {
+ int rowstride;
+ guint64 len;
+
+ rowstride = _gdk_pixbuf_calculate_rowstride (GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ context->frame_len,
+ context->frame_height);
+ if (rowstride > 0 &&
+ _g_uint64_checked_mul (&len, rowstride, context->frame_height) &&
+ len <= G_MAXINT) {
+ context->frame->pixbuf =
+ gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ context->frame_len,
+ context->frame_height);
+ } else {
+ context->frame->pixbuf = NULL;
+ }
+ }
+
if (!context->frame->pixbuf) {
g_free (context->frame);
g_set_error_literal (context->error,
|