< prev index next >

src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c

Print this page

        

@@ -27,12 +27,12 @@
  * This file is available under and governed by the GNU General Public
  * License version 2 only, as published by the Free Software Foundation.
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Last changed in libpng 1.6.27 [January 5, 2017]
- * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.33 [September 28, 2017]
+ * Copyright (c) 1998-2002,2004,2006-2017 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.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer

@@ -207,10 +207,13 @@
    png_calculate_crc(png_ptr, buf + 4, 4);
 
    /* Check to see if chunk name is valid. */
    png_check_chunk_name(png_ptr, png_ptr->chunk_name);
 
+   /* Check for too-large chunk length */
+   png_check_chunk_length(png_ptr, length);
+
 #ifdef PNG_IO_STATE_SUPPORTED
    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
 #endif
 
    return length;

@@ -337,10 +340,11 @@
    {
       buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size));
 
       if (buffer != NULL)
       {
+         memset(buffer, 0, new_size); /* just in case */
          png_ptr->read_buffer = buffer;
          png_ptr->read_buffer_size = new_size;
       }
 
       else if (warn < 2) /* else silent */

@@ -444,11 +448,11 @@
 
          if (ret == Z_OK)
             png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
       }
 
-#if ZLIB_VERNUM >= 0x1281 && \
+#if ZLIB_VERNUM >= 0x1290 && \
    defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32)
       if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON)
          /* Turn off validation of the ADLER32 checksum in IDAT chunks */
          ret = inflateValidate(&png_ptr->zstream, 0);
 #endif

@@ -696,10 +700,12 @@
                png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr,
                    buffer_size));
 
                if (text != NULL)
                {
+                  memset(text, 0, buffer_size);
+
                   ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
                       png_ptr->read_buffer + prefix_size, &lzsize,
                       text + prefix_size, newlength);
 
                   if (ret == Z_STREAM_END)

@@ -759,12 +765,10 @@
 
             else
             {
                /* inflateReset failed, store the error message */
                png_zstream_error(png_ptr, ret);
-
-               if (ret == Z_STREAM_END)
                   ret = PNG_UNEXPECTED_ZLIB_RETURN;
             }
          }
 
          else if (ret == Z_OK)

@@ -1403,15 +1407,17 @@
 
    /* Consistent with all the above colorspace handling an obviously *invalid*
     * chunk is just ignored, so does not invalidate the color space.  An
     * alternative is to set the 'invalid' flags at the start of this routine
     * and only clear them in they were not set before and all the tests pass.
-    * The minimum 'deflate' stream is assumed to be just the 2 byte header and
-    * 4 byte checksum.  The keyword must be at least one character and there is
-    * a terminator (0) byte and the compression method.
     */
-   if (length < 9)
+
+   /* The keyword must be at least one character and there is a
+    * terminator (0) byte and the compression method byte, and the
+    * 'zlib' datastream is at least 11 bytes.
+    */
+   if (length < 14)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "too short");
       return;
    }

@@ -1439,10 +1445,20 @@
          read_length = (uInt)length;
 
       png_crc_read(png_ptr, (png_bytep)keyword, read_length);
       length -= read_length;
 
+      /* The minimum 'zlib' stream is assumed to be just the 2 byte header,
+       * 5 bytes minimum 'deflate' stream, and the 4 byte checksum.
+       */
+      if (length < 11)
+      {
+         png_crc_finish(png_ptr, length);
+         png_chunk_benign_error(png_ptr, "too short");
+         return;
+      }
+
       keyword_length = 0;
       while (keyword_length < 80 && keyword_length < read_length &&
          keyword[keyword_length] != 0)
          ++keyword_length;
 

@@ -1457,11 +1473,11 @@
          {
             read_length -= keyword_length+2;
 
             if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK)
             {
-               Byte profile_header[132];
+               Byte profile_header[132]={0};
                Byte local_buffer[PNG_INFLATE_BUF_SIZE];
                png_alloc_size_t size = (sizeof profile_header);
 
                png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2);
                png_ptr->zstream.avail_in = read_length;

@@ -1487,11 +1503,11 @@
                          png_ptr->color_type) != 0)
                      {
                         /* Now read the tag table; a variable size buffer is
                          * needed at this point, allocate one for the whole
                          * profile.  The header check has already validated
-                         * that none of these stuff will overflow.
+                         * that none of this stuff will overflow.
                          */
                         const png_uint_32 tag_count = png_get_uint_32(
                             profile_header+128);
                         png_bytep profile = png_read_buffer(png_ptr,
                             profile_length, 2/*silent*/);

@@ -1594,23 +1610,15 @@
                                     {
                                        png_ptr->zowner = 0;
                                        return;
                                     }
                                  }
-
-                                 else if (size > 0)
-                                    errmsg = "truncated";
-
-#ifndef __COVERITY__
-                                 else
+                                 if (errmsg == NULL)
                                     errmsg = png_ptr->zstream.msg;
-#endif
                               }
-
                               /* else png_icc_check_tag_table output an error */
                            }
-
                            else /* profile truncated */
                               errmsg = png_ptr->zstream.msg;
                         }
 
                         else

@@ -2035,10 +2043,73 @@
 
    png_set_bKGD(png_ptr, info_ptr, &background);
 }
 #endif
 
+#ifdef PNG_READ_eXIf_SUPPORTED
+void /* PRIVATE */
+png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+{
+   unsigned int i;
+
+   png_debug(1, "in png_handle_eXIf");
+
+   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+      png_chunk_error(png_ptr, "missing IHDR");
+
+   if (length < 2)
+   {
+      png_crc_finish(png_ptr, length);
+      png_chunk_benign_error(png_ptr, "too short");
+      return;
+   }
+
+   else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0)
+   {
+      png_crc_finish(png_ptr, length);
+      png_chunk_benign_error(png_ptr, "duplicate");
+      return;
+   }
+
+   info_ptr->free_me |= PNG_FREE_EXIF;
+
+   info_ptr->eXIf_buf = png_voidcast(png_bytep,
+             png_malloc_warn(png_ptr, length));
+
+   if (info_ptr->eXIf_buf == NULL)
+   {
+      png_crc_finish(png_ptr, length);
+      png_chunk_benign_error(png_ptr, "out of memory");
+      return;
+   }
+
+   for (i = 0; i < length; i++)
+   {
+      png_byte buf[1];
+      png_crc_read(png_ptr, buf, 1);
+      info_ptr->eXIf_buf[i] = buf[0];
+      if (i == 1 && buf[0] != 'M' && buf[0] != 'I'
+                 && info_ptr->eXIf_buf[0] != buf[0])
+      {
+         png_crc_finish(png_ptr, length);
+         png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
+         png_free(png_ptr, info_ptr->eXIf_buf);
+         info_ptr->eXIf_buf = NULL;
+         return;
+      }
+   }
+
+   if (png_crc_finish(png_ptr, 0) != 0)
+      return;
+
+   png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
+
+   png_free(png_ptr, info_ptr->eXIf_buf);
+   info_ptr->eXIf_buf = NULL;
+}
+#endif
+
 #ifdef PNG_READ_hIST_SUPPORTED
 void /* PRIVATE */
 png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    unsigned int num, i;

@@ -2563,10 +2634,13 @@
       png_chunk_error(png_ptr, "missing IHDR");
 
    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
       png_ptr->mode |= PNG_AFTER_IDAT;
 
+   /* Note, "length" is sufficient here; we won't be adding
+    * a null terminator later.
+    */
    buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
 
    if (buffer == NULL)
    {
       png_crc_finish(png_ptr, length);

@@ -2609,13 +2683,17 @@
       if (png_decompress_chunk(png_ptr, length, keyword_length+2,
           &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
       {
          png_text text;
 
-         /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except
-          * for the extra compression type byte and the fact that it isn't
-          * necessarily '\0' terminated.
+         if (png_ptr->read_buffer == NULL)
+           errmsg="Read failure in png_handle_zTXt";
+         else
+         {
+            /* It worked; png_ptr->read_buffer now looks like a tEXt chunk
+             * except for the extra compression type byte and the fact that
+             * it isn't necessarily '\0' terminated.
           */
          buffer = png_ptr->read_buffer;
          buffer[uncompressed_length+(keyword_length+2)] = 0;
 
          text.compression = PNG_TEXT_COMPRESSION_zTXt;

@@ -2627,10 +2705,11 @@
          text.lang_key = NULL;
 
          if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
             errmsg = "insufficient memory";
       }
+      }
 
       else
          errmsg = png_ptr->zstream.msg;
    }
 

@@ -3001,20 +3080,20 @@
       switch (png_ptr->user_chunk_cache_max)
       {
          case 2:
             png_ptr->user_chunk_cache_max = 1;
             png_chunk_benign_error(png_ptr, "no space in chunk cache");
-            /* FALL THROUGH */
+            /* FALLTHROUGH */
          case 1:
             /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
              * chunk being skipped, now there will be a hard error below.
              */
             break;
 
          default: /* not at limit */
             --(png_ptr->user_chunk_cache_max);
-            /* FALL THROUGH */
+            /* FALLTHROUGH */
          case 0: /* no limit */
 #  endif /* USER_LIMITS */
             /* Here when the limit isn't reached or when limits are compiled
              * out; store the chunk.
              */

@@ -3061,24 +3140,62 @@
  *
  * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
  */
 
 void /* PRIVATE */
-png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name)
+png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name)
 {
    int i;
+   png_uint_32 cn=chunk_name;
 
    png_debug(1, "in png_check_chunk_name");
 
    for (i=1; i<=4; ++i)
    {
-      int c = chunk_name & 0xff;
+      int c = cn & 0xff;
 
       if (c < 65 || c > 122 || (c > 90 && c < 97))
          png_chunk_error(png_ptr, "invalid chunk type");
 
-      chunk_name >>= 8;
+      cn >>= 8;
+   }
+}
+
+void /* PRIVATE */
+png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length)
+{
+   png_alloc_size_t limit = PNG_UINT_31_MAX;
+
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+   if (png_ptr->user_chunk_malloc_max > 0 &&
+       png_ptr->user_chunk_malloc_max < limit)
+      limit = png_ptr->user_chunk_malloc_max;
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+      limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+   if (png_ptr->chunk_name == png_IDAT)
+   {
+      png_alloc_size_t idat_limit = PNG_UINT_31_MAX;
+      size_t row_factor =
+         (png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1)
+          + 1 + (png_ptr->interlaced? 6: 0));
+      if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
+         idat_limit=PNG_UINT_31_MAX;
+      else
+         idat_limit = png_ptr->height * row_factor;
+      row_factor = row_factor > 32566? 32566 : row_factor;
+      idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */
+      idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX;
+      limit = limit < idat_limit? idat_limit : limit;
+   }
+
+   if (length > limit)
+   {
+      png_debug2(0," length = %lu, limit = %lu",
+         (unsigned long)length,(unsigned long)limit);
+      png_chunk_error(png_ptr, "chunk data is too large");
    }
 }
 
 /* Combines the row recently read in with the existing pixels in the row.  This
  * routine takes care of alpha and transparency if requested.  This routine also

@@ -3403,11 +3520,11 @@
                /* There is a possibility of a partial copy at the end here; this
                 * slows the code down somewhat.
                 */
                do
                {
-                  dp[0] = sp[0], dp[1] = sp[1];
+                  dp[0] = sp[0]; dp[1] = sp[1];
 
                   if (row_width <= bytes_to_jump)
                      return;
 
                   sp += bytes_to_jump;

@@ -3424,11 +3541,11 @@
                /* This can only be the RGB case, so each copy is exactly one
                 * pixel and it is not necessary to check for a partial copy.
                 */
                for (;;)
                {
-                  dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2];
+                  dp[0] = sp[0]; dp[1] = sp[1]; dp[2] = sp[2];
 
                   if (row_width <= bytes_to_jump)
                      return;
 
                   sp += bytes_to_jump;

@@ -3913,11 +4030,14 @@
 #endif
 
       /* Find the best predictor, the least of pa, pb, pc favoring the earlier
        * ones in the case of a tie.
        */
-      if (pb < pa) pa = pb, a = b;
+      if (pb < pa)
+      {
+         pa = pb; a = b;
+      }
       if (pc < pa) a = c;
 
       /* Calculate the current pixel in a, and move the previous row pixel to c
        * for the next time round the loop
        */

@@ -3965,11 +4085,14 @@
       pa = p < 0 ? -p : p;
       pb = pc < 0 ? -pc : pc;
       pc = (p + pc) < 0 ? -(p + pc) : p + pc;
 #endif
 
-      if (pb < pa) pa = pb, a = b;
+      if (pb < pa)
+      {
+         pa = pb; a = b;
+      }
       if (pc < pa) a = c;
 
       a += *row;
       *row++ = (png_byte)a;
    }
< prev index next >