[libpng17] Update CHANGES and ANNOUNCE about pngcp; sync timepng.c with libpng16
diff --git a/ANNOUNCE b/ANNOUNCE
index be141ed..76d967d 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
 
-Libpng 1.7.0beta80 - May 5, 2016
+Libpng 1.7.0beta80 - May 6, 2016
 
 This is not intended to be a public release.  It will be replaced
 within a few weeks by a public version or by another test version.
@@ -1264,9 +1264,10 @@
     (Robert C. Seacord). Various other flags in png.h made unsigned as well.
   Fixed some misleading indentation (Krishnaraj Bhat).
 
-Version 1.7.0beta80 [May 5, 2016]
+Version 1.7.0beta80 [May 6, 2016]
   Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED
     Bug report by (Y.Ohashik).
+  Quieted two Coverity issues in contrib/libtests/timepng.c.
   Write code update (John Bowler):
     Implemented better defaulting of zlib settings based on image properties.
     Replaced pngtest.png with one compressed with the new zlib settings.
@@ -1283,6 +1284,11 @@
     There are minimal API changes beyond removal of the selection options.
       Work is still to be done to investigate a filter selection mechanism that
       is at least as good as the previous one.
+    Minor write bug-fixes, remove unimplemented code.  A debug() assert
+      fired if windowBits was set to 8 for the Huffman only and no-compression
+      cases. This commit changes it to do some extra checking.  Removed
+      unreachable code in pz_default_settings and eliminated a spurious
+      warning in pngcp for small files.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index 95c5496..3bc6fa2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -5564,9 +5564,10 @@
     (Robert C. Seacord). Various other flags in png.h made unsigned as well.
   Fixed some misleading indentation (Krishnaraj Bhat).
 
-Version 1.7.0beta80 [May 5, 2016]
+Version 1.7.0beta80 [May 6, 2016]
   Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED
     Bug report by (Y.Ohashik).
+  Quieted two Coverity issues in contrib/libtests/timepng.c.
   Write code update (John Bowler):
     Implemented better defaulting of zlib settings based on image properties.
     Replaced pngtest.png with one compressed with the new zlib settings.
@@ -5583,6 +5584,11 @@
     There are minimal API changes beyond removal of the selection options.
       Work is still to be done to investigate a filter selection mechanism that
       is at least as good as the previous one.
+    Minor write bug-fixes, remove unimplemented code.  A debug() assert
+      fired if windowBits was set to 8 for the Huffman only and no-compression
+      cases. This commit changes it to do some extra checking.  Removed
+      unreachable code in pz_default_settings and eliminated a spurious
+      warning in pngcp for small files.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/contrib/examples/pngcp.c b/contrib/examples/pngcp.c
index 3e61c34..e6de44b 100644
--- a/contrib/examples/pngcp.c
+++ b/contrib/examples/pngcp.c
@@ -1199,7 +1199,7 @@
    else if (opt == OPTIND(dp, windowBits))
    {
       /* Changing windowBits for strategies that do not search the window is
-       * pointless.  Huffman-only does not search, RLE only searchs backwards
+       * pointless.  Huffman-only does not search, RLE only searches backwards
        * one byte, so given that the maximum string length is 258, a windowBits
        * of 9 is always sufficient.
        */
diff --git a/contrib/libtests/timepng.c b/contrib/libtests/timepng.c
index 7c93797..4073ab6 100644
--- a/contrib/libtests/timepng.c
+++ b/contrib/libtests/timepng.c
@@ -1,8 +1,8 @@
 /* timepng.c
  *
- * Copyright (c) 2013 John Cunningham Bowler
+ * Copyright (c) 2013,2016 John Cunningham Bowler
  *
- * Last changed in libpng 1.6.1 [March 28, 2013]
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -10,15 +10,17 @@
  *
  * Load an arbitrary number of PNG files (from the command line, or, if there
  * are no arguments on the command line, from stdin) then run a time test by
- * reading each file by row.  The test does nothing with the read result and
- * does no transforms.  The only output is a time as a floating point number of
- * seconds with 9 decimal digits.
+ * reading each file by row or by image (possibly with transforms in the latter
+ * case).  The only output is a time as a floating point number of seconds with
+ * 9 decimal digits.
  */
 #define _POSIX_C_SOURCE 199309L /* for clock_gettime */
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
+#include <limits.h>
 
 #include <time.h>
 
@@ -35,36 +37,61 @@
 #  include "../../png.h"
 #endif
 
-static int read_png(FILE *fp)
+/* The following is to support direct compilation of this file as C++ */
+#ifdef __cplusplus
+#  define voidcast(type, value) static_cast<type>(value)
+#else
+#  define voidcast(type, value) (value)
+#endif /* __cplusplus */
+
+#if ((defined(PNG_SEQUENTIAL_READ_SUPPORTED)) && defined(PNG_STDIO_SUPPORTED)\
+     && defined(PNG_EASY_ACCESS_SUPPORTED) && defined(PNG_INFO_IMAGE_SUPPORTED))
+typedef struct
 {
-   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
-   png_infop info_ptr = NULL;
-   png_bytep row = NULL, display = NULL;
+   FILE *input;
+   FILE *output;
+}  io_data;
 
-   if (png_ptr == NULL)
-      return 0;
+static PNG_CALLBACK(void, read_and_copy,
+      (png_structp png_ptr, png_bytep buffer, png_size_t cb))
+{
+   io_data *io = (io_data*)png_get_io_ptr(png_ptr);
 
-   if (setjmp(png_jmpbuf(png_ptr)))
+   if (fread(buffer, cb, 1, io->input) != 1)
+      png_error(png_ptr, strerror(errno));
+
+   if (fwrite(buffer, cb, 1, io->output) != 1)
    {
-      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-      if (row != NULL) free(row);
-      if (display != NULL) free(display);
-      return 0;
+      perror("temporary file");
+      fprintf(stderr, "temporary file PNG write failed\n");
+      exit(1);
    }
+}
 
-   png_init_io(png_ptr, fp);
+static void read_by_row(png_structp png_ptr, png_infop info_ptr,
+      FILE *write_ptr, FILE *read_ptr)
+{
+   /* These don't get freed on error, this is fine; the program immediately
+    * exits.
+    */
+   png_bytep row = NULL, display = NULL;
+   io_data io_copy;
 
-   info_ptr = png_create_info_struct(png_ptr);
-   if (info_ptr == NULL)
-      png_error(png_ptr, "OOM allocating info structure");
+   if (write_ptr != NULL)
+   {
+      /* Set up for a copy to the temporary file: */
+      io_copy.input = read_ptr;
+      io_copy.output = write_ptr;
+      png_set_read_fn(png_ptr, &io_copy, read_and_copy);
+   }
 
    png_read_info(png_ptr, info_ptr);
 
    {
       png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
 
-      row = malloc(rowbytes);
-      display = malloc(rowbytes);
+      row = voidcast(png_bytep,malloc(rowbytes));
+      display = voidcast(png_bytep,malloc(rowbytes));
 
       if (row == NULL || display == NULL)
          png_error(png_ptr, "OOM allocating row buffers");
@@ -81,7 +108,8 @@
             png_uint_32 y = height;
 
             /* NOTE: this trashes the row each time; interlace handling won't
-             * work, but this avoids memory thrashing for speed testing.
+             * work, but this avoids memory thrashing for speed testing and is
+             * somewhat representative of an application that works row-by-row.
              */
             while (y-- > 0)
                png_read_row(png_ptr, row, display);
@@ -91,9 +119,51 @@
 
    /* Make sure to read to the end of the file: */
    png_read_end(png_ptr, info_ptr);
-   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+   /* Free this up: */
    free(row);
    free(display);
+}
+
+static PNG_CALLBACK(void, no_warnings, (png_structp png_ptr,
+         png_const_charp warning))
+{
+   (void)png_ptr;
+   (void)warning;
+}
+
+static int read_png(FILE *fp, png_int_32 transforms, FILE *write_file)
+{
+   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,
+         no_warnings);
+   png_infop info_ptr = NULL;
+
+   if (png_ptr == NULL)
+      return 0;
+
+   if (setjmp(png_jmpbuf(png_ptr)))
+   {
+      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+      return 0;
+   }
+
+#  ifdef PNG_BENIGN_ERRORS_SUPPORTED
+      png_set_benign_errors(png_ptr, 1/*allowed*/);
+#  endif
+   png_init_io(png_ptr, fp);
+
+   info_ptr = png_create_info_struct(png_ptr);
+
+   if (info_ptr == NULL)
+      png_error(png_ptr, "OOM allocating info structure");
+
+   if (transforms < 0)
+      read_by_row(png_ptr, info_ptr, write_file, fp);
+
+   else
+      png_read_png(png_ptr, info_ptr, transforms, NULL/*params*/);
+
+   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    return 1;
 }
 
@@ -108,7 +178,7 @@
    return 0;
 }
 
-static int perform_one_test(FILE *fp, int nfiles)
+static int perform_one_test(FILE *fp, int nfiles, png_int_32 transforms)
 {
    int i;
    struct timespec before, after;
@@ -120,7 +190,7 @@
    {
       for (i=0; i<nfiles; ++i)
       {
-         if (read_png(fp))
+         if (read_png(fp, transforms, NULL/*write*/))
          {
             if (ferror(fp))
             {
@@ -184,120 +254,343 @@
 
    if (ip != NULL)
    {
-      int ch;
-      for (;;)
+      /* Read the file using libpng; this detects errors and also deals with
+       * files which contain data beyond the end of the file.
+       */
+      int ok = 0;
+      fpos_t pos;
+
+      if (fgetpos(fp, &pos))
       {
-         ch = getc(ip);
-         if (ch == EOF) break;
-         putc(ch, fp);
+         /* Fatal error reading the start: */
+         perror("temporary file");
+         fprintf(stderr, "temporary file fgetpos error\n");
+         exit(1);
       }
 
-      if (ferror(ip))
+      if (read_png(ip, -1/*by row*/, fp/*output*/))
       {
-         perror(name);
-         fprintf(stderr, "%s: read error\n", name);
-         return 0;
+         if (ferror(ip))
+         {
+            perror(name);
+            fprintf(stderr, "%s: read error\n", name);
+         }
+
+         else
+            ok = 1; /* read ok */
       }
 
+      else
+         fprintf(stderr, "%s: file not added\n", name);
+
       (void)fclose(ip);
 
+      /* An error in the output is fatal; exit immediately: */
       if (ferror(fp))
       {
          perror("temporary file");
          fprintf(stderr, "temporary file write error\n");
-         return 0;
+         exit(1);
+      }
+
+      if (ok)
+         return 1;
+
+      /* Did not read the file successfully, simply rewind the temporary
+       * file.  This must happen after the ferror check above to avoid clearing
+       * the error.
+       */
+      if (fsetpos(fp, &pos))
+      {
+         perror("temporary file");
+         fprintf(stderr, "temporary file fsetpos error\n");
+         exit(1);
       }
    }
 
    else
    {
+      /* file open error: */
       perror(name);
       fprintf(stderr, "%s: open failed\n", name);
-      return 0;
    }
 
-   return 1;
+   return 0; /* file not added */
+}
+
+static void
+usage(FILE *fp)
+{
+   if (fp != NULL) fclose(fp);
+
+   fprintf(stderr,
+"Usage:\n"
+" timepng --assemble <assembly> {files}\n"
+"  Read the files into <assembly>, output the count.  Options are ignored.\n"
+" timepng --dissemble <assembly> <count> [options]\n"
+"  Time <count> files from <assembly>, additional files may not be given.\n"
+" Otherwise:\n"
+"  Read the files into a temporary file and time the decode\n"
+"Transforms:\n"
+"  --by-image: read by image with png_read_png\n"
+"  --<transform>: implies by-image, use PNG_TRANSFORM_<transform>\n"
+"  Otherwise: read by row using png_read_row (to a single row buffer)\n"
+   /* ISO C90 string length max 509 */);fprintf(stderr,
+"{files}:\n"
+"  PNG files to copy into the assembly and time.  Invalid files are skipped\n"
+"  with appropriate error messages.  If no files are given the list of files\n"
+"  is read from stdin with each file name terminated by a newline\n"
+"Output:\n"
+"  For --assemble the output is the name of the assembly file followed by the\n"
+"  count of the files it contains; the arguments for --dissemble.  Otherwise\n"
+"  the output is the total decode time in seconds.\n");
+
+   exit(99);
 }
 
 int main(int argc, char **argv)
 {
    int ok = 0;
-   FILE *fp = tmpfile();
+   int err = 0;
+   int nfiles = 0;
+   int transforms = -1; /* by row */
+   const char *assembly = NULL;
+   FILE *fp;
 
-   if (fp != NULL)
+   if (argc > 2 && strcmp(argv[1], "--assemble") == 0)
    {
-      int err = 0;
-      int nfiles = 0;
-
-      if (argc > 1)
+      /* Just build the test file, argv[2] is the file name. */
+      assembly = argv[2];
+      fp = fopen(assembly, "wb");
+      if (fp == NULL)
       {
-         int i;
+         perror(assembly);
+         fprintf(stderr, "timepng --assemble %s: could not open for write\n",
+               assembly);
+         usage(NULL);
+      }
 
-         for (i=1; i<argc; ++i)
+      argv += 2;
+      argc -= 2;
+   }
+
+   else if (argc > 3 && strcmp(argv[1], "--dissemble") == 0)
+   {
+      fp = fopen(argv[2], "rb");
+
+      if (fp == NULL)
+      {
+         perror(argv[2]);
+         fprintf(stderr, "timepng --dissemble %s: could not open for read\n",
+               argv[2]);
+         usage(NULL);
+      }
+
+      nfiles = atoi(argv[3]);
+      if (nfiles <= 0)
+      {
+         fprintf(stderr,
+               "timepng --dissemble <file> <count>: %s is not a count\n",
+               argv[3]);
+         exit(99);
+      }
+#ifdef __COVERITY__
+      else
+      {
+         nfiles &= PNG_UINT_31_MAX;
+      }
+#endif
+
+      argv += 3;
+      argc -= 3;
+   }
+
+   else /* Else use a temporary file */
+   {
+#ifndef __COVERITY__
+      fp = tmpfile();
+#else
+      /* Experimental. Coverity says tmpfile() is insecure because it
+       * generates predictable names.
+       *
+       * It is possible to satisfy Coverity by using mkstemp(); however,
+       * any platform supporting mkstemp() undoubtedly has a secure tmpfile()
+       * implementation as well, and doesn't need the fix.  Note that
+       * the fix won't work on platforms that don't support mkstemp().
+       *
+       * https://www.securecoding.cert.org/confluence/display/c/
+       * FIO21-C.+Do+not+create+temporary+files+in+shared+directories
+       * says that most historic implementations of tmpfile() provide
+       * only a limited number of possible temporary file names
+       * (usually 26) before file names are recycled. That article also
+       * provides a secure solution that unfortunately depends upon mkstemp().
+       */
+      char tmpfile[] = "timepng-XXXXXX";
+      int filedes;
+      umask(0177);
+      filedes = mkstemp(tmpfile);
+      if (filedes < 0)
+        fp = NULL;
+      else
+      {
+        fp = fdopen(filedes,"w+");
+        /* Hide the filename immediately and ensure that the file does
+         * not exist after the program ends
+         */
+        (void) unlink(tmpfile);
+      }
+#endif
+
+      if (fp == NULL)
+      {
+         perror("tmpfile");
+         fprintf(stderr, "timepng: could not open the temporary file\n");
+         exit(1); /* not a user error */
+      }
+   }
+
+   /* Handle the transforms: */
+   while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
+   {
+      const char *opt = *++argv + 2;
+
+      --argc;
+
+      /* Transforms turn on the by-image processing and maybe set some
+       * transforms:
+       */
+      if (transforms == -1)
+         transforms = PNG_TRANSFORM_IDENTITY;
+
+      if (strcmp(opt, "by-image") == 0)
+      {
+         /* handled above */
+      }
+
+#        define OPT(name) else if (strcmp(opt, #name) == 0)\
+         transforms |= PNG_TRANSFORM_ ## name
+
+      OPT(STRIP_16);
+      OPT(STRIP_ALPHA);
+      OPT(PACKING);
+      OPT(PACKSWAP);
+      OPT(EXPAND);
+      OPT(INVERT_MONO);
+      OPT(SHIFT);
+      OPT(BGR);
+      OPT(SWAP_ALPHA);
+      OPT(SWAP_ENDIAN);
+      OPT(INVERT_ALPHA);
+      OPT(STRIP_FILLER);
+      OPT(STRIP_FILLER_BEFORE);
+      OPT(STRIP_FILLER_AFTER);
+      OPT(GRAY_TO_RGB);
+      OPT(EXPAND_16);
+      OPT(SCALE_16);
+
+      else
+      {
+         fprintf(stderr, "timepng %s: unrecognized transform\n", opt);
+         usage(fp);
+      }
+   }
+
+   /* Handle the files: */
+   if (argc > 1 && nfiles > 0)
+      usage(fp); /* Additional files not valid with --dissemble */
+
+   else if (argc > 1)
+   {
+      int i;
+
+      for (i=1; i<argc; ++i)
+      {
+         if (nfiles == INT_MAX)
          {
-            if (add_one_file(fp, argv[i]))
+            fprintf(stderr, "%s: skipped, too many files\n", argv[i]);
+            break;
+         }
+
+         else if (add_one_file(fp, argv[i]))
+            ++nfiles;
+      }
+   }
+
+   else if (nfiles == 0) /* Read from stdin withoout --dissemble */
+   {
+      char filename[FILENAME_MAX+1];
+
+      while (fgets(filename, FILENAME_MAX+1, stdin))
+      {
+         size_t len = strlen(filename);
+
+         if (filename[len-1] == '\n')
+         {
+            filename[len-1] = 0;
+            if (nfiles == INT_MAX)
+            {
+               fprintf(stderr, "%s: skipped, too many files\n", filename);
+               break;
+            }
+
+            else if (add_one_file(fp, filename))
                ++nfiles;
+         }
+
+         else
+         {
+            fprintf(stderr, "timepng: file name too long: ...%s\n",
+               filename+len-32);
+            err = 1;
+            break;
+         }
+      }
+
+      if (ferror(stdin))
+      {
+         fprintf(stderr, "timepng: stdin: read error\n");
+         err = 1;
+      }
+   }
+
+   /* Perform the test, or produce the --assemble output: */
+   if (!err)
+   {
+      if (nfiles > 0)
+      {
+         if (assembly != NULL)
+         {
+            if (fflush(fp) && !ferror(fp) && fclose(fp))
+            {
+               perror(assembly);
+               fprintf(stderr, "%s: close failed\n", assembly);
+            }
 
             else
             {
-               err = 1;
-               break;
+               printf("%s %d\n", assembly, nfiles);
+               fflush(stdout);
+               ok = !ferror(stdout);
             }
          }
+
+         else
+         {
+            ok = perform_one_test(fp, nfiles, transforms);
+            (void)fclose(fp);
+         }
       }
 
       else
-      {
-         char filename[FILENAME_MAX+1];
-
-         while (fgets(filename, FILENAME_MAX+1, stdin))
-         {
-            size_t len = strlen(filename);
-
-            if (filename[len-1] == '\n')
-            {
-               filename[len-1] = 0;
-               if (add_one_file(fp, filename))
-                  ++nfiles;
-
-               else
-               {
-                  err = 1;
-                  break;
-               }
-            }
-
-            else
-            {
-               fprintf(stderr, "timepng: truncated file name ...%s\n",
-                  filename+len-32);
-               err = 1;
-               break;
-            }
-         }
-
-         if (ferror(stdin))
-         {
-            fprintf(stderr, "timepng: stdin: read error\n");
-            err = 1;
-         }
-      }
-
-      if (!err)
-      {
-         if (nfiles > 0)
-            ok = perform_one_test(fp, nfiles);
-
-         else
-            fprintf(stderr, "usage: timepng {files} or ls files | timepng\n");
-      }
-
-      (void)fclose(fp);
+         usage(fp);
    }
 
    else
-      fprintf(stderr, "timepng: could not open temporary file\n");
+      (void)fclose(fp);
 
    /* Exit code 0 on success. */
    return ok == 0;
 }
+#else /* !sufficient support */
+int main(void) { return 77; }
+#endif /* !sufficient support */
diff --git a/png.h b/png.h
index 9bce970..7930e18 100644
--- a/png.h
+++ b/png.h
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.7.0beta80, May 5, 2016
+ * libpng version 1.7.0beta80, May 6, 2016
  *
  * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -12,7 +12,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.7.0beta80, May 5, 2016:
+ *   libpng versions 0.97, January 1998, through 1.7.0beta80, May 6, 2016:
  *     Glenn Randers-Pehrson.
  *   See also "Contributing Authors", below.
  */
@@ -25,7 +25,7 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.0.7, July 1, 2000, through 1.7.0beta80, May 5, 2016, are
+ * libpng versions 1.0.7, July 1, 2000, through 1.7.0beta80, May 6, 2016, are
  * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
  * derived from libpng-1.0.6, and are distributed according to the same
  * disclaimer and license as libpng-1.0.6 with the following individuals
@@ -218,7 +218,7 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    May 5, 2016
+ *    May 6, 2016
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
@@ -288,7 +288,7 @@
 /* Version information for png.h - this should match the version in png.c */
 #define PNG_LIBPNG_VER_STRING "1.7.0beta80"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.7.0beta80 - May 5, 2016\n"
+     " libpng version 1.7.0beta80 - May 6, 2016\n"
 
 #define PNG_LIBPNG_VER_SONUM   17
 #define PNG_LIBPNG_VER_DLLNUM  17