summaryrefslogtreecommitdiff
path: root/gdk-pixbuf/gdk-pixbuf-data.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdk-pixbuf/gdk-pixbuf-data.c')
-rw-r--r--gdk-pixbuf/gdk-pixbuf-data.c130
1 files changed, 105 insertions, 25 deletions
diff --git a/gdk-pixbuf/gdk-pixbuf-data.c b/gdk-pixbuf/gdk-pixbuf-data.c
index 94db20f376..a1b0232400 100644
--- a/gdk-pixbuf/gdk-pixbuf-data.c
+++ b/gdk-pixbuf/gdk-pixbuf-data.c
@@ -23,6 +23,7 @@
#include <config.h>
#include "gdk-pixbuf.h"
#include "gdk-pixbuf-private.h"
+#include "gdk-pixbuf-i18n.h"
#include <stdlib.h>
#include <string.h>
@@ -106,7 +107,10 @@ read_bool (const guchar **p)
}
static GdkPixbuf*
-read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
+read_raw_inline (const guchar *data,
+ gboolean copy_pixels,
+ int length,
+ GError **error)
{
GdkPixbuf *pixbuf;
const guchar *p = data;
@@ -116,6 +120,11 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
if (length >= 0 && length < 12) {
/* Not enough buffer to hold the width/height/rowstride */
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image data is partially missing"));
+
return NULL;
}
@@ -123,9 +132,14 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
width = read_int (&p);
height = read_int (&p);
- if (rowstride < width)
+ if (rowstride < width) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an incorrect pixel rowstride, perhaps the data was corrupted somehow."));
return NULL; /* bad data from untrusted source. */
-
+ }
+
/* rowstride >= width, so we can trust width */
length -= 12;
@@ -133,37 +147,71 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
/* There's some better way like G_MAXINT/height > rowstride
* but I'm not sure it works, so stick to this for now.
*/
- if (((double)height) * ((double)rowstride) > (double)G_MAXINT)
+ if (((double)height) * ((double)rowstride) > (double)G_MAXINT) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image size is impossibly large, perhaps the data was corrupted somehow"));
+
return NULL; /* overflow */
-
+ }
+
if (length >= 0 &&
length < (height * rowstride + 13)) {
/* Not enough buffer to hold the remaining header
* information plus the data.
*/
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image data is partially missing, probably it was ocorrupted somehow."));
return NULL;
}
-
+
/* Read the remaining 13 bytes of header information */
has_alpha = read_bool (&p) != FALSE;
colorspace = read_int (&p);
n_channels = read_int (&p);
bits_per_sample = read_int (&p);
-
- if (colorspace != GDK_COLORSPACE_RGB)
+
+ if (colorspace != GDK_COLORSPACE_RGB) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an unknown colorspace code (%d), perhaps the image data was corrupted"),
+ colorspace);
return NULL;
+ }
- if (bits_per_sample != 8)
+ if (bits_per_sample != 8) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an improper number of bits per sample (%d), perhaps the image data was corrupted"),
+ bits_per_sample);
return NULL;
-
- if (has_alpha && n_channels != 4)
+ }
+
+ if (has_alpha && n_channels != 4) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an improper number of channels (%d), perhaps the image data was corrupted"),
+ n_channels);
return NULL;
-
- if (!has_alpha && n_channels != 3)
+ }
+
+ if (!has_alpha && n_channels != 3) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an improper number of channels (%d), perhaps the image data was corrupted"),
+ n_channels);
return NULL;
-
+ }
+
if (copy_pixels) {
guchar *pixels;
gint dest_rowstride;
@@ -172,10 +220,19 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
pixbuf = gdk_pixbuf_new (colorspace,
has_alpha, bits_per_sample,
width, height);
-
+
+ if (pixbuf == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Not enough memory to store a %d by %d image; try exiting some applications to free memory."),
+ width, height);
+ return NULL;
+ }
+
pixels = gdk_pixbuf_get_pixels (pixbuf);
dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
+
for (row = 0; row < height; row++) {
memcpy (pixels, p, rowstride);
pixels += dest_rowstride;
@@ -190,32 +247,42 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
rowstride,
NULL, NULL);
}
-
+
return pixbuf;
}
/**
* gdk_pixbuf_new_from_inline:
- * @data: An inlined GdkPixbuf
+ * @inline_pixbuf: An inlined GdkPixbuf
* @copy_pixels: whether to copy the pixels out of the inline data, or to use them in-place
+ * @length: length of the inline data
+ * @error: return location for error
*
* Create a #GdkPixbuf from a custom format invented to store pixbuf
- * data in C program code. This library comes with a program called "make-inline-pixbuf"
- * that can write out a variable definition containing an inlined pixbuf.
- * This is useful if you want to ship a program with images, but
- * don't want to depend on any external files.
+ * data in C program code. This library comes with a program called
+ * "make-inline-pixbuf" that can write out a variable definition
+ * containing an inlined pixbuf. This is useful if you want to ship a
+ * program with images, but don't want to depend on any external
+ * files.
*
* The inline data format contains the pixels in #GdkPixbuf's native
* format. Since the inline pixbuf is read-only static data, you
* don't need to copy it unless you intend to write to it.
*
+ * If you create a pixbuf from const inline data compiled into your
+ * program, it's probably safe to ignore errors, since things will
+ * always succeed. For non-const inline data, you could get out of
+ * memory. For untrusted inline data located at runtime, you could
+ * have corrupt inline data in addition.
+ *
* Return value: A newly-created #GdkPixbuf structure with a reference count of
- * 1.
+ * 1, or NULL If error is set.
**/
GdkPixbuf*
gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
gboolean copy_pixels,
- int length)
+ int length,
+ GError **error)
{
const guchar *p;
GdkPixbuf *pixbuf;
@@ -225,12 +292,20 @@ gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
/* not enough bytes to contain even the magic number
* and format code.
*/
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image contained no data."));
return NULL;
}
p = inline_pixbuf;
if (read_int (&p) != GDK_PIXBUF_INLINE_MAGIC_NUMBER) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image isn't in the correct format (inline GdkPixbuf format)"));
return NULL;
}
@@ -239,10 +314,15 @@ gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
switch (format)
{
case GDK_PIXBUF_INLINE_RAW:
- pixbuf = read_raw_inline (p, copy_pixels, length - 8);
+ pixbuf = read_raw_inline (p, copy_pixels, length - 8, error);
break;
default:
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("This version of the software is unable to read images with type code %d"),
+ format);
return NULL;
}