cvs: gd /libgd gd_png.c

[email protected] ("Pierre-Alain Joye")
Newsgroups php.gd.cvs
Message-ID <cvspajoye1168193886@cvsserver>
pajoye		Sun Jan  7 18:18:06 2007 UTC

  Modified files:              
    /gd/libgd	gd_png.c 
  Log:
  - #32, malformed PNG image crashes (CRC error)
    test is following
pajoye-20070107181806.txt (text/plain, 13.4 KB)
http://cvs.php.net/viewvc.cgi/gd/libgd/gd_png.c?r1=1.20&r2=1.21&diff_format=u
Index: gd/libgd/gd_png.c
diff -u gd/libgd/gd_png.c:1.20 gd/libgd/gd_png.c:1.21
--- gd/libgd/gd_png.c:1.20	Sun Nov  5 15:01:47 2006
+++ gd/libgd/gd_png.c	Sun Jan  7 18:18:06 2007
@@ -1,4 +1,4 @@
-/* $Id: gd_png.c,v 1.20 2006/11/05 15:01:47 pajoye Exp $ */
+/* $Id: gd_png.c,v 1.21 2007/01/07 18:18:06 pajoye Exp $ */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -68,10 +68,8 @@
   fflush (stderr);
 
   jmpbuf_ptr = png_get_error_ptr (png_ptr);
-  if (jmpbuf_ptr == NULL)
-    {				/* we are completely hosed now */
-      fprintf (stderr,
-	       "gd-png:  EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n");
+  if (jmpbuf_ptr == NULL) {				/* we are completely hosed now */
+      fprintf (stderr, "gd-png:  EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n");
       fflush (stderr);
       exit (99);
     }
@@ -123,7 +121,7 @@
   png_byte sig[8];
   png_structp png_ptr;
   png_infop info_ptr;
-  png_uint_32 width, height, rowbytes;
+	png_uint_32 width, height, rowbytes, w, h;
   int bit_depth, color_type, interlace_type;
   int num_palette, num_trans;
   png_colorp palette;
@@ -147,40 +145,40 @@
 	return NULL;
   }
 
-  if (!png_check_sig (sig, 8))
-    return NULL;		/* bad signature */
+	if (!png_check_sig (sig, 8)) { /* bad signature */
+    	return NULL;		/* bad signature */
+	}
 
 #ifndef PNG_SETJMP_NOT_SUPPORTED
-  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct,
-				    gdPngErrorHandler, NULL);
+  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct, gdPngErrorHandler, NULL);
 #else
   png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 #endif
-  if (png_ptr == NULL)
-    {
+  if (png_ptr == NULL) {
       fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n");
       return NULL;
     }
 
   info_ptr = png_create_info_struct (png_ptr);
-  if (info_ptr == NULL)
-    {
+  if (info_ptr == NULL) {
       fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n");
       png_destroy_read_struct (&png_ptr, NULL, NULL);
+
       return NULL;
     }
 
   /* we could create a second info struct here (end_info), but it's only
    * useful if we want to keep pre- and post-IDAT chunk info separated
-   * (mainly for PNG-aware image editors and converters) */
+   * (mainly for PNG-aware image editors and converters) 
+	*/
 
   /* setjmp() must be called in every non-callback function that calls a
    * PNG-reading libpng function */
 #ifndef PNG_SETJMP_NOT_SUPPORTED
-  if (setjmp (gdPngJmpbufStruct.jmpbuf))
-    {
-      fprintf (stderr, "gd-png error: setjmp returns error condition\n");
+  if (setjmp (gdPngJmpbufStruct.jmpbuf)) {
+      fprintf (stderr, "gd-png error: setjmp returns error condition 1\n");
       png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+
       return NULL;
     }
 #endif
@@ -190,52 +188,61 @@
   png_set_read_fn (png_ptr, (void *) infile, gdPngReadData);
   png_read_info (png_ptr, info_ptr);	/* read all PNG info up to image data */
 
-  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
-		&interlace_type, NULL, NULL);
-  if ((color_type == PNG_COLOR_TYPE_RGB) ||
-      (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
-    {
+  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
+  if ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
       im = gdImageCreateTrueColor ((int) width, (int) height);
-    }
-  else
-    {
+    } else {
       im = gdImageCreate ((int) width, (int) height);
     }
-  if (im == NULL)
-    {
+  if (im == NULL) {
       fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n");
       png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
       gdFree (image_data);
       gdFree (row_pointers);
+
       return NULL;
     }
 
-  if (bit_depth == 16)
+  if (bit_depth == 16) {
     png_set_strip_16 (png_ptr);
-  else if (bit_depth < 8)
+  } else if (bit_depth < 8) {
     png_set_packing (png_ptr);	/* expand to 1 byte per pixel */
-  switch (color_type)
-    {
+	}
+
+	/* setjmp() must be called in every non-callback function that calls a
+	 * PNG-reading libpng function
+	 */
+#ifndef PNG_SETJMP_NOT_SUPPORTED
+	if (setjmp(gdPngJmpbufStruct.jmpbuf)) {
+		fprintf(stderr, "gd-png error: setjmp returns error condition 2");
+		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+		gdFree(image_data);
+		gdFree(row_pointers);
+		if (im) {
+			gdImageDestroy(im);
+		}
+		return NULL;
+	}
+#endif
+
+  switch (color_type) {
     case PNG_COLOR_TYPE_PALETTE:
       png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette);
 #ifdef DEBUG
-      fprintf (stderr, "gd-png color_type is palette, colors: %d\n",
-	       num_palette);
+      fprintf (stderr, "gd-png color_type is palette, colors: %d\n", num_palette);
 #endif /* DEBUG */
-      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
-	{
-	  /* gd 2.0: we support this rather thoroughly now. Grab the
-	     first fully transparent entry, if any, as the value of 
-	     the simple-transparency index, mostly for backwards
-	     binary compatibility. The alpha channel is where it's
-	     really at these days. */
+      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
+				/* gd 2.0: we support this rather thoroughly now. Grab the
+				 * first fully transparent entry, if any, as the value of
+				 * the simple-transparency index, mostly for backwards
+				 * binary compatibility. The alpha channel is where it's
+				 * really at these days.
+				 */
 	  int firstZero = 1;
 	  png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL);
-	  for (i = 0; i < num_trans; ++i)
-	    {
+	  for (i = 0; i < num_trans; ++i) {
 	      im->alpha[i] = gdAlphaMax - (trans[i] >> 1);
-	      if ((trans[i] == 0) && (firstZero))
-		{
+	      if ((trans[i] == 0) && (firstZero)) {
 		  /* 2.0.5: long-forgotten patch from Wez Furlong */
 		  transparent = i;
 		  firstZero = 0;
@@ -247,38 +254,31 @@
     case PNG_COLOR_TYPE_GRAY:
     case PNG_COLOR_TYPE_GRAY_ALPHA:
       /* create a fake palette and check for single-shade transparency */
-      if ((palette =
-	   (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL)
-	{
+      if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) {
 	  fprintf (stderr, "gd-png error: cannot allocate gray palette\n");
 	  png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
 	  return NULL;
 	}
       palette_allocated = TRUE;
-      if (bit_depth < 8)
-	{
+      if (bit_depth < 8) {
 	  num_palette = 1 << bit_depth;
-	  for (i = 0; i < 256; ++i)
-	    {
+	  for (i = 0; i < 256; ++i) {
 	      j = (255 * i) / (num_palette - 1);
 	      palette[i].red = palette[i].green = palette[i].blue = j;
 	    }
-	}
-      else
-	{
+	} else {
 	  num_palette = 256;
-	  for (i = 0; i < 256; ++i)
-	    {
+	  for (i = 0; i < 256; ++i) {
 	      palette[i].red = palette[i].green = palette[i].blue = i;
 	    }
 	}
-      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
-	{
+      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
 	  png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb);
-	  if (bit_depth == 16)	/* png_set_strip_16() not yet in effect */
+	  if (bit_depth == 16) {	/* png_set_strip_16() not yet in effect */
 	    transparent = trans_gray_rgb->gray >> 8;
-	  else
+	 } else {
 	    transparent = trans_gray_rgb->gray;
+	}
 	  /* Note slight error in 16-bit case:  up to 256 16-bit shades
 	   * may get mapped to a single 8-bit shade, and only one of them
 	   * is supposed to be transparent.  IOW, both opaque pixels and
@@ -297,18 +297,18 @@
       /* gd 2.0: we now support truecolor. See the comment above
          for a rare situation in which the transparent pixel may not
          work properly with 16-bit channels. */
-      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
-	{
+      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
 	  png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb);
-	  if (bit_depth == 16)	/* png_set_strip_16() not yet in effect */
+	  if (bit_depth == 16) {	/* png_set_strip_16() not yet in effect */
 	    transparent = gdTrueColor (trans_color_rgb->red >> 8,
 				       trans_color_rgb->green >> 8,
 				       trans_color_rgb->blue >> 8);
-	  else
+	 } else {
 	    transparent = gdTrueColor (trans_color_rgb->red,
 				       trans_color_rgb->green,
 				       trans_color_rgb->blue);
 	}
+	}
       break;
     }
 
@@ -319,52 +319,57 @@
   if (overflow2(rowbytes, height)) {
     png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
     return NULL;
-  }  
-  if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL)
-    {
+  }
+	image_data = (png_bytep) gdMalloc (rowbytes * height);
+  if (!image_data) {
       fprintf (stderr, "gd-png error: cannot allocate image data\n");
       png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+	if (im) {
+		gdImageDestroy(im);
+	}
       return NULL;
     }
   if (overflow2(height, sizeof (png_bytep))) {
     png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
     gdFree (image_data);
+	if (im) {
+		gdImageDestroy(im);
+	}
     return NULL;
-  }    
-  if ((row_pointers =
-       (png_bytepp) gdMalloc (height * sizeof (png_bytep))) == NULL)
-    {
+  }
+
+	row_pointers = (png_bytepp) gdMalloc (height * sizeof (png_bytep));    
+  if (!row_pointers) {
       fprintf (stderr, "gd-png error: cannot allocate row pointers\n");
       png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+	if (im) {
+		gdImageDestroy(im);
+	}
       gdFree (image_data);
       return NULL;
     }
 
   /* set the individual row_pointers to point at the correct offsets */
-  for (j = 0; j < height; ++j)
-    {
-      row_pointers[j] = image_data + j * rowbytes;
+	for (h = 0; h < height; ++h) {
+		row_pointers[h] = image_data + h * rowbytes;
     }
 
   png_read_image (png_ptr, row_pointers);	/* read whole image... */
   png_read_end (png_ptr, NULL);	/* ...done! */
 
-  if (!im->trueColor)
-    {
+  if (!im->trueColor) {
       im->colorsTotal = num_palette;
       /* load the palette and mark all entries "open" (unused) for now */
       open = im->open;
-      for (i = 0; i < num_palette; ++i)
-	{
+      for (i = 0; i < num_palette; ++i) {
 	  im->red[i] = palette[i].red;
 	  im->green[i] = palette[i].green;
 	  im->blue[i] = palette[i].blue;
 	  open[i] = 1;
 	}
-      for (i = num_palette; i < gdMaxColors; ++i)
-	{
+      for (i = num_palette; i < gdMaxColors; ++i) {
 	  open[i] = 1;
-	}
+		}
     }
   /* 2.0.12: Slaven Rezic: palette images are not the only images
      with a simple transparent color setting */
@@ -373,58 +378,50 @@
 
   /* can't nuke structs until done with palette */
   png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
-  switch (color_type)
-    {
+  switch (color_type) {
     case PNG_COLOR_TYPE_RGB:
-      for (j = 0; j < height; j++)
-	{
+			for (h = 0; h < height; h++) {
 	  int boffset = 0;
-	  for (i = 0; i < width; i++)
-	    {
-	      register png_byte r = row_pointers[j][boffset++];
-	      register png_byte g = row_pointers[j][boffset++];
-	      register png_byte b = row_pointers[j][boffset++];
-	      im->tpixels[j][i] = gdTrueColor (r, g, b);
+				for (w = 0; w < width; w++) {
+					register png_byte r = row_pointers[h][boffset++];
+					register png_byte g = row_pointers[h][boffset++];
+					register png_byte b = row_pointers[h][boffset++];
+					im->tpixels[h][w] = gdTrueColor (r, g, b);
 	    }
 	}
       break;
     case PNG_COLOR_TYPE_RGB_ALPHA:
-      for (j = 0; j < height; j++)
-	{
+			for (h = 0; h < height; h++) {
 	  int boffset = 0;
-	  for (i = 0; i < width; i++)
-	    {
-	      register png_byte r = row_pointers[j][boffset++];
-	      register png_byte g = row_pointers[j][boffset++];
-	      register png_byte b = row_pointers[j][boffset++];
-	      /* gd has only 7 bits of alpha channel resolution, and
-	         127 is transparent, 0 opaque. A moment of convenience, 
-	         a lifetime of compatibility. */
-	      register png_byte a = gdAlphaMax -
-		(row_pointers[j][boffset++] >> 1);
-	      im->tpixels[j][i] = gdTrueColorAlpha (r, g, b, a);
+				for (w = 0; w < width; w++) {
+					register png_byte r = row_pointers[h][boffset++];
+					register png_byte g = row_pointers[h][boffset++];
+					register png_byte b = row_pointers[h][boffset++];
+
+   /* gd has only 7 bits of alpha channel resolution, and
+	* 127 is transparent, 0 opaque. A moment of convenience,
+	*  a lifetime of compatibility.
+	*/
+
+					register png_byte a = gdAlphaMax - (row_pointers[h][boffset++] >> 1);
+					im->tpixels[h][w] = gdTrueColorAlpha(r, g, b, a);
 	    }
 	}
       break;
     default:
       /* Palette image, or something coerced to be one */
-      for (j = 0; j < height; ++j)
-	{
-	  for (i = 0; i < width; ++i)
-	    {
-	      register png_byte idx = row_pointers[j][i];
-	      im->pixels[j][i] = idx;
+			for (h = 0; h < height; ++h) {
+				for (w = 0; w < width; ++w) {
+					register png_byte idx = row_pointers[h][w];
+					im->pixels[h][w] = idx;
 	      open[idx] = 0;
 	    }
 	}
     }
 #ifdef DEBUG
-  if (!im->trueColor)
-    {
-      for (i = num_palette; i < gdMaxColors; ++i)
-	{
-	  if (!open[i])
-	    {
+  if (!im->trueColor) {
+      for (i = num_palette; i < gdMaxColors; ++i) {
+	  if (!open[i]) {
 	      fprintf (stderr,
 		       "gd-png warning: image data references out-of-range"
 		       " color index (%d)\n", i);
@@ -433,8 +430,9 @@
     }
 #endif
 
-  if (palette_allocated)
+  if (palette_allocated) {
     gdFree (palette);
+	}
   gdFree (image_data);
   gdFree (row_pointers);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.