Imported Upstream version 1.6.36
[platform/upstream/libpng.git] / contrib / gregbook / readpng.c
index abfc1fb..fad9b53 100644 (file)
@@ -4,7 +4,7 @@
 
   ---------------------------------------------------------------------------
 
-      Copyright (c) 1998-2007 Greg Roelofs.  All rights reserved.
+      Copyright (c) 1998-2007,2017 Greg Roelofs.  All rights reserved.
 
       This software is provided "as is," without warranty of any kind,
       express or implied.  In no event shall the author or contributors
@@ -55,8 +55,9 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <zlib.h>
 
-#include "png.h"        /* libpng header; includes zlib.h */
+#include "png.h"        /* libpng header */
 #include "readpng.h"    /* typedefs, common macros, public prototypes */
 
 /* future versions of libpng will provide this macro: */
@@ -99,7 +100,8 @@ int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
 
     /* could pass pointers to user-defined error handlers instead of NULLs: */
 
-    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL,
+        NULL);
     if (!png_ptr)
         return 4;   /* out of memory */
 
@@ -214,6 +216,10 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
      * libpng function */
 
     if (setjmp(png_jmpbuf(png_ptr))) {
+        free(image_data);
+        image_data = NULL;
+        free(row_pointers);
+        row_pointers = NULL;
         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
         return NULL;
     }
@@ -229,8 +235,14 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
         png_set_expand(png_ptr);
     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
         png_set_expand(png_ptr);
+#ifdef PNG_READ_16_TO_8_SUPPORTED
     if (bit_depth == 16)
+#  ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+        png_set_scale_16(png_ptr);
+#  else
         png_set_strip_16(png_ptr);
+#  endif
+#endif
     if (color_type == PNG_COLOR_TYPE_GRAY ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
         png_set_gray_to_rgb(png_ptr);
@@ -252,6 +264,12 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
     *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
     *pChannels = (int)png_get_channels(png_ptr, info_ptr);
 
+    /* Guard against integer overflow */
+    if (height > ((size_t)(-1))/rowbytes) {
+        fprintf(stderr, "readpng:  image_data buffer would be too large\n",
+        return NULL;
+    }
+
     if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
         return NULL;
@@ -263,7 +281,8 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
         return NULL;
     }
 
-    Trace((stderr, "readpng_get_image:  channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height));
+    Trace((stderr, "readpng_get_image:  channels = %d, rowbytes = %ld, height = %ld\n",
+        *pChannels, rowbytes, height));
 
 
     /* set the individual row_pointers to point at the correct offsets */