]> git.saurik.com Git - wxWidgets.git/blobdiff - src/png/pngrutil.c
merged libpng 1.2.34 into the trunk (see #10043)
[wxWidgets.git] / src / png / pngrutil.c
index 99bca1933b4695d5fe7c9e93433b6cc7966a2ecb..3dfcb864ba067394f17e2d8e47dfb6694473dea9 100644 (file)
@@ -1,9 +1,9 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.2.19 August 19, 2007
+ * Last changed in libpng 1.2.34 [December 18, 2008]
  * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2008 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -13,7 +13,6 @@
 
 #define PNG_INTERNAL
 #include "png.h"
-
 #if defined(PNG_READ_SUPPORTED)
 
 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
@@ -30,7 +29,7 @@ __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **end
    wchar_t *str, *end;
 
    len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
-   str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
+   str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
    if ( NULL != str )
    {
       MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
@@ -49,7 +48,15 @@ __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **end
 png_uint_32 PNGAPI
 png_get_uint_31(png_structp png_ptr, png_bytep buf)
 {
+#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
    png_uint_32 i = png_get_uint_32(buf);
+#else
+   /* Avoid an extra function call by inlining the result. */
+   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
+      ((png_uint_32)(*(buf + 1)) << 16) +
+      ((png_uint_32)(*(buf + 2)) << 8) +
+      (png_uint_32)(*(buf + 3));
+#endif
    if (i > PNG_UINT_31_MAX)
      png_error(png_ptr, "PNG unsigned integer out of range.");
    return (i);
@@ -92,11 +99,40 @@ png_get_uint_16(png_bytep buf)
 }
 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
 
+/* Read the chunk header (length + type name).
+ * Put the type name into png_ptr->chunk_name, and return the length.
+ */
+png_uint_32 /* PRIVATE */
+png_read_chunk_header(png_structp png_ptr)
+{
+   png_byte buf[8];
+   png_uint_32 length;
+
+   /* read the length and the chunk name */
+   png_read_data(png_ptr, buf, 8);
+   length = png_get_uint_31(png_ptr, buf);
+
+   /* put the chunk name into png_ptr->chunk_name */
+   png_memcpy(png_ptr->chunk_name, buf + 4, 4);
+
+   png_debug2(0, "Reading %s chunk, length = %lu",
+      png_ptr->chunk_name, length);
+
+   /* reset the crc and run it over the chunk name */
+   png_reset_crc(png_ptr);
+   png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
+
+   /* check to see if chunk name is valid */
+   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
+   return length;
+}
+
 /* Read data, and (optionally) run it through the CRC. */
 void /* PRIVATE */
 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL) return;
    png_read_data(png_ptr, buf, length);
    png_calculate_crc(png_ptr, buf, length);
 }
@@ -180,9 +216,9 @@ png_crc_error(png_structp png_ptr)
  * holding the original prefix part and an uncompressed version of the
  * trailing part (the malloc area passed in is freed).
  */
-png_charp /* PRIVATE */
+void /* PRIVATE */
 png_decompress_chunk(png_structp png_ptr, int comp_type,
-                              png_charp chunkdata, png_size_t chunklength,
+                              png_size_t chunklength,
                               png_size_t prefix_size, png_size_t *newlength)
 {
    static PNG_CONST char msg[] = "Error decoding compressed text";
@@ -192,7 +228,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
    if (comp_type == PNG_COMPRESSION_TYPE_BASE)
    {
       int ret = Z_OK;
-      png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
+      png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
       png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
       png_ptr->zstream.next_out = png_ptr->zbuf;
       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
@@ -218,19 +254,21 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
                text = (png_charp)png_malloc_warn(png_ptr, text_size);
                if (text ==  NULL)
                  {
-                    png_free(png_ptr,chunkdata);
-                    png_error(png_ptr,"Not enough memory to decompress chunk");
+                    png_free(png_ptr, png_ptr->chunkdata);
+                    png_ptr->chunkdata = NULL;
+                    png_error(png_ptr, "Not enough memory to decompress chunk");
                  }
-               png_memcpy(text, chunkdata, prefix_size);
+               png_memcpy(text, png_ptr->chunkdata, prefix_size);
             }
 
             text[text_size - 1] = 0x00;
 
             /* Copy what we can of the error message into the text chunk */
-            text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
-            text_size = png_sizeof(msg) > text_size ? text_size :
-               png_sizeof(msg);
-            png_memcpy(text + prefix_size, msg, text_size + 1);
+            text_size = (png_size_t)(chunklength -
+              (text - png_ptr->chunkdata) - 1);
+            if (text_size > png_sizeof(msg))
+               text_size = png_sizeof(msg);
+            png_memcpy(text + prefix_size, msg, text_size);
             break;
          }
          if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
@@ -241,13 +279,15 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
                    png_ptr->zbuf_size - png_ptr->zstream.avail_out;
                text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
                if (text ==  NULL)
-                 {
-                    png_free(png_ptr,chunkdata);
-                    png_error(png_ptr,"Not enough memory to decompress chunk.");
-                 }
+               {
+                  png_free(png_ptr, png_ptr->chunkdata);
+                  png_ptr->chunkdata = NULL;
+                  png_error(png_ptr,
+                    "Not enough memory to decompress chunk.");
+               }
                png_memcpy(text + prefix_size, png_ptr->zbuf,
                     text_size - prefix_size);
-               png_memcpy(text, chunkdata, prefix_size);
+               png_memcpy(text, png_ptr->chunkdata, prefix_size);
                *(text + text_size) = 0x00;
             }
             else
@@ -261,8 +301,10 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
                if (text == NULL)
                {
                   png_free(png_ptr, tmp);
-                  png_free(png_ptr, chunkdata);
-                  png_error(png_ptr,"Not enough memory to decompress chunk..");
+                  png_free(png_ptr, png_ptr->chunkdata);
+                  png_ptr->chunkdata = NULL;
+                  png_error(png_ptr,
+                    "Not enough memory to decompress chunk..");
                }
                png_memcpy(text, tmp, text_size);
                png_free(png_ptr, tmp);
@@ -302,16 +344,17 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
          png_warning(png_ptr,
             "Incomplete compressed datastream in chunk other than IDAT");
 #endif
-         text_size=prefix_size;
+         text_size = prefix_size;
          if (text ==  NULL)
          {
             text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
             if (text == NULL)
               {
-                png_free(png_ptr, chunkdata);
-                png_error(png_ptr,"Not enough memory for text.");
+                png_free(png_ptr, png_ptr->chunkdata);
+                png_ptr->chunkdata = NULL;
+                png_error(png_ptr, "Not enough memory for text.");
               }
-            png_memcpy(text, chunkdata, prefix_size);
+            png_memcpy(text, png_ptr->chunkdata, prefix_size);
          }
          *(text + text_size) = 0x00;
       }
@@ -319,8 +362,8 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
       inflateReset(&png_ptr->zstream);
       png_ptr->zstream.avail_in = 0;
 
-      png_free(png_ptr, chunkdata);
-      chunkdata = text;
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = text;
       *newlength=text_size;
    }
    else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
@@ -328,18 +371,15 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
       char umsg[50];
 
-      png_snprintf(umsg, 50,
-         "Unknown zTXt compression type %d", comp_type);
+      png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
       png_warning(png_ptr, umsg);
 #else
       png_warning(png_ptr, "Unknown zTXt compression type");
 #endif
 
-      *(chunkdata + prefix_size) = 0x00;
-      *newlength=prefix_size;
+      *(png_ptr->chunkdata + prefix_size) = 0x00;
+      *newlength = prefix_size;
    }
-
-   return chunkdata;
 }
 #endif
 
@@ -352,7 +392,7 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    int bit_depth, color_type, compression_type, filter_type;
    int interlace_type;
 
-   png_debug(1, "in png_handle_IHDR\n");
+   png_debug(1, "in png_handle_IHDR");
 
    if (png_ptr->mode & PNG_HAVE_IHDR)
       png_error(png_ptr, "Out of place IHDR");
@@ -406,10 +446,10 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    /* set up other useful info */
    png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
    png_ptr->channels);
-   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
-   png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
-   png_debug1(3,"channels = %d\n", png_ptr->channels);
-   png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
+   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
+   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
+   png_debug1(3, "channels = %d", png_ptr->channels);
+   png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
       color_type, interlace_type, compression_type, filter_type);
 }
@@ -424,7 +464,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_colorp pal_ptr;
 #endif
 
-   png_debug(1, "in png_handle_PLTE\n");
+   png_debug(1, "in png_handle_PLTE");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before PLTE");
@@ -556,7 +596,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_debug(1, "in png_handle_IEND\n");
+   png_debug(1, "in png_handle_IEND");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
    {
@@ -571,7 +611,7 @@ png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
    png_crc_finish(png_ptr, length);
 
-   info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
+   info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
 }
 
 #if defined(PNG_READ_gAMA_SUPPORTED)
@@ -584,7 +624,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
    png_byte buf[4];
 
-   png_debug(1, "in png_handle_gAMA\n");
+   png_debug(1, "in png_handle_gAMA");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before gAMA");
@@ -636,7 +676,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
 #ifndef PNG_NO_CONSOLE_IO
-         fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
+         fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
 #endif
          return;
       }
@@ -662,7 +702,7 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_size_t truelen;
    png_byte buf[4];
 
-   png_debug(1, "in png_handle_sBIT\n");
+   png_debug(1, "in png_handle_sBIT");
 
    buf[0] = buf[1] = buf[2] = buf[3] = 0;
 
@@ -725,7 +765,7 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_byte buf[4];
+   png_byte buf[32];
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 #endif
@@ -734,7 +774,7 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    png_uint_32 uint_x, uint_y;
 
-   png_debug(1, "in png_handle_cHRM\n");
+   png_debug(1, "in png_handle_cHRM");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before cHRM");
@@ -766,64 +806,27 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_x = png_get_uint_32(buf);
-
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x > 80000L || uint_y > 80000L ||
-      uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM white point");
-      png_crc_finish(png_ptr, 24);
+   png_crc_read(png_ptr, buf, 32);
+   if (png_crc_finish(png_ptr, 0))
       return;
-   }
-   int_x_white = (png_fixed_point)uint_x;
-   int_y_white = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
    uint_x = png_get_uint_32(buf);
+   uint_y = png_get_uint_32(buf + 4);
+   int_x_white = (png_fixed_point)uint_x;
+   int_y_white = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM red point");
-      png_crc_finish(png_ptr, 16);
-      return;
-   }
+   uint_x = png_get_uint_32(buf + 8);
+   uint_y = png_get_uint_32(buf + 12);
    int_x_red = (png_fixed_point)uint_x;
    int_y_red = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_x = png_get_uint_32(buf);
-
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM green point");
-      png_crc_finish(png_ptr, 8);
-      return;
-   }
+   uint_x = png_get_uint_32(buf + 16);
+   uint_y = png_get_uint_32(buf + 20);
    int_x_green = (png_fixed_point)uint_x;
    int_y_green = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_x = png_get_uint_32(buf);
-
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM blue point");
-      png_crc_finish(png_ptr, 0);
-      return;
-   }
+   uint_x = png_get_uint_32(buf + 24);
+   uint_y = png_get_uint_32(buf + 28);
    int_x_blue = (png_fixed_point)uint_x;
    int_y_blue = (png_fixed_point)uint_y;
 
@@ -854,19 +857,18 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
               "Ignoring incorrect cHRM value when sRGB is also present");
 #ifndef PNG_NO_CONSOLE_IO
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-            fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
+            fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
                white_x, white_y, red_x, red_y);
-            fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
+            fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
                green_x, green_y, blue_x, blue_y);
 #else
-            fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
+            fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
                int_x_white, int_y_white, int_x_red, int_y_red);
-            fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
+            fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
                int_x_green, int_y_green, int_x_blue, int_y_blue);
 #endif
 #endif /* PNG_NO_CONSOLE_IO */
          }
-         png_crc_finish(png_ptr, 0);
          return;
       }
 #endif /* PNG_READ_sRGB_SUPPORTED */
@@ -880,8 +882,6 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
       int_y_green, int_x_blue, int_y_blue);
 #endif
-   if (png_crc_finish(png_ptr, 0))
-      return;
 }
 #endif
 
@@ -892,7 +892,7 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    int intent;
    png_byte buf[1];
 
-   png_debug(1, "in png_handle_sRGB\n");
+   png_debug(1, "in png_handle_sRGB");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before sRGB");
@@ -949,10 +949,11 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
            "Ignoring incorrect gAMA value when sRGB is also present");
 #ifndef PNG_NO_CONSOLE_IO
 #  ifdef PNG_FIXED_POINT_SUPPORTED
-         fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
+         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
+            (int)png_ptr->int_gamma);
 #  else
 #    ifdef PNG_FLOATING_POINT_SUPPORTED
-         fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
+         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
 #    endif
 #  endif
 #endif
@@ -987,7 +988,6 @@ void /* PRIVATE */
 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 {
-   png_charp chunkdata;
    png_byte compression_type;
    png_bytep pC;
    png_charp profile;
@@ -995,7 +995,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_uint_32 profile_size, profile_length;
    png_size_t slength, prefix_length, data_length;
 
-   png_debug(1, "in png_handle_iCCP\n");
+   png_debug(1, "in png_handle_iCCP");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before iCCP");
@@ -1025,28 +1025,31 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, skip))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (profile = chunkdata; *profile; profile++)
+   for (profile = png_ptr->chunkdata; *profile; profile++)
       /* empty loop to find end of name */ ;
 
    ++profile;
 
    /* there should be at least one zero (the compression type byte)
       following the separator, and we should be on it  */
-   if ( profile >= chunkdata + slength - 1)
+   if ( profile >= png_ptr->chunkdata + slength - 1)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "Malformed iCCP chunk");
       return;
    }
@@ -1056,43 +1059,46 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    if (compression_type)
    {
       png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
-      compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
+      compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
                                  wrote nonzero) */
    }
 
-   prefix_length = profile - chunkdata;
-   chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
-                                    slength, prefix_length, &data_length);
+   prefix_length = profile - png_ptr->chunkdata;
+   png_decompress_chunk(png_ptr, compression_type,
+     slength, prefix_length, &data_length);
 
    profile_length = data_length - prefix_length;
 
    if ( prefix_length > data_length || profile_length < 4)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "Profile size field missing from iCCP chunk");
       return;
    }
 
    /* Check the profile_size recorded in the first 32 bits of the ICC profile */
-   pC = (png_bytep)(chunkdata+prefix_length);
-   profile_size = ((*(pC  ))<<24) |
-                  ((*(pC+1))<<16) |
-                  ((*(pC+2))<< 8) |
-                  ((*(pC+3))    );
+   pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
+   profile_size = ((*(pC    ))<<24) |
+                  ((*(pC + 1))<<16) |
+                  ((*(pC + 2))<< 8) |
+                  ((*(pC + 3))    );
 
-   if(profile_size < profile_length)
+   if (profile_size < profile_length)
       profile_length = profile_size;
 
-   if(profile_size > profile_length)
+   if (profile_size > profile_length)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "Ignoring truncated iCCP profile.");
       return;
    }
 
-   png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
-                chunkdata + prefix_length, profile_length);
-   png_free(png_ptr, chunkdata);
+   png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
+     compression_type, png_ptr->chunkdata + prefix_length, profile_length);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
 }
 #endif /* PNG_READ_iCCP_SUPPORTED */
 
@@ -1101,7 +1107,6 @@ void /* PRIVATE */
 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 {
-   png_bytep chunkdata;
    png_bytep entry_start;
    png_sPLT_t new_palette;
 #ifdef PNG_NO_POINTER_INDEXING
@@ -1111,7 +1116,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_uint_32 skip = 0;
    png_size_t slength;
 
-   png_debug(1, "in png_handle_sPLT\n");
+   png_debug(1, "in png_handle_sPLT");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before sPLT");
@@ -1131,45 +1136,49 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, skip))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (entry_start = chunkdata; *entry_start; entry_start++)
+   for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++)
       /* empty loop to find end of name */ ;
    ++entry_start;
 
    /* a sample depth should follow the separator, and we should be on it  */
-   if (entry_start > chunkdata + slength - 2)
+   if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "malformed sPLT chunk");
       return;
    }
 
    new_palette.depth = *entry_start++;
    entry_size = (new_palette.depth == 8 ? 6 : 10);
-   data_length = (slength - (entry_start - chunkdata));
+   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
 
    /* integrity-check the data length */
    if (data_length % entry_size)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "sPLT chunk has bad length");
       return;
    }
 
    new_palette.nentries = (png_int_32) ( data_length / entry_size);
-   if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
-       png_sizeof(png_sPLT_entry)))
+   if ((png_uint_32) new_palette.nentries >
+       (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
    {
        png_warning(png_ptr, "sPLT chunk too long");
        return;
@@ -1227,11 +1236,12 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
 
    /* discard all chunk data except the name and stash that */
-   new_palette.name = (png_charp)chunkdata;
+   new_palette.name = png_ptr->chunkdata;
 
    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
 
-   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    png_free(png_ptr, new_palette.entries);
 }
 #endif /* PNG_READ_sPLT_SUPPORTED */
@@ -1241,14 +1251,8 @@ void /* PRIVATE */
 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
-   int bit_mask;
 
-   png_debug(1, "in png_handle_tRNS\n");
-
-   /* For non-indexed color, mask off any bits in the tRNS value that
-    * exceed the bit depth.  Some creators were writing extra bits there.
-    * This is not needed for indexed color. */
-   bit_mask = (1 << png_ptr->bit_depth) - 1;
+   png_debug(1, "in png_handle_tRNS");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before tRNS");
@@ -1278,7 +1282,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
       png_crc_read(png_ptr, buf, 2);
       png_ptr->num_trans = 1;
-      png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask;
+      png_ptr->trans_values.gray = png_get_uint_16(buf);
    }
    else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
    {
@@ -1292,9 +1296,9 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       }
       png_crc_read(png_ptr, buf, (png_size_t)length);
       png_ptr->num_trans = 1;
-      png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask;
-      png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask;
-      png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask;
+      png_ptr->trans_values.red = png_get_uint_16(buf);
+      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
+      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
    }
    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
@@ -1344,7 +1348,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_size_t truelen;
    png_byte buf[6];
 
-   png_debug(1, "in png_handle_bKGD\n");
+   png_debug(1, "in png_handle_bKGD");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before bKGD");
@@ -1393,9 +1397,9 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
       png_ptr->background.index = buf[0];
-      if(info_ptr->num_palette)
+      if (info_ptr && info_ptr->num_palette)
       {
-          if(buf[0] > info_ptr->num_palette)
+          if (buf[0] >= info_ptr->num_palette)
           {
              png_warning(png_ptr, "Incorrect bKGD chunk index value");
              return;
@@ -1433,7 +1437,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    unsigned int num, i;
    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
 
-   png_debug(1, "in png_handle_hIST\n");
+   png_debug(1, "in png_handle_hIST");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before hIST");
@@ -1488,7 +1492,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_uint_32 res_x, res_y;
    int unit_type;
 
-   png_debug(1, "in png_handle_pHYs\n");
+   png_debug(1, "in png_handle_pHYs");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before pHYs");
@@ -1531,7 +1535,7 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_int_32 offset_x, offset_y;
    int unit_type;
 
-   png_debug(1, "in png_handle_oFFs\n");
+   png_debug(1, "in png_handle_oFFs");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before oFFs");
@@ -1571,7 +1575,6 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_charp purpose;
    png_int_32 X0, X1;
    png_byte type, nparams;
    png_charp buf, units, endptr;
@@ -1579,7 +1582,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_size_t slength;
    int i;
 
-   png_debug(1, "in png_handle_pCAL\n");
+   png_debug(1, "in png_handle_pCAL");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before pCAL");
@@ -1596,48 +1599,51 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
+   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
       length + 1);
-   purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (purpose == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
      {
        png_warning(png_ptr, "No memory for pCAL purpose.");
        return;
      }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)purpose, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, purpose);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   purpose[slength] = 0x00; /* null terminate the last string */
+   png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
 
-   png_debug(3, "Finding end of pCAL purpose string\n");
-   for (buf = purpose; *buf; buf++)
+   png_debug(3, "Finding end of pCAL purpose string");
+   for (buf = png_ptr->chunkdata; *buf; buf++)
       /* empty loop */ ;
 
-   endptr = purpose + slength;
+   endptr = png_ptr->chunkdata + slength;
 
    /* We need to have at least 12 bytes after the purpose string
       in order to get the parameter information. */
    if (endptr <= buf + 12)
    {
       png_warning(png_ptr, "Invalid pCAL data");
-      png_free(png_ptr, purpose);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
+   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
    X0 = png_get_int_32((png_bytep)buf+1);
    X1 = png_get_int_32((png_bytep)buf+5);
    type = buf[9];
    nparams = buf[10];
    units = buf + 11;
 
-   png_debug(3, "Checking pCAL equation type and number of parameters\n");
+   png_debug(3, "Checking pCAL equation type and number of parameters");
    /* Check that we have the right number of parameters for known
       equation types. */
    if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
@@ -1646,7 +1652,8 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
    {
       png_warning(png_ptr, "Invalid pCAL parameters for equation type");
-      png_free(png_ptr, purpose);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
    else if (type >= PNG_EQUATION_LAST)
@@ -1657,12 +1664,13 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    for (buf = units; *buf; buf++)
       /* Empty loop to move past the units string. */ ;
 
-   png_debug(3, "Allocating pCAL parameters array\n");
-   params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
-      *png_sizeof(png_charp))) ;
+   png_debug(3, "Allocating pCAL parameters array");
+   params = (png_charpp)png_malloc_warn(png_ptr,
+      (png_uint_32)(nparams * png_sizeof(png_charp))) ;
    if (params == NULL)
      {
-       png_free(png_ptr, purpose);
+       png_free(png_ptr, png_ptr->chunkdata);
+       png_ptr->chunkdata = NULL;
        png_warning(png_ptr, "No memory for pCAL params.");
        return;
      }
@@ -1672,24 +1680,26 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    {
       buf++; /* Skip the null string terminator from previous parameter. */
 
-      png_debug1(3, "Reading pCAL parameter %d\n", i);
-      for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
+      png_debug1(3, "Reading pCAL parameter %d", i);
+      for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
          /* Empty loop to move past each parameter string */ ;
 
       /* Make sure we haven't run out of data yet */
       if (buf > endptr)
       {
          png_warning(png_ptr, "Invalid pCAL data");
-         png_free(png_ptr, purpose);
+         png_free(png_ptr, png_ptr->chunkdata);
+         png_ptr->chunkdata = NULL;
          png_free(png_ptr, params);
          return;
       }
    }
 
-   png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
+   png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
       units, params);
 
-   png_free(png_ptr, purpose);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    png_free(png_ptr, params);
 }
 #endif
@@ -1699,7 +1709,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_charp buffer, ep;
+   png_charp ep;
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    double width, height;
    png_charp vp;
@@ -1710,7 +1720,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
    png_size_t slength;
 
-   png_debug(1, "in png_handle_sCAL\n");
+   png_debug(1, "in png_handle_sCAL");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before sCAL");
@@ -1727,77 +1737,91 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
+   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
       length + 1);
-   buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (buffer == NULL)
-     {
-       png_warning(png_ptr, "Out of memory while processing sCAL chunk");
-       return;
-     }
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
+   {
+      png_warning(png_ptr, "Out of memory while processing sCAL chunk");
+      return;
+   }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)buffer, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, buffer);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   buffer[slength] = 0x00; /* null terminate the last string */
+   png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
 
-   ep = buffer + 1;        /* skip unit byte */
+   ep = png_ptr->chunkdata + 1;        /* skip unit byte */
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    width = png_strtod(png_ptr, ep, &vp);
    if (*vp)
    {
-       png_warning(png_ptr, "malformed width string in sCAL chunk");
-       return;
+      png_warning(png_ptr, "malformed width string in sCAL chunk");
+      return;
    }
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
    swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
    if (swidth == NULL)
-     {
-       png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
-       return;
-     }
+   {
+      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
+      return;
+   }
    png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
 #endif
 #endif
 
-   for (ep = buffer; *ep; ep++)
+   for (ep = png_ptr->chunkdata; *ep; ep++)
       /* empty loop */ ;
    ep++;
 
+   if (png_ptr->chunkdata + slength < ep)
+   {
+      png_warning(png_ptr, "Truncated sCAL chunk");
+#if defined(PNG_FIXED_POINT_SUPPORTED) && \
+    !defined(PNG_FLOATING_POINT_SUPPORTED)
+      png_free(png_ptr, swidth);
+#endif
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+      return;
+   }
+
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    height = png_strtod(png_ptr, ep, &vp);
    if (*vp)
    {
-       png_warning(png_ptr, "malformed height string in sCAL chunk");
-       return;
+      png_warning(png_ptr, "malformed height string in sCAL chunk");
+      return;
    }
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
    sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
-   if (swidth == NULL)
-     {
-       png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
-       return;
-     }
+   if (sheight == NULL)
+   {
+      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
+      return;
+   }
    png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
 #endif
 #endif
 
-   if (buffer + slength < ep
+   if (png_ptr->chunkdata + slength < ep
 #ifdef PNG_FLOATING_POINT_SUPPORTED
       || width <= 0. || height <= 0.
 #endif
       )
    {
       png_warning(png_ptr, "Invalid sCAL data");
-      png_free(png_ptr, buffer);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
       png_free(png_ptr, swidth);
       png_free(png_ptr, sheight);
@@ -1807,14 +1831,15 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
+   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
+   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
 #endif
 #endif
 
-   png_free(png_ptr, buffer);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
    png_free(png_ptr, swidth);
    png_free(png_ptr, sheight);
@@ -1829,7 +1854,7 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_byte buf[7];
    png_time mod_time;
 
-   png_debug(1, "in png_handle_tIME\n");
+   png_debug(1, "in png_handle_tIME");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Out of place tIME chunk");
@@ -1877,7 +1902,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_size_t slength;
    int ret;
 
-   png_debug(1, "in png_handle_tEXt\n");
+   png_debug(1, "in png_handle_tEXt");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before tEXt");
@@ -1894,21 +1919,24 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   key = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (key == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
    {
      png_warning(png_ptr, "No memory to process text chunk.");
      return;
    }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)key, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, skip))
    {
-      png_free(png_ptr, key);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
+   key = png_ptr->chunkdata;
    key[slength] = 0x00;
 
    for (text = key; *text; text++)
@@ -1922,7 +1950,8 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    if (text_ptr == NULL)
    {
      png_warning(png_ptr, "Not enough memory to process text chunk.");
-     png_free(png_ptr, key);
+     png_free(png_ptr, png_ptr->chunkdata);
+     png_ptr->chunkdata = NULL;
      return;
    }
    text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
@@ -1935,9 +1964,10 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    text_ptr->text = text;
    text_ptr->text_length = png_strlen(text);
 
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
 
-   png_free(png_ptr, key);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    png_free(png_ptr, text_ptr);
    if (ret)
      png_warning(png_ptr, "Insufficient memory to process text chunk.");
@@ -1950,13 +1980,12 @@ void /* PRIVATE */
 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_textp text_ptr;
-   png_charp chunkdata;
    png_charp text;
    int comp_type;
    int ret;
    png_size_t slength, prefix_len, data_len;
 
-   png_debug(1, "in png_handle_zTXt\n");
+   png_debug(1, "in png_handle_zTXt");
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before zTXt");
 
@@ -1968,36 +1997,39 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       there is no hard and fast rule to tell us where to stop. */
    if (length > (png_uint_32)65535L)
    {
-     png_warning(png_ptr,"zTXt chunk too large to fit in memory");
+     png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_crc_finish(png_ptr, length);
      return;
    }
 #endif
 
-   chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (chunkdata == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
    {
-     png_warning(png_ptr,"Out of memory processing zTXt chunk.");
+     png_warning(png_ptr, "Out of memory processing zTXt chunk.");
      return;
    }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (text = chunkdata; *text; text++)
+   for (text = png_ptr->chunkdata; *text; text++)
       /* empty loop */ ;
 
    /* zTXt must have some text after the chunkdataword */
-   if (text == chunkdata + slength - 1)
+   if (text >= png_ptr->chunkdata + slength - 2)
    {
       png_warning(png_ptr, "Truncated zTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
    else
@@ -2010,33 +2042,35 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
        }
        text++;        /* skip the compression_method byte */
    }
-   prefix_len = text - chunkdata;
+   prefix_len = text - png_ptr->chunkdata;
 
-   chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
-                                    (png_size_t)length, prefix_len, &data_len);
+   png_decompress_chunk(png_ptr, comp_type,
+     (png_size_t)length, prefix_len, &data_len);
 
    text_ptr = (png_textp)png_malloc_warn(png_ptr,
-     (png_uint_32)png_sizeof(png_text));
+      (png_uint_32)png_sizeof(png_text));
    if (text_ptr == NULL)
    {
-     png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
-     png_free(png_ptr, chunkdata);
+     png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
+     png_free(png_ptr, png_ptr->chunkdata);
+     png_ptr->chunkdata = NULL;
      return;
    }
    text_ptr->compression = comp_type;
-   text_ptr->key = chunkdata;
+   text_ptr->key = png_ptr->chunkdata;
 #ifdef PNG_iTXt_SUPPORTED
    text_ptr->lang = NULL;
    text_ptr->lang_key = NULL;
    text_ptr->itxt_length = 0;
 #endif
-   text_ptr->text = chunkdata + prefix_len;
+   text_ptr->text = png_ptr->chunkdata + prefix_len;
    text_ptr->text_length = data_len;
 
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
 
    png_free(png_ptr, text_ptr);
-   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    if (ret)
      png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
 }
@@ -2048,14 +2082,13 @@ void /* PRIVATE */
 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_textp text_ptr;
-   png_charp chunkdata;
    png_charp key, lang, text, lang_key;
    int comp_flag;
    int comp_type = 0;
    int ret;
    png_size_t slength, prefix_len, data_len;
 
-   png_debug(1, "in png_handle_iTXt\n");
+   png_debug(1, "in png_handle_iTXt");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before iTXt");
@@ -2068,29 +2101,31 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       there is no hard and fast rule to tell us where to stop. */
    if (length > (png_uint_32)65535L)
    {
-     png_warning(png_ptr,"iTXt chunk too large to fit in memory");
+     png_warning(png_ptr, "iTXt chunk too large to fit in memory");
      png_crc_finish(png_ptr, length);
      return;
    }
 #endif
 
-   chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (chunkdata == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
    {
      png_warning(png_ptr, "No memory to process iTXt chunk.");
      return;
    }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (lang = chunkdata; *lang; lang++)
+   for (lang = png_ptr->chunkdata; *lang; lang++)
       /* empty loop */ ;
    lang++;        /* skip NUL separator */
 
@@ -2098,10 +2133,11 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       translated keyword (possibly empty), and possibly some text after the
       keyword */
 
-   if (lang >= chunkdata + slength - 3)
+   if (lang >= png_ptr->chunkdata + slength - 3)
    {
       png_warning(png_ptr, "Truncated iTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
    else
@@ -2114,44 +2150,55 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       /* empty loop */ ;
    lang_key++;        /* skip NUL separator */
 
+   if (lang_key >= png_ptr->chunkdata + slength)
+   {
+      png_warning(png_ptr, "Truncated iTXt chunk");
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+      return;
+   }
+
    for (text = lang_key; *text; text++)
       /* empty loop */ ;
    text++;        /* skip NUL separator */
-   if (text >= chunkdata + slength)
+   if (text >= png_ptr->chunkdata + slength)
    {
       png_warning(png_ptr, "Malformed iTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   prefix_len = text - chunkdata;
+   prefix_len = text - png_ptr->chunkdata;
 
-   key=chunkdata;
+   key=png_ptr->chunkdata;
    if (comp_flag)
-       chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
-          (size_t)length, prefix_len, &data_len);
+       png_decompress_chunk(png_ptr, comp_type,
+         (size_t)length, prefix_len, &data_len);
    else
-       data_len=png_strlen(chunkdata + prefix_len);
+       data_len = png_strlen(png_ptr->chunkdata + prefix_len);
    text_ptr = (png_textp)png_malloc_warn(png_ptr,
       (png_uint_32)png_sizeof(png_text));
    if (text_ptr == NULL)
    {
-     png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
-     png_free(png_ptr, chunkdata);
+     png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
+     png_free(png_ptr, png_ptr->chunkdata);
+     png_ptr->chunkdata = NULL;
      return;
    }
    text_ptr->compression = (int)comp_flag + 1;
-   text_ptr->lang_key = chunkdata+(lang_key-key);
-   text_ptr->lang = chunkdata+(lang-key);
+   text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
+   text_ptr->lang = png_ptr->chunkdata + (lang - key);
    text_ptr->itxt_length = data_len;
    text_ptr->text_length = 0;
-   text_ptr->key = chunkdata;
-   text_ptr->text = chunkdata + prefix_len;
+   text_ptr->key = png_ptr->chunkdata;
+   text_ptr->text = png_ptr->chunkdata + prefix_len;
 
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
 
    png_free(png_ptr, text_ptr);
-   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    if (ret)
      png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
 }
@@ -2167,7 +2214,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_uint_32 skip = 0;
 
-   png_debug(1, "in png_handle_unknown\n");
+   png_debug(1, "in png_handle_unknown");
 
    if (png_ptr->mode & PNG_HAVE_IDAT)
    {
@@ -2178,12 +2225,10 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
          png_ptr->mode |= PNG_AFTER_IDAT;
    }
 
-   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-
    if (!(png_ptr->chunk_name[0] & 0x20))
    {
 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
            PNG_HANDLE_CHUNK_ALWAYS
 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
            && png_ptr->read_user_chunk_fn == NULL
@@ -2205,14 +2250,20 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
            length = (png_uint_32)65535L;
        }
 #endif
-       png_strncpy((png_charp)png_ptr->unknown_chunk.name,
-        (png_charp)png_ptr->chunk_name,
-         png_sizeof((png_charp)png_ptr->chunk_name));
-       png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
+       png_memcpy((png_charp)png_ptr->unknown_chunk.name,
+                  (png_charp)png_ptr->chunk_name, 
+                  png_sizeof(png_ptr->unknown_chunk.name));
+       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
        png_ptr->unknown_chunk.size = (png_size_t)length;
-       png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
+       if (length == 0)
+         png_ptr->unknown_chunk.data = NULL;
+       else
+       {
+         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
+         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
+       }
 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
-       if(png_ptr->read_user_chunk_fn != NULL)
+       if (png_ptr->read_user_chunk_fn != NULL)
        {
           /* callback to user unknown chunk handler */
           int ret;
@@ -2223,16 +2274,16 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
           if (ret == 0)
           {
              if (!(png_ptr->chunk_name[0] & 0x20))
-                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+                if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
                      PNG_HANDLE_CHUNK_ALWAYS)
                    png_chunk_error(png_ptr, "unknown critical chunk");
              png_set_unknown_chunks(png_ptr, info_ptr,
                &png_ptr->unknown_chunk, 1);
           }
        }
-#else
-       png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
+       else
 #endif
+       png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
        png_free(png_ptr, png_ptr->unknown_chunk.data);
        png_ptr->unknown_chunk.data = NULL;
    }
@@ -2258,7 +2309,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
 {
-   png_debug(1, "in png_check_chunk_name\n");
+   png_debug(1, "in png_check_chunk_name");
    if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
        isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
    {
@@ -2280,7 +2331,7 @@ png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
 void /* PRIVATE */
 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
 {
-   png_debug(1,"in png_combine_row\n");
+   png_debug(1, "in png_combine_row");
    if (mask == 0xff)
    {
       png_memcpy(row, png_ptr->row_buf + 1,
@@ -2496,7 +2547,7 @@ png_do_read_interlace(png_structp png_ptr)
    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
 #endif
 
-   png_debug(1,"in png_do_read_interlace\n");
+   png_debug(1, "in png_do_read_interlace");
    if (row != NULL && row_info != NULL)
    {
       png_uint_32 final_width;
@@ -2697,7 +2748,7 @@ png_do_read_interlace(png_structp png_ptr)
          }
       }
       row_info->width = final_width;
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
+      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
    }
 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
    transformations = transformations; /* silence compiler warning */
@@ -2709,8 +2760,8 @@ void /* PRIVATE */
 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
    png_bytep prev_row, int filter)
 {
-   png_debug(1, "in png_read_filter_row\n");
-   png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
+   png_debug(1, "in png_read_filter_row");
+   png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
    switch (filter)
    {
       case PNG_FILTER_VALUE_NONE:
@@ -2814,7 +2865,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
                   p = c;
              */
 
-            p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+            p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
 
             *rp = (png_byte)(((int)(*rp) + p) & 0xff);
             rp++;
@@ -2823,7 +2874,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
       }
       default:
          png_warning(png_ptr, "Ignoring bad adaptive filter type");
-         *row=0;
+         *row = 0;
          break;
    }
 }
@@ -2832,6 +2883,7 @@ void /* PRIVATE */
 png_read_finish_row(png_structp png_ptr)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
    /* start of interlace block */
@@ -2845,13 +2897,15 @@ png_read_finish_row(png_structp png_ptr)
 
    /* offset to next interlace block in the y direction */
    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
 #endif
 
-   png_debug(1, "in png_read_finish_row\n");
+   png_debug(1, "in png_read_finish_row");
    png_ptr->row_number++;
    if (png_ptr->row_number < png_ptr->num_rows)
       return;
 
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    if (png_ptr->interlaced)
    {
       png_ptr->row_number = 0;
@@ -2886,6 +2940,7 @@ png_read_finish_row(png_structp png_ptr)
       if (png_ptr->pass < 7)
          return;
    }
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
 
    if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
    {
@@ -2897,7 +2952,7 @@ png_read_finish_row(png_structp png_ptr)
 
       png_ptr->zstream.next_out = (Byte *)&extra;
       png_ptr->zstream.avail_out = (uInt)1;
-      for(;;)
+      for (;;)
       {
          if (!(png_ptr->zstream.avail_in))
          {
@@ -2911,7 +2966,7 @@ png_read_finish_row(png_structp png_ptr)
                png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
                png_reset_crc(png_ptr);
                png_crc_read(png_ptr, png_ptr->chunk_name, 4);
-               if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+               if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
                   png_error(png_ptr, "Not enough image data");
 
             }
@@ -2960,6 +3015,7 @@ void /* PRIVATE */
 png_read_start_row(png_structp png_ptr)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
    /* start of interlace block */
@@ -2973,14 +3029,16 @@ png_read_start_row(png_structp png_ptr)
 
    /* offset to next interlace block in the y direction */
    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
 #endif
 
    int max_pixel_depth;
-   png_uint_32 row_bytes;
+   png_size_t row_bytes;
 
-   png_debug(1, "in png_read_start_row\n");
+   png_debug(1, "in png_read_start_row");
    png_ptr->zstream.avail_in = 0;
    png_init_read_transformations(png_ptr);
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    if (png_ptr->interlaced)
    {
       if (!(png_ptr->transformations & PNG_INTERLACE))
@@ -2994,13 +3052,11 @@ png_read_start_row(png_structp png_ptr)
          png_pass_start[png_ptr->pass]) /
          png_pass_inc[png_ptr->pass];
 
-         row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
-
-         png_ptr->irowbytes = (png_size_t)row_bytes;
-         if((png_uint_32)png_ptr->irowbytes != row_bytes)
-            png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
+         png_ptr->irowbytes =
+            PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
    }
    else
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
    {
       png_ptr->num_rows = png_ptr->height;
       png_ptr->iwidth = png_ptr->width;
@@ -3099,11 +3155,11 @@ png_read_start_row(png_structp png_ptr)
 
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
-   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
      {
-       int user_pixel_depth=png_ptr->user_transform_depth*
+       int user_pixel_depth = png_ptr->user_transform_depth*
          png_ptr->user_transform_channels;
-       if(user_pixel_depth > max_pixel_depth)
+       if (user_pixel_depth > max_pixel_depth)
          max_pixel_depth=user_pixel_depth;
      }
 #endif
@@ -3113,14 +3169,20 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
    row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
    /* calculate the maximum bytes needed, adding a byte and a pixel
       for safety's sake */
-   row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
+   row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
       1 + ((max_pixel_depth + 7) >> 3);
 #ifdef PNG_MAX_MALLOC_64K
    if (row_bytes > (png_uint_32)65536L)
       png_error(png_ptr, "This image requires a row greater than 64KB");
 #endif
-   png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
-   png_ptr->row_buf = png_ptr->big_row_buf+32;
+
+   if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
+   {
+     png_free(png_ptr, png_ptr->big_row_buf);
+     png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
+     png_ptr->row_buf = png_ptr->big_row_buf+32;
+     png_ptr->old_big_row_buf_size = row_bytes+64;
+   }
 
 #ifdef PNG_MAX_MALLOC_64K
    if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
@@ -3128,17 +3190,23 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
 #endif
    if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
       png_error(png_ptr, "Row has too many bytes to allocate in memory.");
-   png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
-      png_ptr->rowbytes + 1));
+
+   if (png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
+   {
+     png_free(png_ptr, png_ptr->prev_row);
+     png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
+        png_ptr->rowbytes + 1));
+     png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
+   }
 
    png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
 
-   png_debug1(3, "width = %lu,\n", png_ptr->width);
-   png_debug1(3, "height = %lu,\n", png_ptr->height);
-   png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
-   png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
-   png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
-   png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
+   png_debug1(3, "width = %lu,", png_ptr->width);
+   png_debug1(3, "height = %lu,", png_ptr->height);
+   png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
+   png_debug1(3, "num_rows = %lu", png_ptr->num_rows);
+   png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
+   png_debug1(3, "irowbytes = %lu,", png_ptr->irowbytes);
 
    png_ptr->flags |= PNG_FLAG_ROW_INIT;
 }