From 84dc47910824fccde97529baf0880bbfd9407d43 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Sun, 6 Jan 2013 12:38:39 -0600 Subject: [PATCH] [libpng15] De-configured build fixes to make a range of deconfiguration options (such as switching off read or write support) work in more cases. Also upgraded pngtest and pngvalid to the libpng 1.6 versions (with some modifications) which provide more extensive testing. Replaced pngtest.png because pngtest writes the ancillary chunks in a different order. --- ANNOUNCE | 9 +- CHANGES | 7 +- png.c | 13 +- pngget.c | 6 + pngpriv.h | 66 ++++- pngrtran.c | 4 +- pngtest.c | 817 ++++++++++++++++++++++++++++++---------------------- pngtest.png | Bin 8695 -> 8695 bytes 8 files changed, 565 insertions(+), 357 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 8a708e8e5..eb39c647e 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.5.14beta07 - January 3, 2013 +Libpng 1.5.14beta07 - January 6, 2013 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. @@ -64,9 +64,14 @@ Version 1.5.14beta06 [January 1, 2013] Discontinued distributing libpng-1.5.14-1.5.13-diff.txt and similar. Fixed 'make distcheck' on SUN OS - libpng.so was not being removed -Version 1.5.14beta07 [January 3, 2013] +Version 1.5.14beta07 [January 6, 2013] Replaced AM_CONFIG_HEADER(config.h) with AC_CONFIG_HEADERS([config.h]) in configure.ac + De-configured build fixes to make a range of deconfiguration options (such + as switching off read or write support) work in more cases. Also upgraded + pngtest and pngvalid to the libpng 1.6 versions (with some modifications) + which provide more extensive testing. Replaced pngtest.png because pngtest + writes the ancillary chunks in a different order. =========================================================================== NOTICE November 17, 2012: diff --git a/CHANGES b/CHANGES index a061b49b2..c53bf6ca6 100644 --- a/CHANGES +++ b/CHANGES @@ -3957,9 +3957,14 @@ Version 1.5.14beta06 [January 1, 2013] Discontinued distributing libpng-1.5.14-1.5.13-diff.txt and similar. Fixed 'make distcheck' on SUN OS - libpng.so was not being removed -Version 1.5.14beta07 [January 3, 2013] +Version 1.5.14beta07 [January 6, 2013] Replaced AM_CONFIG_HEADER(config.h) with AC_CONFIG_HEADERS([config.h]) in configure.ac + De-configured build fixes to make a range of deconfiguration options (such + as switching off read or write support) work in more cases. Also upgraded + pngtest and pngvalid to the libpng 1.6 versions (with some modifications) + which provide more extensive testing. Replaced pngtest.png because pngtest + writes the ancillary chunks in a different order. =========================================================================== NOTICE November 17, 2012: diff --git a/png.c b/png.c index bf370221f..6ff3546b8 100644 --- a/png.c +++ b/png.c @@ -658,13 +658,13 @@ png_get_copyright(png_const_structp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.5.14beta07 - January 1, 2013" PNG_STRING_NEWLINE \ + "libpng version 1.5.14beta07 - January 6, 2013" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.5.14beta07 - January 1, 2013\ + return "libpng version 1.5.14beta07 - January 6, 2013\ Copyright (c) 1998-2013 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -1461,7 +1461,7 @@ png_check_fp_string(png_const_charp string, png_size_t size) } #endif /* pCAL or sCAL */ -#ifdef PNG_READ_sCAL_SUPPORTED +#ifdef PNG_sCAL_SUPPORTED # ifdef PNG_FLOATING_POINT_SUPPORTED /* Utility used below - a simple accurate power of ten from an integral * exponent. @@ -2047,7 +2047,8 @@ png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times, } #endif -#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gamma */ +#if (defined PNG_READ_GAMMA_SUPPORTED) || (defined PNG_cHRM_SUPPORTED) +/* more fixed point functions for gamma and cHRM (xy/XYZ) suport. */ /* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ png_fixed_point png_reciprocal(png_fixed_point a) @@ -2067,6 +2068,7 @@ png_reciprocal(png_fixed_point a) return 0; /* error/overflow */ } +#ifdef PNG_READ_GAMMA_SUPPORTED /* A local convenience routine. */ static png_fixed_point png_product2(png_fixed_point a, png_fixed_point b) @@ -2088,6 +2090,7 @@ png_product2(png_fixed_point a, png_fixed_point b) return 0; /* overflow */ } +#endif /* READ_GAMMA */ /* The inverse of the above. */ png_fixed_point @@ -2115,7 +2118,7 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b) return 0; /* overflow */ } -#endif /* READ_GAMMA */ +#endif /* READ_GAMMA || cHRM */ #ifdef PNG_CHECK_cHRM_SUPPORTED /* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2, diff --git a/pngget.c b/pngget.c index 43400cda7..7d4708fa3 100644 --- a/pngget.c +++ b/pngget.c @@ -175,6 +175,9 @@ png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr) return ((float)((float)info_ptr->y_pixels_per_unit /(float)info_ptr->x_pixels_per_unit)); } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) #endif return ((float)0.0); @@ -203,6 +206,9 @@ png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr, (png_int_32)info_ptr->x_pixels_per_unit)) return res; } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) #endif return 0; diff --git a/pngpriv.h b/pngpriv.h index 163a1acb4..b961bd3b2 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -416,7 +416,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE /* This is used because in some compiler implementations non-aligned * structure members are supported, so the offsetof approach below fails. - * Set PNG_ALIGN_TO_SIZE=0 for compiler combinations where unaligned access + * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access * is good for performance. Do not do this unless you have tested the result * and understand it. */ @@ -823,10 +823,8 @@ PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); # ifdef PNG_FLOATING_POINT_SUPPORTED PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); # endif -# ifdef PNG_FIXED_POINT_SUPPORTED PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point file_gamma)); -# endif #endif #ifdef PNG_WRITE_sBIT_SUPPORTED @@ -1491,14 +1489,16 @@ PNG_EXTERN void png_formatted_warning(png_structp png_ptr, /* ASCII to FP interfaces, currently only implemented if sCAL * support is required. */ -#if defined(PNG_READ_sCAL_SUPPORTED) +#ifdef PNG_sCAL_SUPPORTED /* MAX_DIGITS is actually the maximum number of characters in an sCAL * width or height, derived from the precision (number of significant * digits - a build time settable option) and assumpitions about the * maximum ridiculous exponent. */ #define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) +#endif +#ifdef PNG_sCAL_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii, png_size_t size, double fp, unsigned int precision)); @@ -1629,7 +1629,7 @@ PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr, png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by)); #endif -#ifdef PNG_READ_GAMMA_SUPPORTED +#if (defined PNG_READ_GAMMA_SUPPORTED) || (defined PNG_cHRM_SUPPORTED) /* Calculate a reciprocal - used for gamma values. This returns * 0 if the argument is 0 in order to maintain an undefined value, * there are no warnings. @@ -1664,6 +1664,62 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, int bit_depth)); #endif +/* Missing declarations if FIXED_POINT is *not* supported - fixed properly + * in libpng 1.6 + */ +#ifndef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED +PNG_EXTERN png_uint_32 png_get_cHRM_XYZ_fixed PNGARG( + (png_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)); +PNG_EXTERN void png_set_cHRM_XYZ_fixed PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)); +PNG_EXTERN void png_set_cHRM_fixed PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_EXTERN png_uint_32 png_get_gAMA_fixed PNGARG( + (png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_file_gamma)); +PNG_EXTERN void png_set_gAMA_fixed PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +PNG_EXTERN void png_set_background_fixed PNGARG((png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +PNG_EXTERN void png_set_alpha_mode_fixed PNGARG((png_structp png_ptr, + int mode, png_fixed_point output_gamma)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_set_gamma_fixed PNGARG((png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN void png_set_rgb_to_gray_fixed PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)); +#endif +#endif /* FIX MISSING !FIXED_POINT DECLARATIONS */ + #ifdef PNG_FILTER_OPTIMIZATIONS PNG_EXTERN void PNG_FILTER_OPTIMIZATIONS(png_structp png_ptr, unsigned int bpp); /* This is the initialization function for hardware specific optimizations, diff --git a/pngrtran.c b/pngrtran.c index 21dd04590..a5892d6c9 100644 --- a/pngrtran.c +++ b/pngrtran.c @@ -4746,7 +4746,9 @@ png_do_expand(png_row_infop row_info, png_bytep row, { if (row_info->bit_depth == 8) { - gray = gray & 0xff; + /* NOTE: prior to libpng 1.5.14 this cleared out the top bits of + * 'gray', however if those are set it is an error. + */ sp = row + (png_size_t)row_width - 1; dp = row + (png_size_t)(row_width << 1) - 1; diff --git a/pngtest.c b/pngtest.c index ba18a9a60..9dc88ebd8 100644 --- a/pngtest.c +++ b/pngtest.c @@ -1,8 +1,8 @@ /* pngtest.c - a simple test program to test libpng * - * Last changed in libpng 1.5.6 [November 3, 2011] - * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * Last changed in libpng 1.5.14 [(PENDING RELEASE)] + * Copyright (c) 1998-2013 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.) * @@ -33,16 +33,23 @@ #define _POSIX_SOURCE 1 -#include "zlib.h" +#include +#include +#include + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + #include "png.h" + +#ifdef PNG_READ_SUPPORTED /* else nothing can be done */ +#include "zlib.h" /* Copied from pngpriv.h but only used in error messages below. */ #ifndef PNG_ZBUF_SIZE # define PNG_ZBUF_SIZE 8192 #endif -# include -# include -# include -# define FCLOSE(file) fclose(file) +#define FCLOSE(file) fclose(file) #ifndef PNG_STDIO_SUPPORTED typedef FILE * png_FILE_p; @@ -67,17 +74,6 @@ typedef FILE * png_FILE_p; # define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ #endif -/* The code uses memcmp and memcpy on large objects (typically row pointers) so - * it is necessary to do soemthing special on certain architectures, note that - * the actual support for this was effectively removed in 1.4, so only the - * memory remains in this program: - */ -#define CVT_PTR(ptr) (ptr) -#define CVT_PTR_NOCHECK(ptr) (ptr) -#define png_memcmp memcmp -#define png_memcpy memcpy -#define png_memset memset - /* Turn on CPU timing #define PNGTEST_TIMING */ @@ -99,30 +95,37 @@ static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; static int verbose = 0; static int strict = 0; - -int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); +static int relaxed = 0; +static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ +static int error_count = 0; /* count calls to png_error */ +static int warning_count = 0; /* count calls to png_warning */ #ifdef __TURBOC__ #include #endif -/* Defined so I can write to a file on gui/windowing platforms */ -/* #define STDERR stderr */ -#define STDERR stdout /* For DOS */ - /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ #ifndef png_jmpbuf # define png_jmpbuf(png_ptr) png_ptr->jmpbuf #endif +/* Defines for unknown chunk handling if required. */ +#ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +#endif +#ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +#endif + +/* Utility to save typing/errors, the argument must be a name */ +#define MEMZERO(var) ((void)memset(&var, 0, sizeof var)) + /* Example of using row callbacks to make a simple progress meter */ static int status_pass = 1; static int status_dots_requested = 0; static int status_dots = 1; -void PNGCBAPI -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void PNGCBAPI +static void PNGCBAPI read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) { if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) @@ -146,9 +149,8 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) fprintf(stdout, "r"); } -void PNGCBAPI -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void PNGCBAPI +#ifdef PNG_WRITE_SUPPORTED +static void PNGCBAPI write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) { if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) @@ -156,6 +158,7 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) fprintf(stdout, "w"); } +#endif #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED @@ -164,9 +167,7 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) * 5 in case illegal filter values are present.) */ static png_uint_32 filters_used[256]; -void PNGCBAPI -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void PNGCBAPI +static void PNGCBAPI count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) { if (png_ptr != NULL && row_info != NULL) @@ -181,9 +182,7 @@ count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) static png_uint_32 zero_samples; -void PNGCBAPI -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void PNGCBAPI +static void PNGCBAPI count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) { png_bytep dp = data; @@ -290,8 +289,6 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) } #endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ -static int wrote_question = 0; - #ifndef PNG_STDIO_SUPPORTED /* START of code to validate stdio-free compilation */ /* These copies of the default read/write functions come from pngrio.c and @@ -344,7 +341,6 @@ pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, } #endif -#ifndef USE_FAR_KEYWORD static void PNGCBAPI pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { @@ -369,59 +365,6 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) pngtest_check_io_state(png_ptr, length, PNG_IO_READING); #endif } -#else -/* This is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void PNGCBAPI -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - png_byte *n_data; - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - n_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); - if ((png_bytep)n_data == data) - { - check = fread(n_data, 1, length, io_ptr); - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - - do - { - read = MIN(NEAR_BUF_SIZE, remaining); - err = fread(buf, 1, 1, io_ptr); - png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ - if (err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); - } - - if (check != length) - png_error(png_ptr, "Read Error"); - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_READING); -#endif -} -#endif /* USE_FAR_KEYWORD */ #ifdef PNG_WRITE_FLUSH_SUPPORTED static void PNGCBAPI @@ -437,7 +380,6 @@ pngtest_flush(png_structp png_ptr) * write_data function and use it at run time with png_set_write_fn(), rather * than changing the library. */ -#ifndef USE_FAR_KEYWORD static void PNGCBAPI pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { @@ -454,81 +396,31 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); #endif } -#else -/* This is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void PNGCBAPI -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - near_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); - - if ((png_bytep)near_data == data) - { - check = fwrite(near_data, 1, length, io_ptr); - } - - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t written, remaining, err; - check = 0; - remaining = length; - - do - { - written = MIN(NEAR_BUF_SIZE, remaining); - png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ - err = fwrite(buf, 1, written, io_ptr); - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); - } - - if (check != length) - { - png_error(png_ptr, "Write Error"); - } - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); -#endif -} -#endif /* USE_FAR_KEYWORD */ +#endif /* !PNG_STDIO_SUPPORTED */ /* This function is called when there is a warning, but the library thinks * it can continue anyway. Replacement functions don't have to do anything * here if you don't want to. In the default configuration, png_ptr is * not used, but it is passed in case it may be useful. */ +typedef struct +{ + PNG_CONST char *file_name; +} pngtest_error_parameters; + static void PNGCBAPI pngtest_warning(png_structp png_ptr, png_const_charp message) { PNG_CONST char *name = "UNKNOWN (ERROR!)"; - char *test; - test = png_get_error_ptr(png_ptr); + pngtest_error_parameters *test = + (pngtest_error_parameters*)png_get_error_ptr(png_ptr); - if (test == NULL) - fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + ++warning_count; - else - fprintf(STDERR, "%s: libpng warning: %s\n", test, message); + if (test != NULL && test->file_name != NULL) + name = test->file_name; + + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); } /* This is the default error handling function. Note that replacements for @@ -539,12 +431,14 @@ pngtest_warning(png_structp png_ptr, png_const_charp message) static void PNGCBAPI pngtest_error(png_structp png_ptr, png_const_charp message) { + ++error_count; + pngtest_warning(png_ptr, message); /* We can return because png_error calls the default handler, which is * actually OK in this case. */ } -#endif /* !PNG_STDIO_SUPPORTED */ + /* END of code to validate stdio-free compilation */ /* START of code to validate memory allocation and deallocation */ @@ -563,9 +457,9 @@ typedef struct memory_information { png_alloc_size_t size; png_voidp pointer; - struct memory_information FAR *next; + struct memory_information *next; } memory_information; -typedef memory_information FAR *memory_infop; +typedef memory_information *memory_infop; static memory_infop pinformation = NULL; static int current_allocation = 0; @@ -595,7 +489,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) memory_infop pinfo; png_set_mem_fn(png_ptr, NULL, NULL, NULL); pinfo = (memory_infop)png_malloc(png_ptr, - png_sizeof(*pinfo)); + (sizeof *pinfo)); pinfo->size = size; current_allocation += size; total_allocation += size; @@ -621,7 +515,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) pinfo->next = pinformation; pinformation = pinfo; /* Make sure the caller isn't assuming zeroed memory. */ - png_memset(pinfo->pointer, 0xdd, pinfo->size); + memset(pinfo->pointer, 0xdd, pinfo->size); if (verbose) printf("png_malloc %lu bytes at %p\n", (unsigned long)size, @@ -648,7 +542,7 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) /* Unlink the element from the list. */ { - memory_infop FAR *ppinfo = &pinformation; + memory_infop *ppinfo = &pinformation; for (;;) { @@ -662,7 +556,7 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) fprintf(STDERR, "Duplicate free of memory\n"); /* We must free the list element too, but first kill the memory that is to be freed. */ - png_memset(ptr, 0x55, pinfo->size); + memset(ptr, 0x55, pinfo->size); png_free_default(png_ptr, pinfo); pinfo = NULL; break; @@ -689,25 +583,73 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) /* END of code to test memory allocation/deallocation */ +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED /* Demonstration of user chunk support of the sTER and vpAg chunks */ -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED /* (sTER is a public chunk not yet known by libpng. vpAg is a private chunk used in ImageMagick to store "virtual page" size). */ -static png_uint_32 user_chunk_data[4]; +static struct user_chunk_data +{ + png_const_infop info_ptr; + png_uint_32 vpAg_width, vpAg_height; + png_byte vpAg_units; + png_byte sTER_mode; + int location[2]; +} +user_chunk_data; - /* 0: sTER mode + 1 - * 1: vpAg width - * 2: vpAg height - * 3: vpAg units - */ +/* Used for location and order; zero means nothing. */ +#define have_sTER 0x01 +#define have_vpAg 0x02 +#define before_PLTE 0x10 +#define before_IDAT 0x20 +#define after_IDAT 0x40 + +static void +init_callback_info(png_const_infop info_ptr) +{ + MEMZERO(user_chunk_data); + user_chunk_data.info_ptr = info_ptr; +} + +static int +set_location(png_structp png_ptr, struct user_chunk_data *data, int what) +{ + int location; + + if ((data->location[0] & what) || (data->location[1] & what)) + return 0; /* already have one of these */ + + /* Find where we are (the code below zeros info_ptr to indicate that the + * chunks before the first IDAT have been read.) + */ + if (data->info_ptr == NULL) /* after IDAT */ + location = what | after_IDAT; + + else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE)) + location = what | before_IDAT; + + else + location = what | before_PLTE; + + if (data->location[0] == 0) + data->location[0] = location; + + else + data->location[1] = location; + + return 1; /* handled */ +} static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk) { - png_uint_32 - *my_user_chunk_data; + struct user_chunk_data *my_user_chunk_data = + (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr); + + if (my_user_chunk_data == NULL) + png_error(png_ptr, "lost user chunk pointer"); /* Return one of the following: * return (-n); chunk had an error @@ -732,9 +674,14 @@ static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, if (chunk->data[0] != 0 && chunk->data[0] != 1) return (-1); /* Invalid mode */ - my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); - my_user_chunk_data[0]=chunk->data[0]+1; - return (1); + if (set_location(png_ptr, my_user_chunk_data, have_sTER)) + { + my_user_chunk_data->sTER_mode=chunk->data[0]; + return (1); + } + + else + return (0); /* duplicate sTER - give it to libpng */ } if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ @@ -746,24 +693,119 @@ static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, if (chunk->size != 9) return (-1); /* Error return */ - my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + if (!set_location(png_ptr, my_user_chunk_data, have_vpAg)) + return (0); /* duplicate vpAg */ - my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); - my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); - my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; + my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data->vpAg_units = chunk->data[8]; return (1); - } + +#ifdef PNG_WRITE_SUPPORTED +static void +write_sTER_chunk(png_structp write_ptr) +{ + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode); + + png_write_chunk(write_ptr, png_sTER, &user_chunk_data.sTER_mode, 1); +} + +static void +write_vpAg_chunk(png_structp write_ptr) +{ + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + png_byte vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n", + (unsigned long)user_chunk_data.vpAg_width, + (unsigned long)user_chunk_data.vpAg_height, + user_chunk_data.vpAg_units); + + png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height); + vpag_chunk_data[8] = user_chunk_data.vpAg_units; + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); +} + +static void +write_chunks(png_structp write_ptr, int location) +{ + int i; + + /* Notice that this preserves the original chunk order, however chunks + * intercepted by the callback will be written *after* chunks passed to + * libpng. This will actually reverse a pair of sTER chunks or a pair of + * vpAg chunks, resulting in an error later. This is not worth worrying + * about - the chunks should not be duplicated! + */ + for (i=0; i<2; ++i) + { + if (user_chunk_data.location[i] == (location | have_sTER)) + write_sTER_chunk(write_ptr); + + else if (user_chunk_data.location[i] == (location | have_vpAg)) + write_vpAg_chunk(write_ptr); + } +} +#endif /* PNG_WRITE_SUPPORTED */ +#else /* !PNG_READ_USER_CHUNKS_SUPPORTED */ +# define write_chunks(pp,loc) ((void)0) #endif /* END of code to demonstrate user chunk support */ +/* START of code to check that libpng has the required text support; this only + * checks for the write support because if read support is missing the chunk + * will simply not be reported back to pngtest. + */ +#ifdef PNG_TEXT_SUPPORTED +static void +pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr, + int num_text) +{ + while (num_text > 0) + { + switch (text_ptr[--num_text].compression) + { + case PNG_TEXT_COMPRESSION_NONE: + break; + + case PNG_TEXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_zTXt_SUPPORTED + ++unsupported_chunks; +# endif + break; + + case PNG_ITXT_COMPRESSION_NONE: + case PNG_ITXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_iTXt_SUPPORTED + ++unsupported_chunks; +# endif + break; + + default: + /* This is an error */ + png_error(png_ptr, "invalid text chunk compression field"); + break; + } + } +} +#endif +/* END of code to check that libpng has the required text support */ + /* Test one file */ -int +static int test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { static png_FILE_p fpin; static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + pngtest_error_parameters error_parameters; png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; #ifdef PNG_WRITE_SUPPORTED @@ -780,15 +822,9 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf tmp_jmpbuf; -#endif -#endif - - char inbuf[256], outbuf[256]; row_buf = NULL; + error_parameters.file_name = inname; if ((fpin = fopen(inname, "rb")) == NULL) { @@ -812,20 +848,9 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif -#ifndef PNG_STDIO_SUPPORTED - png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#endif + png_set_error_fn(read_ptr, &error_parameters, pngtest_error, + pngtest_warning); -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED - user_chunk_data[0] = 0; - user_chunk_data[1] = 0; - user_chunk_data[2] = 0; - user_chunk_data[3] = 0; - png_set_read_user_chunk_fn(read_ptr, user_chunk_data, - read_user_chunk_callback); - -#endif #ifdef PNG_WRITE_SUPPORTED #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG write_ptr = @@ -835,10 +860,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif -#ifndef PNG_STDIO_SUPPORTED - png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#endif + png_set_error_fn(write_ptr, &error_parameters, pngtest_error, + pngtest_warning); #endif pngtest_debug("Allocating read_info, write_info and end_info structures"); read_info_ptr = png_create_info_struct(read_ptr); @@ -848,13 +871,15 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) write_end_info_ptr = png_create_info_struct(write_ptr); #endif +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + init_callback_info(read_info_ptr); + png_set_read_user_chunk_fn(read_ptr, &user_chunk_data, + read_user_chunk_callback); +#endif + #ifdef PNG_SETJMP_SUPPORTED pngtest_debug("Setting jmpbuf for read struct"); -#ifdef USE_FAR_KEYWORD - if (setjmp(tmp_jmpbuf)) -#else if (setjmp(png_jmpbuf(read_ptr))) -#endif { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_free(read_ptr, row_buf); @@ -868,18 +893,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) FCLOSE(fpout); return (1); } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(read_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); -#endif #ifdef PNG_WRITE_SUPPORTED pngtest_debug("Setting jmpbuf for write struct"); -#ifdef USE_FAR_KEYWORD - if (setjmp(tmp_jmpbuf)) -#else if (setjmp(png_jmpbuf(write_ptr))) -#endif { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); @@ -891,12 +909,34 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) FCLOSE(fpout); return (1); } +#endif +#endif -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(write_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); -#endif + if (strict) + { + /* Treat png_benign_error() as errors on read */ + png_set_benign_errors(read_ptr, 0); + +#ifdef PNG_WRITE_SUPPORTED + /* Treat them as errors on write */ + png_set_benign_errors(write_ptr, 0); #endif + + /* if strict is not set, then app warnings and errors are treated as + * warnings in release builds, but not in unstable builds; this can be + * changed with '--relaxed'. + */ + } + + else if (relaxed) + { + /* Allow application (pngtest) errors and warnings to pass */ + png_set_benign_errors(read_ptr, 1); + +#ifdef PNG_WRITE_SUPPORTED + png_set_benign_errors(write_ptr, 1); #endif + } pngtest_debug("Initializing input and output streams"); #ifdef PNG_STDIO_SUPPORTED @@ -916,14 +956,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) # endif #endif -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED - /* Normally one would use Z_DEFAULT_STRATEGY for text compression. - * This is here just to make pngtest replicate the results from libpng - * versions prior to 1.5.4, and to test this new API. - */ - png_set_text_compression_strategy(write_ptr, Z_FILTERED); -#endif - if (status_dots_requested == 1) { #ifdef PNG_WRITE_SUPPORTED @@ -955,24 +987,37 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_set_write_user_transform_fn(write_ptr, count_zero_samples); #endif -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_HANDLE_CHUNK_ALWAYS -# define PNG_HANDLE_CHUNK_ALWAYS 3 -# endif +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + /* Preserve all the unknown chunks, if possible. If this is disabled then, + * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use + * libpng to *save* the unknown chunks on read (because we can't switch the + * save option on!) + * + * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all + * unknown chunks and write will write them all. + */ +#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0); #endif #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_HANDLE_CHUNK_IF_SAFE -# define PNG_HANDLE_CHUNK_IF_SAFE 2 -# endif - png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0); +#endif #endif pngtest_debug("Reading info struct"); png_read_info(read_ptr, read_info_ptr); +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is a bit of a hack; there is no obvious way in the callback function + * to determine that the chunks before the first IDAT have been read, so + * remove the info_ptr (which is only used to determine position relative to + * PLTE) here to indicate that we are after the IDAT. + */ + user_chunk_data.info_ptr = NULL; +#endif + pngtest_debug("Transferring info struct"); { int interlace_type, compression_type, filter_type; @@ -1164,8 +1209,19 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + pngtest_check_text_support(read_ptr, text_ptr, num_text); + if (verbose) - printf("\n Text compression=%d\n", text_ptr->compression); + { + int i; + + printf("\n"); + for (i=0; i 0) { pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose) + { + int i; + + printf("\n"); + for (i=0; i 0) + { + /* We don't really expect to get here because of the setjmp handling + * above, but this is safe. + */ + fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)", + inname, error_count, warning_count); + + if (strict != 0) + return (1); + } + +# ifdef PNG_WRITE_SUPPORTED + /* If there we no write support nothing was written! */ + else if (unsupported_chunks > 0) + { + fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", + inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); + } +# endif + + else if (warning_count > 0) + { + fprintf(STDERR, "\n %s: %d libpng warnings found", + inname, warning_count); + + if (strict != 0) + return (1); + } + pngtest_debug("Opening files for comparison"); if ((fpin = fopen(inname, "rb")) == NULL) { @@ -1457,71 +1555,85 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) return (1); } - for (;;) +#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */ { - png_size_t num_in, num_out; + int wrote_question = 0; - num_in = fread(inbuf, 1, 1, fpin); - num_out = fread(outbuf, 1, 1, fpout); - - if (num_in != num_out) + for (;;) { - fprintf(STDERR, "\nFiles %s and %s are of a different size\n", - inname, outname); + png_size_t num_in, num_out; + char inbuf[256], outbuf[256]; - if (wrote_question == 0) + + num_in = fread(inbuf, 1, sizeof inbuf, fpin); + num_out = fread(outbuf, 1, sizeof outbuf, fpout); + + if (num_in != num_out) { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname, PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question = 1; - } + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); - FCLOSE(fpin); - FCLOSE(fpout); - - if (strict != 0) - return (1); - - else - return (0); - } - - if (!num_in) - break; - - if (png_memcmp(inbuf, outbuf, num_in)) - { - fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); - - if (wrote_question == 0) - { - fprintf(STDERR, + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question = 1; + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + + if (strict != 0 && unsupported_chunks == 0) + return (1); + + else + return (0); } - FCLOSE(fpin); - FCLOSE(fpout); + if (!num_in) + break; - if (strict != 0) - return (1); + if (memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, + outname); - else - return (0); + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + + /* NOTE: the unsupported_chunks escape is permitted here because + * unsupported text chunk compression will result in the compression + * mode being changed (to NONE) yet, in the test case, the result + * can be exactly the same size! + */ + if (strict != 0 && unsupported_chunks == 0) + return (1); + + else + return (0); + } } } +#endif /* PNG_WRITE_SUPPORTED */ FCLOSE(fpin); FCLOSE(fpout); @@ -1607,6 +1719,16 @@ main(int argc, char *argv[]) verbose = 1; inname = argv[2]; strict++; + relaxed = 0; + } + + else if (strcmp(argv[1], "--relaxed") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict = 0; + relaxed++; } else @@ -1815,6 +1937,15 @@ main(int argc, char *argv[]) return (int)(ierror != 0); } +#else +int +main(void) +{ + fprintf(STDERR, + " test ignored because libpng was not built with read support\n"); + return 0; +} +#endif /* Generate a compiler error if there is an old png.h in the search path. */ typedef png_libpng_version_1_5_14beta07 Your_png_h_is_not_version_1_5_14beta07; diff --git a/pngtest.png b/pngtest.png index 81f5f8438a9f0fa8b87cd0266334f72792febf8f..cb3fef4cf844324953cc45f21b479a338cb9c288 100644 GIT binary patch delta 18 acmezF{M~s%?PPOC#fde$Hb*edR{#K1bqD|e delta 17 ZcmezF{M~s%?Zo*zC)Ox!j$oXx0033t2xR~O