Commits

Anonymous committed 1e2962e

- #32, malformed PNG image crashes (CRC error)
test is following

Comments (0)

Files changed (1)

   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);
     }
   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;
 	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
   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;
     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
       /* 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;
     }
 
   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 */
 
   /* 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);
     }
 #endif
 
-  if (palette_allocated)
+  if (palette_allocated) {
     gdFree (palette);
+	}
   gdFree (image_data);
   gdFree (row_pointers);