diff --git a/libs/tk/ydk-pixbuf/io-xpm.c b/libs/tk/ydk-pixbuf/io-xpm.c index 43dee42603..27add284ca 100644 --- a/libs/tk/ydk-pixbuf/io-xpm.c +++ b/libs/tk/ydk-pixbuf/io-xpm.c @@ -178,7 +178,6 @@ parse_color (const char *spec, XPMColor *colorPtr) { if (spec[0] == '#') { - char fmt[16]; int i, red, green, blue; if ((i = strlen (spec + 1)) % 3) { @@ -186,25 +185,27 @@ parse_color (const char *spec, } i /= 3; - g_snprintf (fmt, 16, "%%%dx%%%dx%%%dx", i, i, i); - - if (sscanf (spec + 1, fmt, &red, &green, &blue) != 3) { - return FALSE; - } if (i == 4) { + if (sscanf (spec + 1, "%4x%4x%4x", &red, &green, &blue) != 3) + return FALSE; colorPtr->red = red; colorPtr->green = green; colorPtr->blue = blue; } else if (i == 1) { + if (sscanf (spec + 1, "%1x%1x%1x", &red, &green, &blue) != 3) + return FALSE; colorPtr->red = (red * 65535) / 15; colorPtr->green = (green * 65535) / 15; colorPtr->blue = (blue * 65535) / 15; - } else if (i == 2) - { + } else if (i == 2) { + if (sscanf (spec + 1, "%2x%2x%2x", &red, &green, &blue) != 3) + return FALSE; colorPtr->red = (red * 65535) / 255; colorPtr->green = (green * 65535) / 255; colorPtr->blue = (blue * 65535) / 255; } else /* if (i == 3) */ { + if (sscanf (spec + 1, "%3x%3x%3x", &red, &green, &blue) != 3) + return FALSE; colorPtr->red = (red * 65535) / 4095; colorPtr->green = (green * 65535) / 4095; colorPtr->blue = (blue * 65535) / 4095; @@ -400,7 +401,8 @@ file_buffer (enum buf_op op, gpointer handle) case op_cmap: xpm_seek_char (h->infile, '"'); - fseek (h->infile, -1, SEEK_CUR); + if (fseek (h->infile, -1, SEEK_CUR) != 0) + return NULL; /* Fall through to the xpm_read_string. */ case op_body: @@ -455,7 +457,8 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl GHashTable *color_hash; XPMColor *colors, *color, *fallbackcolor; guchar *pixtmp; - GdkPixbuf *pixbuf; + GdkPixbuf *pixbuf = NULL; + gint rowstride; fallbackcolor = NULL; @@ -493,7 +496,16 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl return NULL; } - if (cpp <= 0 || cpp >= 32) { + /* Check from libXpm's ParsePixels() */ + if ((h > 0 && w >= UINT_MAX / h) || + w * h >= UINT_MAX / sizeof(unsigned int)) { + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Invalid XPM header")); + return NULL; + } + if (cpp <= 0 || cpp >= 32 || w >= G_MAXINT / cpp) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, @@ -542,10 +554,7 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Cannot read XPM colormap")); - g_hash_table_destroy (color_hash); - g_free (name_buf); - g_free (colors); - return NULL; + goto out; } color = &colors[cnt]; @@ -580,20 +589,25 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Cannot allocate memory for loading XPM image")); - g_hash_table_destroy (color_hash); - g_free (colors); - g_free (name_buf); - return NULL; + goto out; } + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + wbytes = w * cpp; for (ycnt = 0; ycnt < h; ycnt++) { - pixtmp = pixbuf->pixels + ycnt * pixbuf->rowstride; + pixtmp = gdk_pixbuf_get_pixels (pixbuf) + ycnt * rowstride; buffer = (*get_buf) (op_body, handle); - if ((!buffer) || (strlen (buffer) < wbytes)) - continue; + if ((!buffer) || (strlen (buffer) < wbytes)) { + /* Advertised width doesn't match pixels */ + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Dimensions do not match data")); + goto out; + } for (n = 0, xcnt = 0; n < wbytes; n += cpp, xcnt++) { strncpy (pixel_str, &buffer[n], cpp); @@ -630,6 +644,14 @@ pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handl } return pixbuf; + +out: + g_hash_table_destroy (color_hash); + g_free (colors); + g_free (name_buf); + + g_clear_object (&pixbuf); + return NULL; } /* Shared library entry point for file loading */ @@ -742,7 +764,11 @@ gdk_pixbuf__xpm_image_stop_load (gpointer data, NULL, context->user_data); if (context->update_func) - (* context->update_func) (pixbuf, 0, 0, pixbuf->width, pixbuf->height, context->user_data); + (* context->update_func) (pixbuf, + 0, 0, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + context->user_data); g_object_unref (pixbuf); retval = TRUE;