]> granicus.if.org Git - imagemagick/commitdiff
coders/png.c: Update zxIf support to latest (2017-0128) proposal. Go back
authorGlenn Randers-Pehrson <glennrp@gmail.com>
Sun, 29 Jan 2017 00:33:42 +0000 (19:33 -0500)
committerGlenn Randers-Pehrson <glennrp@gmail.com>
Sun, 29 Jan 2017 00:33:42 +0000 (19:33 -0500)
to one-pass decoding of the compressed data.

coders/png.c

index 5b5c1a55f71e3da80008113bb2109ddab6057627..62df4b3706413993e40f92624575665edf51a488 100644 (file)
@@ -1833,71 +1833,8 @@ Magick_png_read_raw_profile(png_struct *ping,Image *image,
 
 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
 #ifdef zxIf_SUPPORTED
-#define CHUNK 4096
-#define MAX_CHUNK_SIZE 40000000
-/* Derived from code in libpng-1.4.1beta06 */
-png_size_t
-measure_decompressed_chunk(unsigned char *source, png_size_t chunklength)
-{
-   png_size_t text_size = 0;
-   z_stream zstream;
-   png_byte temp[CHUNK];
-
-   {
-      int ret = Z_OK;
-
-      /* allocate inflate state */
-      zstream.zalloc = Z_NULL;
-      zstream.zfree = Z_NULL;
-      zstream.opaque = Z_NULL;
-      ret = inflateInit(&zstream);
-      if (ret != Z_OK)
-          return (-1);
-
-      zstream.next_in = source;
-      zstream.avail_in = (uInt)(chunklength);
-      zstream.next_out = temp;
-      zstream.avail_out = CHUNK;
-
-      while (zstream.avail_in)
-      {
-         ret = inflate(&zstream, Z_PARTIAL_FLUSH);
-         if (ret != Z_OK && ret != Z_STREAM_END)
-         {
-            inflateReset(&zstream);
-            zstream.avail_in = 0;
-            break;
-         }
-         if (!zstream.avail_out || ret == Z_STREAM_END)
-         {
-            if (text_size == 0)  /* Initialize the decompression buffer */
-            {
-               text_size = CHUNK - zstream.avail_out;
-            }
-            else               /* Enlarge the decompression buffer */
-            {
-              text_size += CHUNK - zstream.avail_out;
-              if (text_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
-                 return 0;
-            }
-         }
-         if (ret == Z_STREAM_END)
-            break;
-
-         else
-         {
-            zstream.next_out = temp;
-            zstream.avail_out = CHUNK;
-         }
-      }
 
-      inflateReset(&zstream);
-      zstream.avail_in = 0;
-   }
-   return text_size;
-}
-
-/* exif_inf() derived from zlib-1.2.11/examples/zpipe.c/inf()
+/* exif_inf() was derived from zlib-1.2.11/examples/zpipe.c/inf()
    Not copyrighted -- provided to the public domain
    Version 1.4  11 December 2005  Mark Adler */
 
@@ -1911,7 +1848,7 @@ measure_decompressed_chunk(unsigned char *source, png_size_t chunklength)
    is an error reading or writing the files. */
 
 int exif_inf(png_structp png_ptr, unsigned char *source,
-    unsigned char **dest, size_t n)
+    unsigned char **dest, size_t n, png_uint_32 inflated_size)
 {
     /* *source: compressed data stream (input)
        *dest:   inflated data (output)
@@ -1925,9 +1862,10 @@ int exif_inf(png_structp png_ptr, unsigned char *source,
     int ret;
     z_stream strm;
 
-    size_t inflated_length= measure_decompressed_chunk(source, n);
+    size_t inflated_length = inflated_size;
 
-    if (inflated_length == 0)
+    if (inflated_length >= PNG_USER_CHUNK_MALLOC_MAX - 1U ||
+        inflated_length == 0)
         return (-1);
 
     /* allocate dest */
@@ -1938,7 +1876,6 @@ int exif_inf(png_structp png_ptr, unsigned char *source,
     *dest=(unsigned char *) png_malloc(png_ptr,
        (png_size_t) inflated_length);
 #endif
-
     /* allocate inflate state */
     strm.zalloc = Z_NULL;
     strm.zfree = Z_NULL;
@@ -1948,10 +1885,8 @@ int exif_inf(png_structp png_ptr, unsigned char *source,
     ret = inflateInit(&strm);
     if (ret != Z_OK)
         return (-1);
-
     /* decompress until deflate stream ends or end of file */
     do {
-
         strm.avail_in = (int)n;
         strm.next_in = source;
 
@@ -1959,7 +1894,6 @@ int exif_inf(png_structp png_ptr, unsigned char *source,
         do {
             strm.avail_out = (int)inflated_length;
             strm.next_out = *dest;
-
             ret = inflate(&strm, Z_NO_FLUSH);
             assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
             switch (ret) {
@@ -1974,6 +1908,9 @@ int exif_inf(png_structp png_ptr, unsigned char *source,
     } while (ret != Z_STREAM_END);
 
     /* clean up and return */
+
+    /* To do: take care of too little or too much data */
+
     (void)inflateEnd(&strm);
     return (inflated_length);
 }
@@ -2009,16 +1946,11 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
       chunk-> name[3] == 102)
     {
       /* process uxIf or zxIf chunk */
-#ifdef IM
       StringInfo *
         profile;
 
       PNGErrorInfo
         *error_info;
-#else /* GM */
-      unsigned char *
-        profile;
-#endif /* IM */
 
       unsigned char
         *p;
@@ -2034,7 +1966,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
 
       image=(Image *) png_get_user_chunk_ptr(ping);
 
-#ifdef IM
       error_info=(PNGErrorInfo *) png_get_error_ptr(ping);
 
       profile=BlobToStringInfo((const void *) NULL,chunk->size+6);
@@ -2047,16 +1978,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
           return(-1);
         }
       p=GetStringInfoDatum(profile);
-#else /* GM */
-#if PNG_LIBPNG_VER >= 14000
-      profile=(unsigned char *) png_malloc(ping,
-        (png_alloc_size_t) chunk->size+6);
-#else
-      profile=(unsigned char *) png_malloc(ping,
-         (png_size_t) chunk->size+6);
-#endif
-      p = profile;
-#endif /* IM */
 
       /* Initialize profile with "Exif\0\0" */
       *p++ ='E';
@@ -2071,10 +1992,8 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
 
       switch (chunk->data[0])
         {
-#ifdef IM
           PNGErrorInfo
             *error_info;
-#endif
           case 'E':
           case 'I':
           {
@@ -2087,15 +2006,9 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                "     SetImageProfile with %lu bytes",
                (unsigned long) chunk->size+6);
-#ifdef IM
             error_info=(PNGErrorInfo *) png_get_error_ptr(ping);
             (void) SetImageProfile(image,"exif",profile,
               error_info->exception);
-#else
-            (void) SetImageProfile(image,"exif",
-               (const unsigned char *)profile, chunk->size+6);
-#endif /* GM */
-
             return(1);
           }
           case '\0':
@@ -2105,28 +2018,34 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
             unsigned char *
               temp;
 
-            int inflated_size;
+            png_uint_32 inflated_size;
 
             png_free(ping,profile);
 
+            if (chunk->size < 5)
+               return(-1);
+
             s=chunk->data;
             s++;  // skip compression byte
 
-            /* uncompress chunk->data to temporary profile */
-            inflated_size=exif_inf(ping,s,&temp,chunk->size-1);
+            inflated_size = (png_uint_32)
+               (((s[0] & 0xff) << 24) | ((s[1] & 0xff) << 16) |
+                ((s[2] & 0xff) <<  8) | ((s[3] & 0xff)      ));
+
+            s+=4;
 
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-               "exif_inf returned %lu bytes for inflated_size",
-               (unsigned long) inflated_size);
+               "     inflated_size = %lu bytes",inflated_size);
+
+            /* uncompress chunk->data to temporary profile */
+            inflated_size=exif_inf(ping,s,&temp,chunk->size-1,inflated_size);
 
             if (inflated_size <= 0)
             {
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                  "     inflated_size = %d bytes",inflated_size);
+                  "     inflated_size = %lu bytes",inflated_size);
                return(-1);
             }
-
-#ifdef IM
            error_info=(PNGErrorInfo *) png_get_error_ptr(ping);
 
            profile=BlobToStringInfo((const void *) NULL,inflated_size+6);
@@ -2140,17 +2059,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
                return(-1);
              }
            p=GetStringInfoDatum(profile);
-#else /* GM */
-#if PNG_LIBPNG_VER >= 14000
-           profile=(unsigned char *) png_malloc(ping,
-             (png_alloc_size_t) inflated_size+6);
-#else
-           profile=(unsigned char *) png_malloc(ping,
-              (png_size_t) inflated_size+6);
-#endif
-           p = profile;
-#endif /* IM */
-
            /* Initialize profile with "Exif\0\0" */
            *p++ ='E';
            *p++ ='x';
@@ -2165,14 +2073,9 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                "     SetImageProfile with %lu bytes",
                (unsigned long) inflated_size+6);
-#ifdef IM
             error_info=(PNGErrorInfo *) png_get_error_ptr(ping);
             (void) SetImageProfile(image,"exif",profile,
               error_info->exception);
-#else
-            (void) SetImageProfile(image,"exif",
-               (const unsigned char *)profile, inflated_size+6);
-#endif /* GM */
 
             png_free(ping,temp);
 
@@ -2183,23 +2086,17 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
 #endif /* zxIf_SUPPORTED */
 
   if (chunk->name[0]  == 101 &&
-      (chunk->name[1] ==   88 || chunk->name[1] == 120 ) &&
+      (chunk->name[1] ==  88 || chunk->name[1] == 120 ) &&
       chunk->name[2] ==   73 &&
       chunk-> name[3] == 102)
     {
       /* process eXIf or exIf chunk */
 
-#ifdef IM
       PNGErrorInfo
         *error_info;
 
       StringInfo
         *profile;
-#else /* GM */
-
-      unsigned char
-        *profile;
-#endif /* IM */
 
       unsigned char
         *p;
@@ -2215,7 +2112,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
 
       image=(Image *) png_get_user_chunk_ptr(ping);
 
-#ifdef IM
       error_info=(PNGErrorInfo *) png_get_error_ptr(ping);
 
       profile=BlobToStringInfo((const void *) NULL,chunk->size+6);
@@ -2228,18 +2124,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
           return(-1);
         }
       p=GetStringInfoDatum(profile);
-#else /* GM */
-
-#if PNG_LIBPNG_VER >= 14000
-      profile=(unsigned char *) png_malloc(ping,
-        (png_alloc_size_t) chunk->size+6);
-#else
-      profile=(unsigned char *) png_malloc(ping,
-         (png_size_t) chunk->size+6);
-#endif
-      p = profile;
-
-#endif /* GM */
 
       /* Initialize profile with "Exif\0\0" */
       *p++ ='E';
@@ -2254,19 +2138,13 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
       for (i=0; i<chunk->size; i++)
         *p++ = *s++;
 
-#ifdef IM
       error_info=(PNGErrorInfo *) png_get_error_ptr(ping);
       (void) SetImageProfile(image,"exif",profile,
         error_info->exception);
-#else
-      (void) SetImageProfile(image,"exif",
-         (const unsigned char *)profile, chunk->size+6);
-#endif /* GM */
 
       return(1);
     }
 
-#ifdef IM
   /* vpAg (deprecated, replaced by caNv) */
   if (chunk->name[0] == 118 &&
       chunk->name[1] == 112 &&
@@ -2291,7 +2169,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
 
      return(1);
     }
-#endif /* IM */
 
   /* caNv */
   if (chunk->name[0] ==  99 &&
@@ -2318,11 +2195,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
      image->page.y=(size_t) ((chunk->data[12] << 24) |
         (chunk->data[13] << 16) | (chunk->data[14] << 8) | chunk->data[15]);
 
-     /* Return one of the following: */
-        /* return(-n);  chunk had an error */
-        /* return(0);  did not recognize */
-        /* return(n);  success */
-
      return(1);
     }
 
@@ -7946,7 +7818,7 @@ ModuleExport size_t RegisterPNGImage(void)
 #endif
 
   entry=AcquireMagickInfo("PNG","MNG","Multiple-image Network Graphics");
-  entry->flags|=CoderDecoderSeekableStreamFlag;  /* To do: eliminate this. */
+  entry->flags|=CoderSeekableStreamFlag;  /* To do: eliminate this. */
 
 #if defined(MAGICKCORE_PNG_DELEGATE)
   entry->decoder=(DecodeImageHandler *) ReadMNGImage;