Changed signature to return success and set a GError parameter, adjusted

* io-png.c (setup_png_transformations): Changed signature to
	return success and set a GError parameter, adjusted all callers.
	Also work around a possible FPE in libpng and always check that
	the new info is sane.
This commit is contained in:
Matthias Clasen 2002-03-25 00:15:00 +00:00
parent ec1f7614ff
commit 2a8fc72b0d
2 changed files with 49 additions and 26 deletions

View File

@ -1,3 +1,10 @@
2002-03-25 Matthias Clasen <maclas@gmx.de>
* io-png.c (setup_png_transformations): Changed signature to
return success and set a GError parameter, adjusted all callers.
Also work around a possible FPE in libpng and always check that
the new info is sane.
2002-03-23 Matthias Clasen <maclas@gmx.de> 2002-03-23 Matthias Clasen <maclas@gmx.de>
* io-wbmp.c (gdk_pixbuf__wbmp_image_load_increment): * io-wbmp.c (gdk_pixbuf__wbmp_image_load_increment):

View File

@ -32,20 +32,29 @@
static void static gboolean
setup_png_transformations(png_structp png_read_ptr, png_infop png_info_ptr, setup_png_transformations(png_structp png_read_ptr, png_infop png_info_ptr,
gboolean *fatal_error_occurred, GError **error,
png_uint_32* width_p, png_uint_32* height_p, png_uint_32* width_p, png_uint_32* height_p,
int* color_type_p) int* color_type_p)
{ {
png_uint_32 width, height; png_uint_32 width, height;
int bit_depth, color_type, interlace_type, compression_type, filter_type; int bit_depth, color_type, interlace_type, compression_type, filter_type;
#ifndef G_DISABLE_CHECKS
int channels; int channels;
#endif
/* Get the image info */ /* Get the image info */
/* Must check bit depth, since png_get_IHDR generates an
FPE on bit_depth 0.
*/
bit_depth = png_get_bit_depth (png_read_ptr, png_info_ptr);
if (bit_depth < 1 || bit_depth > 16) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Bits per channel of PNG image is invalid."));
return FALSE;
}
png_get_IHDR (png_read_ptr, png_info_ptr, png_get_IHDR (png_read_ptr, png_info_ptr,
&width, &height, &width, &height,
&bit_depth, &bit_depth,
@ -118,29 +127,42 @@ setup_png_transformations(png_structp png_read_ptr, png_infop png_info_ptr,
*height_p = height; *height_p = height;
*color_type_p = color_type; *color_type_p = color_type;
#ifndef G_DISABLE_CHECKS
/* Check that the new info is what we want */ /* Check that the new info is what we want */
if (width == 0 || height == 0) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Transformed PNG has zero width or height."));
return FALSE;
}
if (bit_depth != 8) { if (bit_depth != 8) {
g_warning("Bits per channel of transformed PNG is %d, not 8.", bit_depth); g_set_error (error,
*fatal_error_occurred = TRUE; GDK_PIXBUF_ERROR,
return; GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Bits per channel of transformed PNG is not 8."));
return FALSE;
} }
if ( ! (color_type == PNG_COLOR_TYPE_RGB || if ( ! (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) ) { color_type == PNG_COLOR_TYPE_RGB_ALPHA) ) {
g_warning("Transformed PNG not RGB or RGBA."); g_set_error (error,
*fatal_error_occurred = TRUE; GDK_PIXBUF_ERROR,
return; GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Transformed PNG not RGB or RGBA."));
return FALSE;
} }
channels = png_get_channels(png_read_ptr, png_info_ptr); channels = png_get_channels(png_read_ptr, png_info_ptr);
if ( ! (channels == 3 || channels == 4) ) { if ( ! (channels == 3 || channels == 4) ) {
g_warning("Transformed PNG has %d channels, must be 3 or 4.", channels); g_set_error (error,
*fatal_error_occurred = TRUE; GDK_PIXBUF_ERROR,
return; GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Transformed PNG has unsupported number of channels, must be 3 or 4."));
return FALSE;
} }
#endif return TRUE;
} }
static void static void
@ -208,7 +230,6 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr, end_info; png_infop info_ptr, end_info;
png_textp text_ptr; png_textp text_ptr;
gboolean failed = FALSE;
gint i, ctype, bpp; gint i, ctype, bpp;
png_uint_32 w, h; png_uint_32 w, h;
png_bytepp volatile rows = NULL; png_bytepp volatile rows = NULL;
@ -249,9 +270,7 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
png_init_io (png_ptr, f); png_init_io (png_ptr, f);
png_read_info (png_ptr, info_ptr); png_read_info (png_ptr, info_ptr);
setup_png_transformations(png_ptr, info_ptr, &failed, &w, &h, &ctype); if (!setup_png_transformations(png_ptr, info_ptr, error, &w, &h, &ctype)) {
if (failed) {
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
return NULL; return NULL;
} }
@ -558,19 +577,16 @@ png_info_callback (png_structp png_read_ptr,
int i, num_texts; int i, num_texts;
int color_type; int color_type;
gboolean have_alpha = FALSE; gboolean have_alpha = FALSE;
gboolean failed = FALSE;
lc = png_get_progressive_ptr(png_read_ptr); lc = png_get_progressive_ptr(png_read_ptr);
if (lc->fatal_error_occurred) if (lc->fatal_error_occurred)
return; return;
setup_png_transformations(lc->png_read_ptr, if (!setup_png_transformations(lc->png_read_ptr,
lc->png_info_ptr, lc->png_info_ptr,
&failed, lc->error,
&width, &height, &color_type); &width, &height, &color_type)) {
if (failed) {
lc->fatal_error_occurred = TRUE; lc->fatal_error_occurred = TRUE;
return; return;
} }