[master] Imported from libpng-1.4.1beta04.tar
diff --git a/ANNOUNCE b/ANNOUNCE
index d713b35..cbb331d 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -44,7 +44,13 @@
 version 1.4.1beta03 [January 10, 2010]
   Removed png_set_premultiply_alpha() from scripts/*.def
 
+version 1.4.1rc01 [January 16, 2010]
+  No changes.
+
 version 1.4.1beta04 [January 23, 2010]
+  Revised png_decompress_chunk() to improve speed and memory usage when
+    decoding large chunks.
+  Added png_set|get_chunk_malloc_max() function and PNG_CHUNK_MALLOC_MAX macro.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index 40d1f2b..1e57726 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2476,7 +2476,13 @@
 version 1.4.1beta03 [January 10, 2010]
   Removed png_set_premultiply_alpha() from scripts/*.def
 
+version 1.4.1rc01 [January 16, 2010]
+  No changes.
+
 version 1.4.1beta04 [January 23, 2010]
+  Revised png_decompress_chunk() to improve speed and memory usage when
+    decoding large chunks.
+  Added png_set|get_chunk_malloc_max() function and PNG_CHUNK_MALLOC_MAX macro.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/libpng-1.4.1beta04.txt b/libpng-1.4.1beta04.txt
index c928df6..ad7cb74 100644
--- a/libpng-1.4.1beta04.txt
+++ b/libpng-1.4.1beta04.txt
@@ -432,6 +432,18 @@
 This limit also applies to the number of buffers that can be allocated
 by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks.
 
+You can also set a limit on the amount of memory that a compressed chunk
+other than IDAT can occupy, with
+
+   png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max);
+
+and you can retrieve the limit with
+
+   chunk_malloc_max = png_get_chunk_malloc_max(png_ptr);
+
+Any chunks that would cause either of these limits to be exceeded will
+be ignored.
+
 The high-level read interface
 
 At this point there are two ways to proceed; through the high-level
diff --git a/libpng.3 b/libpng.3
index 7b9cfca..2790363 100644
--- a/libpng.3
+++ b/libpng.3
@@ -192,6 +192,10 @@
 
 \fI\fB
 
+\fBpng_uint_32 png_get_chunk_malloc_max (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
 \fBpng_voidp png_get_mem_ptr(png_structp \fIpng_ptr\fP\fB);\fP
 
 \fI\fB
@@ -538,6 +542,10 @@
 
 \fI\fB
 
+\fBvoid png_set_chunk_malloc_max (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIuser_chunk_cache_max\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_set_mem_fn(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
 
 \fI\fB
@@ -1209,6 +1217,18 @@
 This limit also applies to the number of buffers that can be allocated
 by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks.
 
+You can also set a limit on the amount of memory that a compressed chunk
+other than IDAT can occupy, with
+
+   png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max);
+
+and you can retrieve the limit with
+
+   chunk_malloc_max = png_get_chunk_malloc_max(png_ptr);
+
+Any chunks that would cause either of these limits to be exceeded will
+be ignored.
+
 .SS The high-level read interface
 
 At this point there are two ways to proceed; through the high-level
diff --git a/png.h b/png.h
index c30fced..2da190d 100644
--- a/png.h
+++ b/png.h
@@ -1336,10 +1336,18 @@
 /* New member added in libpng-1.2.30 */
   png_charp chunkdata PNG_DEPSTRUCT;  /* buffer for reading chunk data */
 
-/* New member added in libpng-1.4.0 */
 #ifdef PNG_IO_STATE_SUPPORTED
+/* New member added in libpng-1.4.0 */
    png_uint_32 io_state PNG_DEPSTRUCT;
 #endif
+
+/* Added in libpng-1.4.1 */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+   /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk
+    * can occupy when decompressed.
+    */
+   png_uint_32 user_chunk_malloc_max PNG_DEPSTRUCT;
+#endif
 };
 
 
@@ -2396,6 +2404,11 @@
    png_ptr, png_uint_32 user_chunk_cache_max));
 extern PNG_EXPORT(png_uint_32,png_get_chunk_cache_max)
    PNGARG((png_structp png_ptr));
+/* Added in libpng-1.4.1 */
+extern PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp
+   png_ptr, png_uint_32 user_chunk_cache_max));
+extern PNG_EXPORT(png_uint_32,png_get_chunk_malloc_max)
+   PNGARG((png_structp png_ptr));
 #endif
 
 #if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
diff --git a/pngconf.h b/pngconf.h
index 2a7ba16..a295037 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -675,6 +675,10 @@
 #ifndef PNG_SET_USER_LIMITS_SUPPORTED
 #  ifndef PNG_NO_SET_USER_LIMITS
 #    define PNG_SET_USER_LIMITS_SUPPORTED
+     /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */
+#    define PNG_CHUNK_CACHE_LIMIT_SUPPORTED
+     /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */
+#    define PNG_CHUNK_MALLOC_LIMIT_SUPPORTED
 #  endif
 #endif
 
diff --git a/pngget.c b/pngget.c
index 0674bf5..9fa2ac0 100644
--- a/pngget.c
+++ b/pngget.c
@@ -895,8 +895,14 @@
 png_uint_32 PNGAPI
 png_get_chunk_cache_max (png_structp png_ptr)
 {
-    return (png_ptr? png_ptr->user_chunk_cache_max? 0x7fffffffL :
-       png_ptr->user_chunk_cache_max - 1 : 0);
+    return (png_ptr? (png_ptr->user_chunk_cache_max? 0x7fffffffL :
+       png_ptr->user_chunk_cache_max - 1) : 0);
+}
+/* This function was added to libpng 1.4.1 */
+png_uint_32 PNGAPI
+png_get_chunk_malloc_max (png_structp png_ptr)
+{
+    return (png_ptr? png_ptr->user_chunk_cache_max : 0);
 }
 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
 
diff --git a/pngrutil.c b/pngrutil.c
index 0bee16e..e0222d6 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -278,63 +278,90 @@
                text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
                if (text ==  NULL)
                {
-                  png_free(png_ptr, png_ptr->chunkdata);
-                  png_ptr->chunkdata = NULL;
                   png_error(png_ptr,
                     "Not enough memory to decompress chunk");
+                  text_size = 0;
+                  break;
                }
+               png_memcpy(text, png_ptr->chunkdata, prefix_size);
                png_memcpy(text + prefix_size, png_ptr->zbuf,
                     text_size - prefix_size);
-               png_memcpy(text, png_ptr->chunkdata, prefix_size);
                *(text + text_size) = 0x00;
                buffer_size = text_size;
             }
             else               /* Enlarge the decompression buffer */
             {
-               png_charp tmp;
+               png_charp tmp = text;
+               png_size_t new_text_size;
 
-               tmp = text;
-#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED
-               if ((png_ptr->user_chunk_cache_max != 0) &&
-                  (--png_ptr->user_chunk_cache_max == 0))
+               new_text_size = text_size + png_ptr->zbuf_size -
+                   png_ptr->zstream.avail_out;
+
+               if (new_text_size > buffer_size)
                {
-                  png_warning(png_ptr, "No space in chunk cache");
+                  if (png_ptr->zstream.avail_out)
+                     buffer_size = new_text_size;
+                  else
+                     buffer_size += buffer_size;
+               }
+
+#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED
+               if (png_ptr->user_chunk_malloc_max <= buffer_size)
+               {
+                  png_free(png_ptr, tmp);
+                  png_warning(png_ptr, "No space for decompressed chunk");
                   text = NULL;
                }
 
                else
-               {
-#endif
                   text = (png_charp)png_malloc_warn(png_ptr,
-                     (png_size_t)(text_size +
-                      png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
-#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED
-               }
+                     buffer_size + 1);
+#else
+               text = (png_charp)png_malloc_warn(png_ptr,
+                  buffer_size + 1);
 #endif
+
                if (text == NULL)
                {
-                  png_free(png_ptr, tmp);
-                  png_free(png_ptr, png_ptr->chunkdata);
-                  png_ptr->chunkdata = NULL;
-                  png_error(png_ptr,
+                  png_warning(png_ptr,
                     "Not enough memory to decompress chunk");
+                  break;
                }
+
                png_memcpy(text, tmp, text_size);
                png_free(png_ptr, tmp);
-               png_memcpy(text + text_size, png_ptr->zbuf,
-                  (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
-               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
-               *(text + text_size) = 0x00;
-            }
-            if (ret == Z_STREAM_END)
-               break;
-            else
-            {
-               png_ptr->zstream.next_out = png_ptr->zbuf;
-               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
             }
          }
+         if (ret == Z_STREAM_END)
+            break;
+
+         else
+         {
+            png_ptr->zstream.next_out = png_ptr->zbuf;
+            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         }
       }
+
+      if (text != NULL && buffer_size > text_size)
+      {
+         /* Reduce text allocation to actual size */
+         png_charp tmp;
+
+         tmp = text;
+         text = (png_charp)png_malloc_warn(png_ptr,
+             text_size);
+
+         if (text == NULL)
+            text = tmp;
+
+         else
+         {
+            png_memcpy(text, tmp, text_size + 1);
+            png_free(png_ptr, tmp);
+         }
+
+      }
+
       if (ret != Z_STREAM_END)
       {
 #ifdef PNG_STDIO_SUPPORTED
@@ -365,11 +392,11 @@
          {
             text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
             if (text == NULL)
-              {
-                png_free(png_ptr, png_ptr->chunkdata);
-                png_ptr->chunkdata = NULL;
-                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, png_ptr->chunkdata, prefix_size);
          }
          *(text + text_size) = 0x00;
diff --git a/pngset.c b/pngset.c
index cb3953e..1afae23 100644
--- a/pngset.c
+++ b/pngset.c
@@ -1130,6 +1130,7 @@
    png_ptr->user_width_max = user_width_max;
    png_ptr->user_height_max = user_height_max;
 }
+
 /* This function was added to libpng 1.4.0 */
 void PNGAPI
 png_set_chunk_cache_max (png_structp png_ptr,
@@ -1143,6 +1144,16 @@
     else
        png_ptr->user_chunk_cache_max = user_chunk_cache_max + 1;
 }
+
+/* This function was added to libpng 1.4.1 */
+void PNGAPI
+png_set_chunk_malloc_max (png_structp png_ptr,
+   png_uint_32 user_chunk_malloc_max)
+{
+    if (png_ptr == NULL)
+      return;
+    png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
+}
 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
 
 
diff --git a/scripts/png32ce.def b/scripts/png32ce.def
index 97ff838..b270cda 100644
--- a/scripts/png32ce.def
+++ b/scripts/png32ce.def
@@ -254,3 +254,6 @@
   png_check_cHRM_fixed @217
   png_calloc @218
   png_set_longjmp_fn @219
+; Added at version 1.4.1
+  png_get_chunk_malloc_max @220
+  png_set_chunk_malloc_max @221
diff --git a/scripts/pngos2.def b/scripts/pngos2.def
index 11d4c9b..ffe9572 100644
--- a/scripts/pngos2.def
+++ b/scripts/pngos2.def
@@ -214,6 +214,9 @@
   png_check_cHRM_fixed
   png_calloc
   png_set_longjmp_fn
+; Added at version 1.4.1
+  png_get_chunk_malloc_max
+  png_set_chunk_malloc_max
 
 ; These are not present when libpng is compiled with PNG_NO_GLOBAL_ARRAYS
   png_libpng_ver
diff --git a/scripts/pngwin.def b/scripts/pngwin.def
index f10bd85..bf1d2b0 100644
--- a/scripts/pngwin.def
+++ b/scripts/pngwin.def
@@ -209,3 +209,6 @@
   png_check_cHRM_fixed
   png_calloc
   png_set_longjmp_fn
+; Added at version 1.4.1
+  png_get_chunk_malloc_max
+  png_set_chunk_malloc_max