diff options
author | Matthias Clasen <matthiasc@src.gnome.org> | 2001-08-20 06:47:28 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2001-08-20 06:47:28 +0000 |
commit | d504d82aa8d5cd87ae96753718635a8f1d2d70fe (patch) | |
tree | ee37e54857482ee8850151cf1f9cd332f04b38ed /gdk-pixbuf | |
parent | 9b14c046826ac88885fc7ad9bbd9deeecd06e142 (diff) | |
download | gdk-pixbuf-d504d82aa8d5cd87ae96753718635a8f1d2d70fe.tar.gz |
Add ico and wbmp tests. Fail with a suitable error if buffer allocation
* test-images.h, test-loaders.c: Add ico and wbmp tests.
* io-jpeg.c (gdk_pixbuf__jpeg_image_save): Fail with a suitable
error if buffer allocation fails.
* io-ico.c: Make .ICO loader more robust.
All of these are due to sandmann@daimi.au.dk (#50187)
Diffstat (limited to 'gdk-pixbuf')
-rw-r--r-- | gdk-pixbuf/io-ico.c | 160 | ||||
-rw-r--r-- | gdk-pixbuf/io-jpeg.c | 9 | ||||
-rw-r--r-- | gdk-pixbuf/test-images.h | 85 | ||||
-rw-r--r-- | gdk-pixbuf/test-loaders.c | 35 |
4 files changed, 237 insertions, 52 deletions
diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c index 6a2ca4884..364fcd9df 100644 --- a/gdk-pixbuf/io-ico.c +++ b/gdk-pixbuf/io-ico.c @@ -41,6 +41,7 @@ Known bugs: #include <string.h> #include "gdk-pixbuf-private.h" #include "gdk-pixbuf-io.h" +#include <errno.h> @@ -115,8 +116,8 @@ static void DumpBIH(unsigned char *BIH) /* Progressive loading */ struct headerpair { - guint width; - guint height; + gint width; + gint height; guint depth; guint Negative; /* Negative = 1 -> top down BMP, Negative = 0 -> bottom up BMP */ @@ -163,14 +164,27 @@ static gboolean gdk_pixbuf__ico_image_load_increment(gpointer data, const guchar * buf, guint size, GError **error); +static void +context_free (struct ico_progressive_state *context) +{ + if (context->LineBuf != NULL) + g_free (context->LineBuf); + context->LineBuf = NULL; + if (context->HeaderBuf != NULL) + g_free (context->HeaderBuf); + if (context->pixbuf) + gdk_pixbuf_unref (context->pixbuf); + g_free (context); +} + /* Shared library entry point --> Can go when generic_image_load enters gdk-pixbuf-io */ static GdkPixbuf * gdk_pixbuf__ico_image_load(FILE * f, GError **error) { - guchar *membuf; + guchar membuf [4096]; size_t length; struct ico_progressive_state *State; @@ -179,24 +193,35 @@ gdk_pixbuf__ico_image_load(FILE * f, GError **error) State = gdk_pixbuf__ico_image_begin_load(NULL, NULL, NULL, error); if (State == NULL) - return NULL; + return NULL; - membuf = g_malloc(4096); - - g_assert(membuf != NULL); - - while (feof(f) == 0) { + while (!feof(f)) { length = fread(membuf, 1, 4096, f); + if (ferror (f)) { + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Failure reading ICO: %s"), g_strerror (errno)); + context_free (State); + return NULL; + } if (length > 0) if (!gdk_pixbuf__ico_image_load_increment(State, membuf, length, error)) { - gdk_pixbuf__ico_image_stop_load (State, NULL); + context_free (State); return NULL; - } + } } - g_free(membuf); if (State->pixbuf != NULL) - gdk_pixbuf_ref(State->pixbuf); + gdk_pixbuf_ref (State->pixbuf); + else { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("ICO file was missing some data (perhaps it was truncated somehow?)")); + context_free (State); + return NULL; + } pb = State->pixbuf; @@ -205,7 +230,8 @@ gdk_pixbuf__ico_image_load(FILE * f, GError **error) } static void DecodeHeader(guchar *Data, gint Bytes, - struct ico_progressive_state *State) + struct ico_progressive_state *State, + GError **error) { /* For ICO's we have to be very clever. There are multiple images possible in an .ICO. For now, we select (in order of priority): @@ -225,7 +251,14 @@ static void DecodeHeader(guchar *Data, gint Bytes, State->HeaderSize = 6 + IconCount*16; if (State->HeaderSize>State->BytesInHeaderBuf) { - State->HeaderBuf=g_realloc(State->HeaderBuf,State->HeaderSize); + State->HeaderBuf=g_try_realloc(State->HeaderBuf,State->HeaderSize); + if (!State->HeaderBuf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Not enough memory to load icon")); + return; + } State->BytesInHeaderBuf = State->HeaderSize; } if (Bytes < State->HeaderSize) @@ -266,7 +299,14 @@ static void DecodeHeader(guchar *Data, gint Bytes, State->HeaderSize = State->DIBoffset + 40; /* 40 = sizeof(InfoHeader) */ if (State->HeaderSize>State->BytesInHeaderBuf) { - State->HeaderBuf=g_realloc(State->HeaderBuf,State->HeaderSize); + State->HeaderBuf=g_try_realloc(State->HeaderBuf,State->HeaderSize); + if (!State->HeaderBuf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Not enough memory to load icon")); + return; + } State->BytesInHeaderBuf = State->HeaderSize; } if (Bytes<State->HeaderSize) @@ -282,9 +322,23 @@ static void DecodeHeader(guchar *Data, gint Bytes, State->Header.width = (int)(BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]); + if (State->Header.width == 0) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Icon has zero width")); + return; + } State->Header.height = (int)(BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) + (BIH[8])/2; /* /2 because the BIH height includes the transparency mask */ + if (State->Header.height == 0) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Icon has zero height")); + return; + } State->Header.depth = (BIH[15] << 8) + (BIH[14]);; State->Type = State->Header.depth; @@ -308,7 +362,14 @@ static void DecodeHeader(guchar *Data, gint Bytes, State->HeaderSize+=I; if (State->HeaderSize>State->BytesInHeaderBuf) { - State->HeaderBuf=g_realloc(State->HeaderBuf,State->HeaderSize); + State->HeaderBuf=g_try_realloc(State->HeaderBuf,State->HeaderSize); + if (!State->HeaderBuf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Not enough memory to load icon")); + return; + } State->BytesInHeaderBuf = State->HeaderSize; } if (Bytes < State->HeaderSize) @@ -316,7 +377,12 @@ static void DecodeHeader(guchar *Data, gint Bytes, if ((BIH[16] != 0) || (BIH[17] != 0) || (BIH[18] != 0) || (BIH[19] != 0)) { - g_assert(0); /* Compressed icons aren't allowed */ + /* FIXME: is this the correct message? */ + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Compressed icons are not supported")); + return; } /* Negative heights mean top-down pixel-order */ @@ -327,6 +393,8 @@ static void DecodeHeader(guchar *Data, gint Bytes, if (State->Header.width < 0) { State->Header.width = -State->Header.width; } + g_assert (State->Header.width > 0); + g_assert (State->Header.height > 0); if (State->Type == 24) State->LineWidth = State->Header.width * 3; @@ -346,8 +414,16 @@ static void DecodeHeader(guchar *Data, gint Bytes, State->LineWidth = (State->LineWidth / 4) * 4 + 4; - if (State->LineBuf == NULL) - State->LineBuf = g_malloc(State->LineWidth); + if (State->LineBuf == NULL) { + State->LineBuf = g_try_malloc(State->LineWidth); + if (!State->LineBuf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Not enough memory to load icon")); + } + return; + } g_assert(State->LineBuf != NULL); @@ -355,8 +431,8 @@ static void DecodeHeader(guchar *Data, gint Bytes, if (State->pixbuf == NULL) { State->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, - (gint) State->Header.width, - (gint) State->Header.height); + State->Header.width, + State->Header.height); if (State->prepared_func != NULL) /* Notify the client that we are ready to go */ @@ -388,7 +464,14 @@ gdk_pixbuf__ico_image_begin_load(ModulePreparedNotifyFunc prepared_func, context->user_data = user_data; context->HeaderSize = 54; - context->HeaderBuf = g_malloc(14 + 40 + 4*256 + 512); + context->HeaderBuf = g_try_malloc(14 + 40 + 4*256 + 512); + if (!context->HeaderBuf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Not enough memory to load ICO file")); + return NULL; + } /* 4*256 for the colormap */ context->BytesInHeaderBuf = 14 + 40 + 4*256 + 512 ; context->HeaderDone = 0; @@ -425,18 +508,8 @@ gboolean gdk_pixbuf__ico_image_stop_load(gpointer data, */ g_return_val_if_fail(context != NULL, TRUE); - - if (context->LineBuf != NULL) - g_free(context->LineBuf); - context->LineBuf = NULL; - if (context->HeaderBuf != NULL) - g_free(context->HeaderBuf); - - if (context->pixbuf) - gdk_pixbuf_unref(context->pixbuf); - - g_free(context); - + + context_free (context); return TRUE; } @@ -672,9 +745,8 @@ gdk_pixbuf__ico_image_load_increment(gpointer data, size -= BytesToCopy; buf += BytesToCopy; context->HeaderDone += BytesToCopy; - - } else - { + } + else { BytesToCopy = context->LineWidth - context->LineDone; if (BytesToCopy > size) @@ -696,11 +768,15 @@ gdk_pixbuf__ico_image_load_increment(gpointer data, } - if (context->HeaderDone >= 6) + if (context->HeaderDone >= 6) { + GError *decode_err = NULL; DecodeHeader(context->HeaderBuf, - context->HeaderDone, context); - - + context->HeaderDone, context, &decode_err); + if (decode_err) { + g_propagate_error (error, decode_err); + return FALSE; + } + } } return TRUE; diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index c707d347a..6864a7895 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -693,7 +693,14 @@ gdk_pixbuf__jpeg_image_save (FILE *f, g_return_val_if_fail (pixels != NULL, FALSE); /* allocate a small buffer to convert image data */ - buf = g_malloc (w * 3 * sizeof (guchar)); + buf = g_try_malloc (w * 3 * sizeof (guchar)); + if (!buf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Couldn't allocate memory for loading JPEG file")); + return FALSE; + } /* set up error handling */ jerr.pub.error_exit = fatal_error_handler; diff --git a/gdk-pixbuf/test-images.h b/gdk-pixbuf/test-images.h index 8c200cb7f..3ecd8db4e 100644 --- a/gdk-pixbuf/test-images.h +++ b/gdk-pixbuf/test-images.h @@ -825,6 +825,91 @@ static unsigned char const tiff1_test_1[] = { 0 }; +static unsigned char const valid_ico_test[] = { + 0, 0, 1, 0, 1, 0, 16, 16, 16, 0, 0, 0, 0, 0, 40, 1, 0, 0, 22, 0, 0, + 0, 40, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 0, 0, 128, 0, 0, 0, 128, 128, 0, 128, 0, 0, 0, 128, + 0, 128, 0, 128, 128, 0, 0, 192, 192, 192, 0, 128, 128, 128, 0, 0, 0, + 255, 0, 0, 255, 0, 0, 0, 255, 255, 0, 255, 0, 0, 0, 255, 0, 255, 0, + 255, 255, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 153, 153, 153, 9, 144, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 153, 0, + 0, 153, 0, 0, 0, 9, 153, 144, 0, 153, 144, 0, 0, 153, 144, 153, 0, + 9, 144, 0, 9, 153, 0, 9, 144, 9, 153, 0, 153, 144, 0, 153, 153, 153, + 153, 153, 153, 153, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 240, 55, 0, 0, 240, + 39, 0, 0, 252, 123, 0, 0, 252, 113, 0, 0, 248, 48, 0, 0, 241, 24, 0, + 0, 227, 136, 0, 0, 129, 0, 0, 0, 1, 255, 0, 0, 255, 255, 0, 0, 255, + 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 +}; + +static unsigned char const ico_test_1[] = { + 0, 0, 1, 0, 1, 0, 16, 16, 16, 0, 0, 0, 0, 0, 40, 1, 0, 0, 22, 0, + 0, 0, 40, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, 0, 1, 0, 4, 0, 0, 222, + 0, 0, 128, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128, 0, 0, 0, 128, 128, 0, 128, 0, + 0, 0, 128, 0, 128, 0, 128, 128, 0, 0, 192, 192, 192, 0, 128, 128, + 128, 0, 0, 0, 255, 0, 0, 255, 0, 0, 0, 255, 255, 0, 255, 0, 0, 0, + 255, 0 , 255, 0, 255, 255, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 153, 153, 153, 9, 144, 0, 0, 0, 0, 153, 0, 0, + 0, 0, 0, 0, 0, 153, 0, 0, 153, 0, 0, 0, 9, 153, 144, 0, 153, 144, + 0, 0, 153, 144, 153, 251, 9, 144, 0, 9, 153, 0, 9, 144, 9, 153 , + 0, 153, 144, 0, 153, 153, 153, 153, 153, 153, 153, 144, 0, 0, 0, + 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 240, 55, 0, 0, 240, 39, 0, 0, 252, 123, 0, 0, 252, + 113, 0, 0, 248, 48, 0, 0, 241, 24, 0, 0, 227, 136, 0, 0 , 129, 0, + 0, 0, 1, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, + 0, 255, 255, 0, 0 +}; + +static unsigned char const wbmp_test_1[] = { + 0, 0, 189, 179, 1, 0, 16, 180, 16, 0, 0, 230, 0, 0, 40, 1, 0, 0, + 22, 0, 0, 115, 40, 0, 0, 0, 16, 0, 0, 0, 32, 56, 0, 0, 1, 70, 4, + 92, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 128, 0, 0, 128, 0, 0, 135, 128, + 128, 0, 128, 0, 0, 0, 248, 0, 128, 0, 128, 128, 0, 154, 84, 192, + 176, 0, 128, 128, 128, 0, 0, 0, 255, 0, 0, 255, 151, 0, 0, 161, + 255, 0, 255, 0, 0, 0, 255, 0, 255, 0, 255, 255, 0, 0, 255, 250, + 255, 0, 0, 159, 0, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 148, + 0, 0, 0, 24, 0, 187, 0, 229, 0, 0, 0, 0, 0, 67, 0, 90, 0, 65, 153, + 153, 9, 144, 205, 236, 0, 0, 153, 0, 0, 0, 0, 0, 0, 251, 249, 0, + 0, 194, 0, 97, 0, 9, 153, 144, 0, 153, 144, 0, 255, 153, 144, 153, + 150, 9, 144, 0, 9, 153, 141, 9, 198, 9, 153, 0, 153, 153, 208, + 153, 153, 233, 239, 153, 153, 153, 144, 0, 0, 71, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 61, 0, 0, 0, 0, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 171, 235, 0, 0, 103, 255, 0, 60, 255, 255, 0, + 0, 240, 55, 0, 41, 240, 39, 220, 0, 252, 123, 0, 0, 58, 113, 0, + 178, 248, 48, 233, 0, 241, 183, 42, 0, 130, 136, 0, 0, 129, 88, 0, + 0, 1, 255, 0, 0, 175, 93, 26, 0, 255, 255, 0, 149, 255, 255, 0, + 198, 212, 255, 0, 0, +}; + +static unsigned char const wbmp_test_2[] = { + 0, 0, 1, 111, 172, 0, 16, 16, 227, 0, 162, 150, 0, 24, 40, 208, 0, + 0, 22, 0, 0, 0, 40, 9, 0, 0, 16, 0, 221, 55, 32, 0, 0, 49, 1, 0, + 4, 0, 0, 0, 171, 0, 128, 0, 0, 24, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 128, 0, 0, 128, 0, 0, 0, 128, + 128, 0, 128, 0, 0, 0, 128, 107, 128, 0, 128, 128, 0, 0, 192, 248, + 192, 234, 128, 128, 128, 209, 0, 28, 255, 0, 0, 255, 0, 0, 0, 255, + 255, 0, 255, 0, 0, 0, 102, 0, 255, 0, 130, 255, 0, 0, 255, 255, + 255, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 232, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 81, 0, 153, 153, 153, + 99, 144, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 153, + 255, 0, 0, 10, 153, 144, 0, 153, 144, 0, 0, 153, 144, 153, 96, 9, + 144, 0, 9, 153, 0, 9, 144, 9, 153, 0, 153, 144, 0, 153, 254, 153, + 153, 153, 153, 153, 144, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 47, 17, 0, 0, 0, 0, 0, 0, 250, 93, 47, 0, + 133, 28, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 240, + 55, 211, 0, 240, 39, 0, 169, 252, 123, 0, 0, 252, 118, 0, 0, 248, + 48, 26, 0, 122, 24, 0, 0, 227, 108, 0, 0, 129, 0, 0, 133, 1, 255, + 0, 0, 142, 255, 0, 0, 255, 255, 88, 40, 120, 64, 0, 178, 168, 255, + 151, 147 +}; + static unsigned char const valid_jpeg_test[] = { JPEG_HEADER, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, 72, 0, 72, 0, 0, diff --git a/gdk-pixbuf/test-loaders.c b/gdk-pixbuf/test-loaders.c index a3de2584d..12385b23a 100644 --- a/gdk-pixbuf/test-loaders.c +++ b/gdk-pixbuf/test-loaders.c @@ -265,18 +265,19 @@ randomly_modify (const guchar *image, guint size, gboolean verbose) { int j; - guint index = rand () % size; - guchar byte = rand () % 256; - + guint index = g_random_int_range (0, size); + guchar byte = g_random_int_range (0, 256); img_copy[index] = byte; if (verbose) - g_print ("%d\n", i); - if (verbose) - for (j = 0; j < size; j++) - g_print ("%u, ", img_copy[j]); - + { + g_print ("img no %d\n", i); + for (j = 0; j < size; j++) + g_print ("%u, ", img_copy[j]); + g_print ("\n\n"); + } + test_loader (img_copy, size, FALSE); } g_free (img_copy); @@ -383,7 +384,16 @@ main (int argc, char **argv) TEST (valid_png_test, TRUE); TEST (png_test_1, FALSE); - + + TEST (valid_ico_test, TRUE); + + TEST (ico_test_1, FALSE); + +#if 0 + TEST (wbmp_test_1, FALSE); + TEST (wbmp_test_2, FALSE); +#endif + #if 0 TEST (png_test_2, FALSE); #endif @@ -399,6 +409,13 @@ main (int argc, char **argv) TEST_RANDOMLY_MODIFIED (valid_tiff1_test, FALSE); #endif +#if 0 + TEST_RANDOMLY_MODIFIED (valid_ico_test, TRUE); /* The ico loader does not seem to + * break, but the image tend to + * mutate into a wbmp image, and + * the wbmp loader is broken + */ +#endif TEST_RANDOMLY_MODIFIED (valid_jpeg_test, FALSE); // The jpeg loader does not break #if 0 |