[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