[libpng16] Start-up code size improvements, error handler flexibility.

These changes alter how the tricky allocation of the initial png_struct and
png_info structures are handled. png_info is now handled in pretty much the
same way as everything else, except that the allocations handle NULL return
silently.  png_struct is changed in a similar way on allocation and on
deallocation a 'safety' error handler is put in place (which should never
be required).  The error handler itself is changed to permit mismatches
in the application and libpng error buffer size; however, this means a
silent change to the API to return the jmp_buf if the size doesn't match
the size from the libpng compilation; libpng now allocates the memory and
this may fail.  Overall these changes result in slight code size
reductions; however, this is a reduction in code that is always executed
so is particularly valuable.  Overall on a 64-bit system the libpng DLL
decreases in code size by 1733 bytes.  pngerror.o increases in size by
about 465 bytes because of the new functionality.
diff --git a/ANNOUNCE b/ANNOUNCE
index eb7867d..9041246 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -60,6 +60,21 @@
     in libpng 1.5.7.
 
 Version 1.6.0beta03 [December 21, 2011]
+  Start-up code size improvements, error handler flexibility. These changes
+    alter how the tricky allocation of the initial png_struct and png_info
+    structures are handled. png_info is now handled in pretty much the same
+    way as everything else, except that the allocations handle NULL return
+    silently.  png_struct is changed in a similar way on allocation and on
+    deallocation a 'safety' error handler is put in place (which should never
+    be required).  The error handler itself is changed to permit mismatches
+    in the application and libpng error buffer size; however, this means a
+    silent change to the API to return the jmp_buf if the size doesn't match
+    the size from the libpng compilation; libpng now allocates the memory and
+    this may fail.  Overall these changes result in slight code size
+    reductions; however, this is a reduction in code that is always executed
+    so is particularly valuable.  Overall on a 64-bit system the libpng DLL
+    decreases in code size by 1733 bytes.  pngerror.o increases in size by
+    about 465 bytes because of the new functionality.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index c5295e2..c4a6b9d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3811,6 +3811,21 @@
     in libpng 1.5.7.
 
 Version 1.6.0beta03 [December 21, 2011]
+  Start-up code size improvements, error handler flexibility. These changes
+    alter how the tricky allocation of the initial png_struct and png_info
+    structures are handled. png_info is now handled in pretty much the same
+    way as everything else, except that the allocations handle NULL return
+    silently.  png_struct is changed in a similar way on allocation and on
+    deallocation a 'safety' error handler is put in place (which should never
+    be required).  The error handler itself is changed to permit mismatches
+    in the application and libpng error buffer size; however, this means a
+    silent change to the API to return the jmp_buf if the size doesn't match
+    the size from the libpng compilation; libpng now allocates the memory and
+    this may fail.  Overall these changes result in slight code size
+    reductions; however, this is a reduction in code that is always executed
+    so is particularly valuable.  Overall on a 64-bit system the libpng DLL
+    decreases in code size by 1733 bytes.  pngerror.o increases in size by
+    about 465 bytes because of the new functionality.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/png.c b/png.c
index 1be8dd8..b1fb74a 100644
--- a/png.c
+++ b/png.c
@@ -72,26 +72,20 @@
 PNG_FUNCTION(voidpf /* PRIVATE */,
 png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
 {
-   png_voidp ptr;
-   png_structp p=(png_structp)png_ptr;
-   png_uint_32 save_flags=p->flags;
-   png_alloc_size_t num_bytes;
+   png_alloc_size_t num_bytes = size;
 
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
-   if (items > PNG_UINT_32_MAX/size)
+   if (items >= (~(png_alloc_size_t)0)/size)
    {
-     png_warning (p, "Potential overflow in png_zalloc()");
-     return (NULL);
+      png_warning (png_voidcast(png_structp, png_ptr),
+         "Potential overflow in png_zalloc()");
+      return NULL;
    }
-   num_bytes = (png_alloc_size_t)items * size;
 
-   p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
-   ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
-   p->flags=save_flags;
-
-   return ((voidpf)ptr);
+   num_bytes *= items;
+   return png_malloc_warn(png_voidcast(png_structp, png_ptr), num_bytes);
 }
 
 /* Function to free memory for zlib */
@@ -220,12 +214,124 @@
    return 1;
 }
 
-/* Allocate the memory for an info_struct for the application.  We don't
- * really need the png_ptr, but it could potentially be useful in the
- * future.  This should be used in favour of malloc(png_sizeof(png_info))
- * and png_info_init() so that applications that want to use a shared
- * libpng don't have to be recompiled if png_info changes size.
+/* Generic function to create a png_struct for either read or write - this
+ * contains the common initialization.
  */
+PNG_FUNCTION(png_structp /* PRIVATE */,
+png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
+    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
+{
+   png_struct create_struct;
+#  ifdef PNG_SETJMP_SUPPORTED
+      jmp_buf create_jmp_buf;
+#  endif
+
+   /* This temporary stack-allocated structure is used to provide a place to
+    * build enough context to allow the user provided memory allocator (if any)
+    * to be called.
+    */
+   png_memset(&create_struct, 0, sizeof create_struct);
+
+   /* Added at libpng-1.2.6 */
+#  ifdef PNG_USER_LIMITS_SUPPORTED
+      create_struct.user_width_max = PNG_USER_WIDTH_MAX;
+      create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
+
+#     ifdef PNG_USER_CHUNK_CACHE_MAX
+         /* Added at libpng-1.2.43 and 1.4.0 */
+         create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
+#     endif
+
+#     ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
+         /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
+          * in png_struct regardless.
+          */
+         create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
+#     endif
+#  endif
+
+   /* The following two API calls simply set fields in png_struct, so it is safe
+    * to do them now even though error handling is not yet set up.
+    */
+#  ifdef PNG_USER_MEM_SUPPORTED
+      png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
+#  endif
+
+   /* (*error_fn) can return control to the caller after the error_ptr is set,
+    * this will result in a memory leak unless the error_fn does something
+    * extremely sophisticated.  The design lacks merit but is implicit in the
+    * API.
+    */
+   png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
+
+#  ifdef PNG_SETJMP_SUPPORTED
+      if (!setjmp(create_jmp_buf))
+      {
+         /* Temporarily fake out the longjmp information until we have
+          * successfully completed this function.  This only works if we have
+          * setjmp() support compiled in, but it is safe - this stuff should
+          * never happen.
+          */
+         create_struct.jmp_buf_ptr = &create_jmp_buf;
+         create_struct.jmp_buf_size = 0; /*stack allocation*/
+         create_struct.longjmp_fn = longjmp;
+#  else
+      {
+#  endif
+         /* Call the general version checker (shared with read and write code):
+          */
+         if (png_user_version_check(&create_struct, user_png_ver))
+         {
+
+            /* TODO: delay initializing the zlib structure until it really is
+             * needed.
+             */
+            /* Initialize zbuf - compression/decompression buffer */
+            create_struct.zbuf_size = PNG_ZBUF_SIZE;
+            create_struct.zbuf = png_voidcast(png_bytep,
+               png_malloc_warn(&create_struct, create_struct.zbuf_size));
+
+            /* Finally allocate the png_struct itself. */
+            if (create_struct.zbuf != NULL)
+            {
+               png_structp png_ptr = png_voidcast(png_structp,
+                  png_malloc_warn(&create_struct, sizeof *png_ptr));
+
+               if (png_ptr != NULL)
+               {
+#                 ifdef PNG_SETJMP_SUPPORTED
+                     /* Eliminate the local error handling: */
+                     create_struct.jmp_buf_ptr = NULL;
+                     create_struct.jmp_buf_size = 0;
+                     create_struct.longjmp_fn = 0;
+#                 endif
+
+                  *png_ptr = create_struct;
+
+                  /* This is the successful return point */
+                  return png_ptr;
+               }
+            }
+         }
+      }
+
+   /* A longjmp because of a bug in the application storage allocator or a
+    * simple failure to allocate the png_struct.
+    */
+   if (create_struct.zbuf != NULL)
+   {
+      png_bytep zbuf = create_struct.zbuf;
+
+      /* Ensure we don't keep on returning to this point: */
+      create_struct.zbuf = NULL;
+      png_free(&create_struct, zbuf);
+   }
+
+   return NULL;
+}
+
+/* Allocate the memory for an info_struct for the application. */
 PNG_FUNCTION(png_infop,PNGAPI
 png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED)
 {
@@ -234,24 +340,29 @@
    png_debug(1, "in png_create_info_struct");
 
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
-#ifdef PNG_USER_MEM_SUPPORTED
-   info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
-      png_ptr->malloc_fn, png_ptr->mem_ptr);
-#else
-   info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
-#endif
+   /* Use the internal API that does not (or at least should not) error out, so
+    * that this call always returns ok.  The application typically sets up the
+    * error handling *after* creating the info_struct because this is the way it
+    * has always been done in 'example.c'.
+    */
+   info_ptr = png_voidcast(png_infop, png_malloc_base(png_ptr,
+      sizeof *info_ptr));
+
    if (info_ptr != NULL)
-      png_info_init_3(&info_ptr, png_sizeof(png_info));
+      png_memset(info_ptr, 0, sizeof *info_ptr);
 
-   return (info_ptr);
+   return info_ptr;
 }
 
 /* This function frees the memory associated with a single info struct.
  * Normally, one would use either png_destroy_read_struct() or
  * png_destroy_write_struct() to free an info struct, but this may be
- * useful for some applications.
+ * useful for some applications.  From libpng 1.6.0 this function is also used
+ * internally to implement the png_info release part of the 'struct' destroy
+ * APIs.  This ensures that all possible approaches free the same data (all of
+ * it).
  */
 void PNGAPI
 png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
@@ -268,25 +379,31 @@
 
    if (info_ptr != NULL)
    {
-      png_info_destroy(png_ptr, info_ptr);
-
-#ifdef PNG_USER_MEM_SUPPORTED
-      png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
-          png_ptr->mem_ptr);
-#else
-      png_destroy_struct((png_voidp)info_ptr);
-#endif
+      /* Do this first in case of an error below; if the app implements its own
+       * memory management this can lead to png_free calling png_error, which
+       * will abort this routine and return control to the app error handler.
+       * An infinite loop may result if it then tries to free the same info
+       * ptr.
+       */
       *info_ptr_ptr = NULL;
+
+      png_info_destroy(png_ptr, info_ptr);
+      png_free(png_ptr, info_ptr);
    }
 }
 
 /* Initialize the info structure.  This is now an internal function (0.89)
  * and applications using it are urged to use png_create_info_struct()
- * instead.
+ * instead.  Use deprecated in 1.6.0, internal use removed (used internally it
+ * is just a memset).
+ *
+ * NOTE: it is almost inconceivable that this API is used because it bypasses
+ * the user-memory mechanism and the user error handling/warning mechanisms in
+ * those cases where it does anything other than a memset.
  */
-
-void PNGAPI
-png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
+PNG_FUNCTION(void,PNGAPI
+png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
+   PNG_DEPRECATED)
 {
    png_infop info_ptr = *ptr_ptr;
 
@@ -297,13 +414,16 @@
 
    if (png_sizeof(png_info) > png_info_struct_size)
    {
-      png_destroy_struct(info_ptr);
-      info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+      *ptr_ptr = NULL;
+      /* The following line is why this API should not be used: */
+      free(info_ptr);
+      info_ptr = png_voidcast(png_infop, png_malloc_base(NULL,
+         sizeof *info_ptr));
       *ptr_ptr = info_ptr;
    }
 
    /* Set everything to 0 */
-   png_memset(info_ptr, 0, png_sizeof(png_info));
+   png_memset(info_ptr, 0, sizeof *info_ptr);
 }
 
 void PNGAPI
@@ -548,7 +668,7 @@
    }
 #endif
 
-   png_info_init_3(&info_ptr, png_sizeof(png_info));
+   png_memset(info_ptr, 0, sizeof *info_ptr);
 }
 #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
 
diff --git a/png.h b/png.h
index 253b205..922a82e 100644
--- a/png.h
+++ b/png.h
@@ -1065,8 +1065,8 @@
 PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr),
     PNG_ALLOCATED);
 
-PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr,
-    png_size_t png_info_struct_size));
+PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr,
+    png_size_t png_info_struct_size), PNG_DEPRECATED);
 
 /* Writes all the PNG information before the image. */
 PNG_EXPORT(20, void, png_write_info_before_PLTE,
@@ -1894,8 +1894,9 @@
 
 #ifdef PNG_USER_MEM_SUPPORTED
 PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
-PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr));
+    png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED);
+PNG_EXPORTA(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr),
+   PNG_DEPRECATED);
 #endif
 
 #ifdef PNG_ERROR_TEXT_SUPPORTED
diff --git a/pngerror.c b/pngerror.c
index 319a038..0b0c518 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -492,11 +492,108 @@
 png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn,
     size_t jmp_buf_size)
 {
-   if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf))
+   /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
+    * and it must not change after that.  Libpng doesn't care how big the
+    * buffer is, just that it doesn't change.
+    *
+    * If the buffer size is no *larger* than the size of jmp_buf when libpng is
+    * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
+    * semantics that this call will not fail.  If the size is larger, however,
+    * the buffer is allocated and this may fail, causing the function to return
+    * NULL.
+    */
+   if (png_ptr == NULL)
       return NULL;
 
+   if (png_ptr->jmp_buf_ptr == NULL)
+   {
+      png_ptr->jmp_buf_size = 0; /* not allocated */
+
+      if (jmp_buf_size <= sizeof png_ptr->jmp_buf_local)
+         png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
+
+      else
+      {
+         png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
+            png_malloc_warn(png_ptr, jmp_buf_size));
+
+         if (png_ptr->jmp_buf_ptr == NULL)
+            return NULL; /* new NULL return on OOM */
+
+         png_ptr->jmp_buf_size = jmp_buf_size;
+      }
+   }
+
+   else /* Already allocated: check the size */
+   {
+      size_t size = png_ptr->jmp_buf_size;
+
+      if (size == 0)
+      {
+         size = sizeof png_ptr->jmp_buf_local;
+         if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
+         {
+            /* This is an internal error in libpng: somehow we have been left
+             * with a stack allocated jmp_buf when the application regained
+             * control.  It's always possible to fix this up, but for the moment
+             * this is a png_error because that makes it easy to detect.
+             */
+            png_error(png_ptr, "Libpng jmp_buf still allocated");
+            /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
+         }
+      }
+
+      if (size != jmp_buf_size)
+      {
+         png_warning(png_ptr, "Application jmp_buf size changed");
+         return NULL; /* caller will probably crash: no choice here */
+      }
+   }
+
+   /* Finally fill in the function, now we have a satisfactory buffer. It is
+    * valid to change the function on every call.
+    */
    png_ptr->longjmp_fn = longjmp_fn;
-   return &png_ptr->longjmp_buffer;
+   return png_ptr->jmp_buf_ptr;
+}
+
+void /* PRIVATE */
+png_free_jmpbuf(png_structp png_ptr)
+{
+   if (png_ptr != NULL)
+   {
+      jmp_buf *jb = png_ptr->jmp_buf_ptr;
+
+      /* A size of 0 is used to indicate a local, stack, allocation of the
+       * pointer; used here and in png.c
+       */
+      if (jb != NULL && png_ptr->jmp_buf_size > 0)
+      {
+
+         /* This stuff is so that a failure to free the error control structure
+          * does not leave libpng in a state with no valid error handling: the
+          * free always succeeds, if there is an error it gets ignored.
+          */
+         if (jb != &png_ptr->jmp_buf_local)
+         {
+            /* Make an internal, libpng, jmp_buf to return here */
+            jmp_buf free_jmp_buf;
+
+            if (!setjmp(free_jmp_buf))
+            {
+               png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
+               png_ptr->jmp_buf_size = 0; /* stack allocation */
+               png_ptr->longjmp_fn = longjmp;
+               png_free(png_ptr, jb); /* Return to setjmp on error */
+            }
+         }
+      }
+
+      /* *Always* cancel everything out: */
+      png_ptr->jmp_buf_size = 0;
+      png_ptr->jmp_buf_ptr = NULL;
+      png_ptr->longjmp_fn = 0;
+   }
 }
 #endif
 
@@ -556,8 +653,8 @@
 png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
 {
 #ifdef PNG_SETJMP_SUPPORTED
-   if (png_ptr && png_ptr->longjmp_fn)
-      png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val);
+   if (png_ptr && png_ptr->longjmp_fn && png_ptr->jmp_buf_ptr)
+      png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
 #endif
 
    /* Here if not setjmp support or if png_ptr is null. */
@@ -618,7 +715,7 @@
 /* This function is called when the application wants to use another method
  * of handling errors and warnings.  Note that the error function MUST NOT
  * return to the calling routine or serious problems will occur.  The return
- * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1)
+ * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
  */
 void PNGAPI
 png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
diff --git a/pngmem.c b/pngmem.c
index 4c14764..daed745 100644
--- a/pngmem.c
+++ b/pngmem.c
@@ -20,106 +20,23 @@
 #include "pngpriv.h"
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-/* Allocate memory for a png_struct or a png_info.  The malloc and
-   memset can be replaced by a single call to calloc() if this is thought
-   to improve performance noticably. */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct,(int type),PNG_ALLOCATED)
-{
-#  ifdef PNG_USER_MEM_SUPPORTED
-   return (png_create_struct_2(type, NULL, NULL));
-}
-
-/* Allocate memory for a png_struct or a png_info.  The malloc and
-   memset can be replaced by a single call to calloc() if this is thought
-   to improve performance noticably. */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr),
-   PNG_ALLOCATED)
-{
-#  endif /* PNG_USER_MEM_SUPPORTED */
-   png_size_t size;
-   png_voidp struct_ptr;
-
-   if (type == PNG_STRUCT_INFO)
-      size = png_sizeof(png_info);
-
-   else if (type == PNG_STRUCT_PNG)
-      size = png_sizeof(png_struct);
-
-   else
-      return (NULL);
-
-#  ifdef PNG_USER_MEM_SUPPORTED
-   if (malloc_fn != NULL)
-   {
-      png_struct dummy_struct;
-      png_structp png_ptr = &dummy_struct;
-      png_ptr->mem_ptr=mem_ptr;
-      struct_ptr = (*(malloc_fn))(png_ptr, size);
-
-      if (struct_ptr != NULL)
-         png_memset(struct_ptr, 0, size);
-
-      return (struct_ptr);
-   }
-#  endif /* PNG_USER_MEM_SUPPORTED */
-
-#  if defined(__TURBOC__) && !defined(__FLAT__)
-   struct_ptr = (png_voidp)farmalloc(size);
-#  else
-#    if defined(_MSC_VER) && defined(MAXSEG_64K)
-   struct_ptr = (png_voidp)halloc(size, 1);
-#    else
-   struct_ptr = (png_voidp)malloc(size);
-#    endif
-#  endif
-
-   if (struct_ptr != NULL)
-      png_memset(struct_ptr, 0, size);
-
-   return (struct_ptr);
-}
-
-
-/* Free memory allocated by a png_create_struct() call */
+/* Free a png_struct */
 void /* PRIVATE */
-png_destroy_struct(png_voidp struct_ptr)
+png_destroy_png_struct(png_structp png_ptr)
 {
-#  ifdef PNG_USER_MEM_SUPPORTED
-   png_destroy_struct_2(struct_ptr, NULL, NULL);
-}
-
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
-    png_voidp mem_ptr)
-{
-#  endif /* PNG_USER_MEM_SUPPORTED */
-   if (struct_ptr != NULL)
+   if (png_ptr != NULL)
    {
-#  ifdef PNG_USER_MEM_SUPPORTED
-      if (free_fn != NULL)
-      {
-         png_struct dummy_struct;
-         png_structp png_ptr = &dummy_struct;
-         png_ptr->mem_ptr=mem_ptr;
-         (*(free_fn))(png_ptr, struct_ptr);
-         return;
-      }
-#  endif /* PNG_USER_MEM_SUPPORTED */
-#  if defined(__TURBOC__) && !defined(__FLAT__)
-      farfree(struct_ptr);
+      /* png_free might call png_error and may certainly call
+       * png_get_mem_ptr, so fake a temporary png_struct to support this.
+       */
+      png_struct dummy_struct = *png_ptr;
+      memset(png_ptr, 0, sizeof *png_ptr);
+      png_free(&dummy_struct, png_ptr);
 
-#  else
-#    if defined(_MSC_VER) && defined(MAXSEG_64K)
-      hfree(struct_ptr);
-
-#    else
-      free(struct_ptr);
-
-#    endif
-#  endif
+#     ifdef PNG_SETJMP_SUPPORTED
+         /* We may have a jmp_buf left to deallocate. */
+         png_free_jmpbuf(&dummy_struct);
+#     endif
    }
 }
 
@@ -129,95 +46,107 @@
  * need to allocate exactly 64K, so whatever you call here must
  * have the ability to do that.
  */
-
 PNG_FUNCTION(png_voidp,PNGAPI
 png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
 {
    png_voidp ret;
 
-   ret = (png_malloc(png_ptr, size));
+   ret = png_malloc(png_ptr, size);
 
    if (ret != NULL)
-      png_memset(ret,0,(png_size_t)size);
+      png_memset(ret, 0, size);
 
-   return (ret);
+   return ret;
 }
 
+/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
+ * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
+ * Checking and error handling must happen outside this routine; it returns NULL
+ * if the allocation cannot be done (for any reason.)
+ */
+PNG_FUNCTION(png_voidp /* PRIVATE */,
+png_malloc_base,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+{
+   /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
+    * allocators have also been removed in 1.6.0, so any 16-bit system now has
+    * to implement a user memory handler.  This checks to be sure it isn't
+    * called with big numbers.
+    */
+   if (size > 0 && size <= ~(size_t)0
+#     ifdef PNG_MAX_MALLOC_64K
+         && size <= 65536U
+#     endif
+      )
+   {
+      if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
+         return png_ptr->malloc_fn(png_ptr, size);
+
+      else
+         return malloc((size_t)size); /* checked for truncation above */
+   }
+
+   else
+      return NULL;
+}
+
+/* Various functions that have different error handling are derived from this.
+ * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
+ * function png_malloc_default is also provided.
+ */
 PNG_FUNCTION(png_voidp,PNGAPI
 png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
 {
    png_voidp ret;
 
-#  ifdef PNG_USER_MEM_SUPPORTED
-   if (png_ptr == NULL || size == 0)
-      return (NULL);
+   if (png_ptr == NULL)
+      return NULL;
 
-   if (png_ptr->malloc_fn != NULL)
-      ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+   ret = png_malloc_base(png_ptr, size);
 
-   else
-      ret = (png_malloc_default(png_ptr, size));
+   if (ret == NULL)
+       png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
 
-   if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
-       png_error(png_ptr, "Out of Memory");
-
-   return (ret);
+   return ret;
 }
 
+#ifdef PNG_USER_MEM_SUPPORTED
 PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),
+   PNG_ALLOCATED PNG_DEPRECATED)
 {
    png_voidp ret;
-#  endif /* PNG_USER_MEM_SUPPORTED */
 
-   if (png_ptr == NULL || size == 0)
-      return (NULL);
+   if (png_ptr == NULL)
+      return NULL;
 
-#  ifdef PNG_MAX_MALLOC_64K
-   if (size > (png_uint_32)65536L)
+   /* Passing 'NULL' here bypasses the application provided memory handler. */
+   ret = png_malloc_base(NULL/*use malloc*/, size);
+
+   if (ret == NULL)
+      png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
+
+   return ret;
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+/* This function was added at libpng version 1.2.3.  The png_malloc_warn()
+ * function will issue a png_warning and return NULL instead of issuing a
+ * png_error, if it fails to allocate the requested memory.
+ */
+PNG_FUNCTION(png_voidp,PNGAPI
+png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+{
+   if (png_ptr != NULL)
    {
-#    ifndef PNG_USER_MEM_SUPPORTED
-      if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
-         png_error(png_ptr, "Cannot Allocate > 64K");
+      png_voidp ret = png_malloc_base(png_ptr, size);
 
-      else
-#    endif
-         return NULL;
+      if (ret != NULL)
+         return ret;
+
+      png_warning(png_ptr, "Out of memory");
    }
-#  endif
 
-   /* Check for overflow */
-#  if defined(__TURBOC__) && !defined(__FLAT__)
-
-   if (size != (unsigned long)size)
-      ret = NULL;
-
-   else
-      ret = farmalloc(size);
-
-#  else
-#    if defined(_MSC_VER) && defined(MAXSEG_64K)
-   if (size != (unsigned long)size)
-      ret = NULL;
-
-   else
-      ret = halloc(size, 1);
-
-#    else
-   if (size != (size_t)size)
-      ret = NULL;
-
-   else
-      ret = malloc((size_t)size);
-#    endif
-#  endif
-
-#  ifndef PNG_USER_MEM_SUPPORTED
-   if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
-      png_error(png_ptr, "Out of Memory");
-#  endif
-
-   return (ret);
+   return NULL;
 }
 
 /* Free a pointer allocated by png_malloc().  If ptr is NULL, return
@@ -229,60 +158,24 @@
    if (png_ptr == NULL || ptr == NULL)
       return;
 
-#  ifdef PNG_USER_MEM_SUPPORTED
+#ifdef PNG_USER_MEM_SUPPORTED
    if (png_ptr->free_fn != NULL)
-   {
-      (*(png_ptr->free_fn))(png_ptr, ptr);
-      return;
-   }
+      png_ptr->free_fn(png_ptr, ptr);
 
    else
       png_free_default(png_ptr, ptr);
 }
 
-void PNGAPI
-png_free_default(png_structp png_ptr, png_voidp ptr)
+PNG_FUNCTION(void,PNGAPI
+png_free_default,(png_structp png_ptr, png_voidp ptr),PNG_DEPRECATED)
 {
    if (png_ptr == NULL || ptr == NULL)
       return;
+#endif /* PNG_USER_MEM_SUPPORTED */
 
-#  endif /* PNG_USER_MEM_SUPPORTED */
-
-#  if defined(__TURBOC__) && !defined(__FLAT__)
-   farfree(ptr);
-
-#  else
-#    if defined(_MSC_VER) && defined(MAXSEG_64K)
-   hfree(ptr);
-
-#    else
    free(ptr);
-
-#    endif
-#  endif
 }
 
-/* This function was added at libpng version 1.2.3.  The png_malloc_warn()
- * function will set up png_malloc() to issue a png_warning and return NULL
- * instead of issuing a png_error, if it fails to allocate the requested
- * memory.
- */
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
-   png_voidp ptr;
-   png_uint_32 save_flags;
-   if (png_ptr == NULL)
-      return (NULL);
-
-   save_flags = png_ptr->flags;
-   png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
-   ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
-   png_ptr->flags=save_flags;
-   return(ptr);
-}
-
-
 #ifdef PNG_USER_MEM_SUPPORTED
 /* This function is called when the application wants to use another method
  * of allocating and freeing memory.
@@ -307,9 +200,9 @@
 png_get_mem_ptr(png_const_structp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
-   return ((png_voidp)png_ptr->mem_ptr);
+   return png_ptr->mem_ptr;
 }
 #endif /* PNG_USER_MEM_SUPPORTED */
 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/pngpriv.h b/pngpriv.h
index 83da3c4..3e8c5e1 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -489,7 +489,7 @@
 #define PNG_FLAG_LIBRARY_MISMATCH         0x20000
 #define PNG_FLAG_STRIP_ERROR_NUMBERS      0x40000
 #define PNG_FLAG_STRIP_ERROR_TEXT         0x80000
-#define PNG_FLAG_MALLOC_NULL_MEM_OK       0x100000
+                                  /*      0x100000  unused */
                                   /*      0x200000  unused */
                                   /*      0x400000  unused */
 #define PNG_FLAG_BENIGN_ERRORS_WARN       0x800000  /* Added to libpng-1.4.0 */
@@ -677,35 +677,48 @@
 extern "C" {
 #endif /* __cplusplus */
 
-/* These functions are used internally in the code.  They generally
- * shouldn't be used unless you are writing code to add or replace some
- * functionality in libpng.  More information about most functions can
- * be found in the files where the functions are located.
+/* Internal functions; these are not exported from a DLL however because they
+ * are used within several of the C source files they have to be C extern.
  */
 
 /* Check the user version string for compatibility, returns false if the version
  * numbers aren't compatible.
  */
-PNG_EXTERN int png_user_version_check(png_structp png_ptr,
-   png_const_charp user_png_ver);
+PNG_EXTERN int png_user_version_check PNGARG((png_structp png_ptr,
+   png_const_charp user_png_ver));
 
-/* Allocate memory for an internal libpng struct */
-PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)),
-   PNG_ALLOCATED);
+/* Internal base allocator - no messages, NULL on failure to allocate.  This
+ * does, however, call the application provided allocator and that could call
+ * png_error (although that would be a bug in the application implementation.)
+ */
+PNG_EXTERN PNG_FUNCTION(png_voidp,png_malloc_base,PNGARG((png_structp png_ptr,
+   png_alloc_size_t size)),PNG_ALLOCATED);
+
+/* Magic to create a struct when there is no struct to call the user supplied
+ * memory allocators.  Because error handling has not been set up the memory
+ * handlers can't safely call png_error, but this is an obscure and undocumented
+ * restriction so libpng has to assume that the 'free' handler, at least, might
+ * call png_error.
+ */
+PNG_EXTERN PNG_FUNCTION(png_structp,png_create_png_struct,
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+    png_malloc_ptr malloc_fn, png_free_ptr free_fn)),PNG_ALLOCATED);
 
 /* Free memory from internal libpng struct */
-PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
-
-PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2,
-   PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)),
-   PNG_ALLOCATED);
-PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
-    png_free_ptr free_fn, png_voidp mem_ptr));
+#if 0 /* no longer used */
+PNG_EXTERN void png_destroy_struct_2 PNGARG((png_structp png_ptr,
+    png_voidp struct_ptr));
+#endif
+PNG_EXTERN void png_destroy_png_struct PNGARG((png_structp png_ptr));
 
 /* Free any memory that info_ptr points to and reset struct. */
 PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
     png_infop info_ptr));
 
+/* Free an allocated jmp_buf (always succeeds) */
+PNG_EXTERN void png_free_jmpbuf PNGARG((png_structp png_ptr));
+
 /* Function to allocate memory for zlib.  PNGAPI is disallowed. */
 PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items,
    uInt size)),PNG_ALLOCATED);
@@ -1375,13 +1388,6 @@
     int color_type, int interlace_type, int compression_type,
     int filter_type));
 
-/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr,
-    png_infop info_ptr, png_infop end_info_ptr));
-
-/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr));
-
 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
 PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr,
    png_const_charp name),PNG_NORETURN);
diff --git a/pngstruct.h b/pngstruct.h
index 07f3a04..da7ad0c 100644
--- a/pngstruct.h
+++ b/pngstruct.h
@@ -29,8 +29,10 @@
 struct png_struct_def
 {
 #ifdef PNG_SETJMP_SUPPORTED
-   jmp_buf longjmp_buffer;    /* used in png_error */
    png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
+   jmp_buf *jmp_buf_ptr;      /* passed to longjmp_fn */
+   size_t jmp_buf_size;       /* size of the above, if allocated */
+   jmp_buf jmp_buf_local;     /* New name in 1.6.0 for jmp_buf in png_struct */
 #endif
    png_error_ptr error_fn;    /* function for printing errors and aborting */
 #ifdef PNG_WARNINGS_SUPPORTED
diff --git a/pngwrite.c b/pngwrite.c
index bc68d56..d13cd39 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -449,92 +449,34 @@
 png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
     png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
 {
-#ifdef PNG_USER_MEM_SUPPORTED
-   return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
-       warn_fn, NULL, NULL, NULL));
+#ifndef PNG_USER_MEM_SUPPORTED
+   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+      error_fn, warn_fn, NULL, NULL, NULL);
+#else
+   return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+       warn_fn, NULL, NULL, NULL);
 }
 
 /* Alternate initialize png_ptr structure, and allocate any memory needed */
-static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */
-
 PNG_FUNCTION(png_structp,PNGAPI
 png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
     png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
     png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
 {
+   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+      error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
 #endif /* PNG_USER_MEM_SUPPORTED */
-   volatile int png_cleanup_needed = 0;
-#ifdef PNG_SETJMP_SUPPORTED
-   volatile
-#endif
-   png_structp png_ptr;
 
-   png_debug(1, "in png_create_write_struct");
-
-#ifdef PNG_USER_MEM_SUPPORTED
-   png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
-       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
-#else
-   png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-#endif /* PNG_USER_MEM_SUPPORTED */
-   if (png_ptr == NULL)
-      return (NULL);
-
-   /* Added at libpng-1.2.6 */
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
-   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
-#endif
-
-#ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then
- * encounter a png_error() will longjmp here.  Since the jmpbuf is
- * then meaningless we abort instead of returning.
- */
-   if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
-      PNG_ABORT();
-#endif
-
-#ifdef PNG_USER_MEM_SUPPORTED
-   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
-#endif /* PNG_USER_MEM_SUPPORTED */
-   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
-
-   if (!png_user_version_check(png_ptr, user_png_ver))
-      png_cleanup_needed = 1;
-
-   /* Initialize zbuf - compression buffer */
-   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
-
-   if (!png_cleanup_needed)
+   if (png_ptr != NULL)
    {
-      png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
-          png_ptr->zbuf_size);
-      if (png_ptr->zbuf == NULL)
-         png_cleanup_needed = 1;
+      /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
+       * do it itself) avoiding setting the default function if it is not
+       * required.
+       */
+      png_set_write_fn(png_ptr, NULL, NULL, NULL);
    }
 
-   if (png_cleanup_needed)
-   {
-       /* Clean up PNG structure and deallocate any memory. */
-       png_free(png_ptr, png_ptr->zbuf);
-       png_ptr->zbuf = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
-       png_destroy_struct_2((png_voidp)png_ptr,
-           (png_free_ptr)free_fn, (png_voidp)mem_ptr);
-#else
-       png_destroy_struct((png_voidp)png_ptr);
-#endif
-       return (NULL);
-   }
-
-   png_set_write_fn(png_ptr, NULL, NULL, NULL);
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   png_reset_filter_heuristics(png_ptr);
-#endif
-
-   return (png_ptr);
+   return png_ptr;
 }
 
 
@@ -862,87 +804,14 @@
 }
 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
 
-/* Free all memory used by the write */
-void PNGAPI
-png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
-{
-   png_structp png_ptr = NULL;
-   png_infop info_ptr = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
-   png_free_ptr free_fn = NULL;
-   png_voidp mem_ptr = NULL;
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */
 #endif
 
-   png_debug(1, "in png_destroy_write_struct");
-
-   if (png_ptr_ptr != NULL)
-      png_ptr = *png_ptr_ptr;
-
-#ifdef PNG_USER_MEM_SUPPORTED
-   if (png_ptr != NULL)
-   {
-      free_fn = png_ptr->free_fn;
-      mem_ptr = png_ptr->mem_ptr;
-   }
-#endif
-
-   if (info_ptr_ptr != NULL)
-      info_ptr = *info_ptr_ptr;
-
-   if (info_ptr != NULL)
-   {
-      if (png_ptr != NULL)
-      {
-         png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-         if (png_ptr->num_chunk_list)
-         {
-            png_free(png_ptr, png_ptr->chunk_list);
-            png_ptr->num_chunk_list = 0;
-         }
-#endif
-      }
-
-#ifdef PNG_USER_MEM_SUPPORTED
-      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
-          (png_voidp)mem_ptr);
-#else
-      png_destroy_struct((png_voidp)info_ptr);
-#endif
-      *info_ptr_ptr = NULL;
-   }
-
-   if (png_ptr != NULL)
-   {
-      png_write_destroy(png_ptr);
-#ifdef PNG_USER_MEM_SUPPORTED
-      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
-          (png_voidp)mem_ptr);
-#else
-      png_destroy_struct((png_voidp)png_ptr);
-#endif
-      *png_ptr_ptr = NULL;
-   }
-}
-
-
-/* Free any memory used in png_ptr struct (old method) */
-void /* PRIVATE */
+/* Free any memory used in png_ptr struct without freeing the struct itself. */
+static void
 png_write_destroy(png_structp png_ptr)
 {
-#ifdef PNG_SETJMP_SUPPORTED
-   jmp_buf tmp_jmp; /* Save jump buffer */
-#endif
-   png_error_ptr error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
-   png_error_ptr warning_fn;
-#endif
-   png_voidp error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
-   png_free_ptr free_fn;
-#endif
-
    png_debug(1, "in png_write_destroy");
 
    /* Free any memory zlib uses */
@@ -967,34 +836,41 @@
    png_free(png_ptr, png_ptr->inv_filter_costs);
 #endif
 
-#ifdef PNG_SETJMP_SUPPORTED
-   /* Reset structure */
-   png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+   png_free(png_ptr, png_ptr->chunk_list);
 #endif
 
-   error_fn = png_ptr->error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
-   warning_fn = png_ptr->warning_fn;
-#endif
-   error_ptr = png_ptr->error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
-   free_fn = png_ptr->free_fn;
-#endif
+   /* The error handling and memory handling information is left intact at this
+    * point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
+    * for how this happens.
+    */
+}
 
-   png_memset(png_ptr, 0, png_sizeof(png_struct));
+/* Free all memory used by the write.
+ * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
+ * *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
+ * the passed in info_structs but it would quietly fail to free any of the data
+ * inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
+ * has no png_ptr.)
+ */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+   png_debug(1, "in png_destroy_write_struct");
 
-   png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
-   png_ptr->warning_fn = warning_fn;
-#endif
-   png_ptr->error_ptr = error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
-   png_ptr->free_fn = free_fn;
-#endif
+   if (png_ptr_ptr != NULL)
+   {
+      png_structp png_ptr = *png_ptr_ptr;
 
-#ifdef PNG_SETJMP_SUPPORTED
-   png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
-#endif
+      if (png_ptr != NULL) /* added in libpng 1.6.0 */
+      {
+         png_destroy_info_struct(png_ptr, info_ptr_ptr);
+
+         *png_ptr_ptr = NULL;
+         png_write_destroy(png_ptr);
+         png_destroy_png_struct(png_ptr);
+      }
+   }
 }
 
 /* Allow the application to select one or more row filters to use. */