[libpng16] Avoid up-cast warnings in pngvalid.c. On ARM the alignment

requirements of png_modifier are greater than that of png_store and as a
consequence compilation of pngvalid.c results in a warning about increased
alignment requirements because of the bare cast to (png_modifier*). The code
is safe, because the pointer is known to point to a stack allocated
png_modifier, but this change avoids the warning.

  Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was
    compiled without the CHECK option it defaulted to on, not off.

  Check user callback behavior in pngunknown.c. Previous versions compiled
    if SAVE_UNKNOWN was not available but did nothing since the callback
    was never implemented.

  Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes
This commit is contained in:
John Bowler 2013-09-30 11:24:17 -05:00 committed by Glenn Randers-Pehrson
parent 15a80443de
commit 8f381901e3
6 changed files with 347 additions and 75 deletions

View File

@ -1,5 +1,5 @@
Libpng 1.6.7beta01 - September 21, 2013 Libpng 1.6.7beta01 - September 30, 2013
This is not intended to be a public release. It will be replaced 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. within a few weeks by a public version or by another test version.
@ -26,13 +26,25 @@ Other information:
Changes since the last public release (1.6.6): Changes since the last public release (1.6.6):
Version 1.6.7 [September 21, 2013] Version 1.6.7 [September 30, 2013]
Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE
combination combination
Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also
fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff
which terminates the make options (as by default in recent versions of which terminates the make options (as by default in recent versions of
Gentoo). Gentoo).
Avoid up-cast warnings in pngvalid.c. On ARM the alignment requirements of
png_modifier are greater than that of png_store and as a consequence
compilation of pngvalid.c results in a warning about increased alignment
requirements because of the bare cast to (png_modifier*). The code is safe,
because the pointer is known to point to a stack allocated png_modifier,
but this change avoids the warning.
Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was
compiled without the CHECK option it defaulted to on, not off.
Check user callback behavior in pngunknown.c. Previous versions compiled
if SAVE_UNKNOWN was not available but did nothing since the callback
was never implemented.
Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

16
CHANGES
View File

@ -4637,16 +4637,28 @@ Version 1.6.4 [September 12, 2013]
Version 1.6.5 [September 14, 2013] Version 1.6.5 [September 14, 2013]
Removed two stray lines of code from arm/arm_init.c. Removed two stray lines of code from arm/arm_init.c.
Version 1.6.6 [September 21, 2013] Version 1.6.6 [September 30, 2013]
Removed two stray lines of code from arm/arm_init.c, again. Removed two stray lines of code from arm/arm_init.c, again.
Version 1.6.7beta01 [September 21, 2013] Version 1.6.7beta01 [September 30, 2013]
Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE
combination combination
Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also
fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff
which terminates the make options (as by default in recent versions of which terminates the make options (as by default in recent versions of
Gentoo). Gentoo).
Avoid up-cast warnings in pngvalid.c. On ARM the alignment requirements of
png_modifier are greater than that of png_store and as a consequence
compilation of pngvalid.c results in a warning about increased alignment
requirements because of the bare cast to (png_modifier*). The code is safe,
because the pointer is known to point to a stack allocated png_modifier,
but this change avoids the warning.
Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was
compiled without the CHECK option it defaulted to on, not off.
Check user callback behavior in pngunknown.c. Previous versions compiled
if SAVE_UNKNOWN was not available but did nothing since the callback
was never implemented.
Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -154,6 +154,16 @@ png_have_neon(png_structp png_ptr)
void void
png_init_filter_functions_neon(png_structp pp, unsigned int bpp) png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
{ {
/* The switch statement is compiled in for ARM_NEON_API, the call to
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
* the check is only performed if the API has not set the NEON option on
* or off explicitly. In this case the check controls what happens.
*
* If the CHECK is not compiled in and the option is UNSET the behavior prior
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
* as documented in png.h
*/
#ifdef PNG_ARM_NEON_API_SUPPORTED #ifdef PNG_ARM_NEON_API_SUPPORTED
switch ((pp->options >> PNG_ARM_NEON) & 3) switch ((pp->options >> PNG_ARM_NEON) & 3)
{ {
@ -178,13 +188,14 @@ png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
break; break;
#endif #endif
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */ #endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
#ifdef PNG_ARM_NEON_API_SUPPORTED #ifdef PNG_ARM_NEON_API_SUPPORTED
default: /* OFF or INVALID */
return;
case PNG_OPTION_ON: case PNG_OPTION_ON:
/* Option turned on */ /* Option turned on */
break; break;
default: /* OFF or INVALID */
return;
} }
#endif #endif

View File

@ -30,7 +30,19 @@
# include "../../png.h" # include "../../png.h"
#endif #endif
#ifdef PNG_READ_SUPPORTED /* Since this program tests the ability to change the unknown chunk handling
* these must be defined:
*/
#if defined(PNG_SET_UNKNOWN_CHUNKS_SUPPORTED) &&\
defined(PNG_READ_SUPPORTED)
/* One of these must be defined to allow us to find out what happened. It is
* still useful to set unknown chunk handling without either of these in order
* to cause *known* chunks to be discarded. This can be a significant
* efficiency gain, but it can't really be tested here.
*/
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) ||\
defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED)
#if PNG_LIBPNG_VER < 10500 #if PNG_LIBPNG_VER < 10500
/* This deliberately lacks the PNG_CONST. */ /* This deliberately lacks the PNG_CONST. */
@ -75,6 +87,24 @@ typedef png_byte *png_const_bytep;
# define png_const_structp png_structp # define png_const_structp png_structp
#endif #endif
#ifdef __cplusplus
# define this not_the_cpp_this
# define new not_the_cpp_new
# define voidcast(type, value) static_cast<type>(value)
#else
# define voidcast(type, value) (value)
#endif /* __cplusplus */
/* Unused formal parameter errors are removed using the following macro which is
* expected to have no bad effects on performance.
*/
#ifndef UNUSED
# if defined(__GNUC__) || defined(_MSC_VER)
# define UNUSED(param) (void)param;
# else
# define UNUSED(param)
# endif
#endif
/* Copied from pngpriv.h */ /* Copied from pngpriv.h */
#define PNG_32b(b,s) ((png_uint_32)(b) << (s)) #define PNG_32b(b,s) ((png_uint_32)(b) << (s))
@ -139,8 +169,8 @@ static struct
{ "PLTE", PNG_INFO_PLTE, png_PLTE, 0, 0, ABSENT, 0 }, { "PLTE", PNG_INFO_PLTE, png_PLTE, 0, 0, ABSENT, 0 },
/* Non-critical chunks that libpng handles */ /* Non-critical chunks that libpng handles */
/* This is a mess but it seems to be the only way to do it - there is no way to /* This is a mess but it seems to be the only way to do it - there is no way
* check for definition outside a #if. * to check for a definition outside a #if.
*/ */
{ "bKGD", PNG_INFO_bKGD, png_bKGD, { "bKGD", PNG_INFO_bKGD, png_bKGD,
# ifdef PNG_READ_bKGD_SUPPORTED # ifdef PNG_READ_bKGD_SUPPORTED
@ -320,11 +350,13 @@ ancillary(const char *name)
return PNG_CHUNK_ANCILLARY(PNG_CHUNK(name[0], name[1], name[2], name[3])); return PNG_CHUNK_ANCILLARY(PNG_CHUNK(name[0], name[1], name[2], name[3]));
} }
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static int static int
ancillaryb(const png_byte *name) ancillaryb(const png_byte *name)
{ {
return PNG_CHUNK_ANCILLARY(PNG_CHUNK(name[0], name[1], name[2], name[3])); return PNG_CHUNK_ANCILLARY(PNG_CHUNK(name[0], name[1], name[2], name[3]));
} }
#endif
/* Type of an error_ptr */ /* Type of an error_ptr */
typedef struct typedef struct
@ -332,8 +364,11 @@ typedef struct
jmp_buf error_return; jmp_buf error_return;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr, end_ptr; png_infop info_ptr, end_ptr;
png_uint_32 before_IDAT;
png_uint_32 after_IDAT;
int error_count; int error_count;
int warning_count; int warning_count;
int keep; /* the default value */
const char *program; const char *program;
const char *file; const char *file;
const char *test; const char *test;
@ -444,11 +479,88 @@ get_valid(display *d, png_infop info_ptr)
return flags; return flags;
} }
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
static int
read_callback(png_structp pp, png_unknown_chunkp pc)
{
/* This function mimics the behavior of png_set_keep_unknown_chunks by
* returning '0' to keep the chunk and '1' to discard it.
*/
display *d = voidcast(display*, png_get_user_chunk_ptr(pp));
int chunk = findb(pc->name);
int keep, discard;
if (chunk < 0) /* not one in our list, so not a known chunk */
keep = d->keep;
else
{
keep = chunk_info[chunk].keep;
if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
{
/* See the comments in png.h - use the default for unknown chunks,
* do not keep known chunks.
*/
if (chunk_info[chunk].unknown)
keep = d->keep;
else
keep = PNG_HANDLE_CHUNK_NEVER;
}
}
switch (keep)
{
default:
fprintf(stderr, "%s(%s): %d: unrecognized chunk option\n", d->file,
d->test, chunk_info[chunk].keep);
display_exit(d);
case PNG_HANDLE_CHUNK_AS_DEFAULT:
case PNG_HANDLE_CHUNK_NEVER:
discard = 1/*handled; discard*/;
break;
case PNG_HANDLE_CHUNK_IF_SAFE:
case PNG_HANDLE_CHUNK_ALWAYS:
discard = 0/*not handled; keep*/;
break;
}
/* Also store information about this chunk in the display, the relevant flag
* is set if the chunk is to be kept ('not handled'.)
*/
if (chunk >= 0) if (!discard) /* stupidity to stop a GCC warning */
{
png_uint_32 flag = chunk_info[chunk].flag;
if (pc->location & PNG_AFTER_IDAT)
d->after_IDAT |= flag;
else
d->before_IDAT |= flag;
}
/* However if there is no support to store unknown chunks don't ask libpng to
* do it; there will be an png_error.
*/
# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
return discard;
# else
return 1; /*handled; discard*/
# endif
}
#endif /* READ_USER_CHUNKS_SUPPORTED */
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static png_uint_32 static png_uint_32
get_unknown(display *d, int def, png_infop info_ptr) get_unknown(display *d, png_infop info_ptr, int after_IDAT)
{ {
/* Create corresponding 'unknown' flags */ /* Create corresponding 'unknown' flags */
png_uint_32 flags = 0; png_uint_32 flags = 0;
UNUSED(after_IDAT)
{ {
png_unknown_chunkp unknown; png_unknown_chunkp unknown;
int num_unknown = png_get_unknown_chunks(d->png_ptr, info_ptr, &unknown); int num_unknown = png_get_unknown_chunks(d->png_ptr, info_ptr, &unknown);
@ -458,16 +570,16 @@ get_unknown(display *d, int def, png_infop info_ptr)
int chunk = findb(unknown[num_unknown].name); int chunk = findb(unknown[num_unknown].name);
/* Chunks not known to pngunknown must be validated here; since they /* Chunks not known to pngunknown must be validated here; since they
* must also be unknown to libpng the 'def' behavior should have been * must also be unknown to libpng the 'display->keep' behavior should
* used. * have been used.
*/ */
if (chunk < 0) switch (def) if (chunk < 0) switch (d->keep)
{ {
default: /* impossible */ default: /* impossible */
case PNG_HANDLE_CHUNK_AS_DEFAULT: case PNG_HANDLE_CHUNK_AS_DEFAULT:
case PNG_HANDLE_CHUNK_NEVER: case PNG_HANDLE_CHUNK_NEVER:
fprintf(stderr, "%s(%s): %s: %s: unknown chunk saved\n", fprintf(stderr, "%s(%s): %s: %s: unknown chunk saved\n",
d->file, d->test, def ? "discard" : "default", d->file, d->test, d->keep ? "discard" : "default",
unknown[num_unknown].name); unknown[num_unknown].name);
++(d->error_count); ++(d->error_count);
break; break;
@ -493,14 +605,39 @@ get_unknown(display *d, int def, png_infop info_ptr)
return flags; return flags;
} }
#else
static png_uint_32
get_unknown(display *d, png_infop info_ptr, int after_IDAT)
/* Otherwise this will return the cached values set by any user callback */
{
UNUSED(info_ptr);
if (after_IDAT)
return d->after_IDAT;
else
return d->before_IDAT;
}
# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
/* The #defines above should mean this is never reached, it's just here as
* a check to ensure the logic is correct.
*/
# error No store support and no user chunk support, this will not work
# endif
#endif
static int static int
check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/, check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
display *d) display *d, int set_callback)
{ {
int i, def = PNG_HANDLE_CHUNK_AS_DEFAULT, npasses, ipass; int i, npasses, ipass;
png_uint_32 height; png_uint_32 height;
d->keep = PNG_HANDLE_CHUNK_AS_DEFAULT;
d->before_IDAT = 0;
d->after_IDAT = 0;
/* Some of these errors are permanently fatal and cause an exit here, others /* Some of these errors are permanently fatal and cause an exit here, others
* are per-test and cause an error return. * are per-test and cause an error return.
*/ */
@ -526,6 +663,16 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
png_init_io(d->png_ptr, fp); png_init_io(d->png_ptr, fp);
# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
/* This is only done if requested by the caller; it interferes with the
* standard store/save mechanism.
*/
if (set_callback)
png_set_read_user_chunk_fn(d->png_ptr, d, read_callback);
# else
UNUSED(set_callback)
# endif
/* Handle each argument in turn; multiple settings are possible for the same /* Handle each argument in turn; multiple settings are possible for the same
* chunk and multiple calls will occur (the last one should override all * chunk and multiple calls will occur (the last one should override all
* preceding ones). * preceding ones).
@ -565,13 +712,11 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
* in this case, so we just check the arguments! This could * in this case, so we just check the arguments! This could
* be improved in the future by using the read callback. * be improved in the future by using the read callback.
*/ */
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED png_byte name[5];
png_byte name[5];
memcpy(name, chunk_info[chunk].name, 5); memcpy(name, chunk_info[chunk].name, 5);
png_set_keep_unknown_chunks(d->png_ptr, option, name, 1); png_set_keep_unknown_chunks(d->png_ptr, option, name, 1);
chunk_info[chunk].keep = option; chunk_info[chunk].keep = option;
# endif
continue; continue;
} }
@ -580,10 +725,8 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
case 7: /* default */ case 7: /* default */
if (memcmp(argv[i], "default", 7) == 0) if (memcmp(argv[i], "default", 7) == 0)
{ {
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED png_set_keep_unknown_chunks(d->png_ptr, option, NULL, 0);
png_set_keep_unknown_chunks(d->png_ptr, option, NULL, 0); d->keep = option;
# endif
def = option;
continue; continue;
} }
@ -592,14 +735,12 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
case 3: /* all */ case 3: /* all */
if (memcmp(argv[i], "all", 3) == 0) if (memcmp(argv[i], "all", 3) == 0)
{ {
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED png_set_keep_unknown_chunks(d->png_ptr, option, NULL, -1);
png_set_keep_unknown_chunks(d->png_ptr, option, NULL, -1); d->keep = option;
def = option;
for (chunk = 0; chunk < NINFO; ++chunk) for (chunk = 0; chunk < NINFO; ++chunk)
if (chunk_info[chunk].all) if (chunk_info[chunk].all)
chunk_info[chunk].keep = option; chunk_info[chunk].keep = option;
# endif
continue; continue;
} }
@ -673,18 +814,18 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
png_read_end(d->png_ptr, d->end_ptr); png_read_end(d->png_ptr, d->end_ptr);
flags[0] = get_valid(d, d->info_ptr); flags[0] = get_valid(d, d->info_ptr);
flags[1] = get_unknown(d, def, d->info_ptr); flags[1] = get_unknown(d, d->info_ptr, 0/*before IDAT*/);
/* Only png_read_png sets PNG_INFO_IDAT! */ /* Only png_read_png sets PNG_INFO_IDAT! */
flags[chunk_info[0/*IDAT*/].keep != PNG_HANDLE_CHUNK_AS_DEFAULT] |= flags[chunk_info[0/*IDAT*/].keep != PNG_HANDLE_CHUNK_AS_DEFAULT] |=
PNG_INFO_IDAT; PNG_INFO_IDAT;
flags[2] = get_valid(d, d->end_ptr); flags[2] = get_valid(d, d->end_ptr);
flags[3] = get_unknown(d, def, d->end_ptr); flags[3] = get_unknown(d, d->end_ptr, 1/*after IDAT*/);
clean_display(d); clean_display(d);
return def; return d->keep;
} }
static void static void
@ -822,7 +963,7 @@ check_handling(display *d, int def, png_uint_32 chunks, png_uint_32 known,
static void static void
perform_one_test(FILE *fp, int argc, const char **argv, perform_one_test(FILE *fp, int argc, const char **argv,
png_uint_32 *default_flags, display *d) png_uint_32 *default_flags, display *d, int set_callback)
{ {
int def; int def;
png_uint_32 flags[2][4]; png_uint_32 flags[2][4];
@ -831,7 +972,7 @@ perform_one_test(FILE *fp, int argc, const char **argv,
clear_keep(); clear_keep();
memcpy(flags[0], default_flags, sizeof flags[0]); memcpy(flags[0], default_flags, sizeof flags[0]);
def = check(fp, argc, argv, flags[1], d); def = check(fp, argc, argv, flags[1], d, set_callback);
/* Chunks should either be known or unknown, never both and this should apply /* Chunks should either be known or unknown, never both and this should apply
* whether the chunk is before or after the IDAT (actually, the app can * whether the chunk is before or after the IDAT (actually, the app can
@ -878,7 +1019,12 @@ perform_one_test_safe(FILE *fp, int argc, const char **argv,
if (setjmp(d->error_return) == 0) if (setjmp(d->error_return) == 0)
{ {
d->test = test; /* allow use of d->error_return */ d->test = test; /* allow use of d->error_return */
perform_one_test(fp, argc, argv, default_flags, d); # ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
perform_one_test(fp, argc, argv, default_flags, d, 0);
# endif
# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
perform_one_test(fp, argc, argv, default_flags, d, 1);
# endif
d->test = init; /* prevent use of d->error_return */ d->test = init; /* prevent use of d->error_return */
} }
} }
@ -902,7 +1048,7 @@ usage(const char *program, const char *reason)
fprintf(stderr, "pngunknown: %s: usage:\n %s [--strict] " fprintf(stderr, "pngunknown: %s: usage:\n %s [--strict] "
"--default|{(CHNK|default|all)=(default|discard|if-safe|save)} " "--default|{(CHNK|default|all)=(default|discard|if-safe|save)} "
"testfile.png\n", reason, program); "testfile.png\n", reason, program);
exit(2); exit(99);
} }
int int
@ -950,11 +1096,6 @@ main(int argc, const char **argv)
else if (default_tests) if (argc != 1) else if (default_tests) if (argc != 1)
usage(d.program, "extra arguments"); usage(d.program, "extra arguments");
# ifndef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
fprintf(stderr, "%s: warning: no 'save' support so arguments ignored\n",
d.program);
# endif
/* The name of the test file is the last argument; remove it. */ /* The name of the test file is the last argument; remove it. */
d.file = argv[--argc]; d.file = argv[--argc];
@ -962,24 +1103,40 @@ main(int argc, const char **argv)
if (fp == NULL) if (fp == NULL)
{ {
perror(d.file); perror(d.file);
exit(2); exit(99);
} }
/* First find all the chunks, known and unknown, in the test file, a failure /* First find all the chunks, known and unknown, in the test file, a failure
* here aborts the whole test. * here aborts the whole test.
*
* If 'save' is supported then the normal saving method should happen,
* otherwise if 'read' is supported then the read callback will do the
* same thing. If both are supported the 'read' callback won't be
* instantiated by default. If 'save' is *not* supported then a user
* callback is required even though we can call png_get_unknown_chunks.
*/ */
if (check(fp, 1, &count_argv, default_flags, &d) != if (check(fp, 1, &count_argv, default_flags, &d,
PNG_HANDLE_CHUNK_ALWAYS) # ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
0
# else
1
# endif
) != PNG_HANDLE_CHUNK_ALWAYS)
{ {
fprintf(stderr, "%s: %s: internal error\n", d.program, d.file); fprintf(stderr, "%s: %s: internal error\n", d.program, d.file);
exit(3); exit(99);
} }
/* Now find what the various supplied options cause to change: */ /* Now find what the various supplied options cause to change: */
if (!default_tests) if (!default_tests)
{ {
d.test = cmd; /* acts as a flag to say exit, do not longjmp */ d.test = cmd; /* acts as a flag to say exit, do not longjmp */
perform_one_test(fp, argc, argv, default_flags, &d); # ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
perform_one_test(fp, argc, argv, default_flags, &d, 0);
# endif
# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
perform_one_test(fp, argc, argv, default_flags, &d, 1);
# endif
d.test = init; d.test = init;
} }
@ -1037,14 +1194,14 @@ main(int argc, const char **argv)
if (fclose(fsuccess) || err) if (fclose(fsuccess) || err)
{ {
fprintf(stderr, "%s: write failed\n", touch_file); fprintf(stderr, "%s: write failed\n", touch_file);
exit(1); exit(99);
} }
} }
else else
{ {
fprintf(stderr, "%s: open failed\n", touch_file); fprintf(stderr, "%s: open failed\n", touch_file);
exit(1); exit(99);
} }
} }
@ -1054,13 +1211,24 @@ main(int argc, const char **argv)
return 1; return 1;
} }
#else #else /* !(READ_USER_CHUNKS || SAVE_UNKNOWN_CHUNKS) */
int int
main(void) main(void)
{ {
fprintf(stderr, fprintf(stderr,
" test ignored because libpng was not built with unknown chunk support\n"); " test ignored: no support to find out about unknown chunks\n");
/* So the test is skipped: */ /* So the test is skipped: */
return 77; return 77;
} }
#endif #endif /* READ_USER_CHUNKS || SAVE_UNKNOWN_CHUNKS */
#else /* !(SET_UNKNOWN_CHUNKS && READ) */
int
main(void)
{
fprintf(stderr,
" test ignored: no support to modify unknown chunk handling\n");
/* So the test is skipped: */
return 77;
}
#endif /* SET_UNKNOWN_CHUNKS && READ*/

View File

@ -616,7 +616,12 @@ typedef struct png_store
unsigned int validated :1; /* used as a temporary flag */ unsigned int validated :1; /* used as a temporary flag */
int nerrors; int nerrors;
int nwarnings; int nwarnings;
char test[128]; /* Name of test */ int noptions; /* number of options below: */
struct {
unsigned char option; /* option number, 0..30 */
unsigned char setting; /* setting (unset,invalid,on,off) */
} options[16];
char test[128]; /* Name of test */
char error[256]; char error[256];
/* Read fields */ /* Read fields */
@ -717,6 +722,7 @@ store_init(png_store* ps)
ps->new.prev = NULL; ps->new.prev = NULL;
ps->palette = NULL; ps->palette = NULL;
ps->npalette = 0; ps->npalette = 0;
ps->noptions = 0;
} }
static void static void
@ -1518,6 +1524,16 @@ set_store_for_write(png_store *ps, png_infopp ppi,
png_set_write_fn(ps->pwrite, ps, store_write, store_flush); png_set_write_fn(ps->pwrite, ps, store_write, store_flush);
# ifdef PNG_SET_OPTION_SUPPORTED
{
int opt;
for (opt=0; opt<ps->noptions; ++opt)
if (png_set_option(ps->pwrite, ps->options[opt].option,
ps->options[opt].setting) == PNG_OPTION_INVALID)
png_error(ps->pwrite, "png option invalid");
}
# endif
if (ppi != NULL) if (ppi != NULL)
*ppi = ps->piwrite = png_create_info_struct(ps->pwrite); *ppi = ps->piwrite = png_create_info_struct(ps->pwrite);
} }
@ -1581,14 +1597,14 @@ store_read_set(png_store *ps, png_uint_32 id)
pf = pf->next; pf = pf->next;
} }
{ {
size_t pos; size_t pos;
char msg[FILE_NAME_SIZE+64]; char msg[FILE_NAME_SIZE+64];
pos = standard_name_from_id(msg, sizeof msg, 0, id); pos = standard_name_from_id(msg, sizeof msg, 0, id);
pos = safecat(msg, sizeof msg, pos, ": file not found"); pos = safecat(msg, sizeof msg, pos, ": file not found");
png_error(ps->pread, msg); png_error(ps->pread, msg);
} }
} }
/* The main interface for reading a saved file - pass the id number of the file /* The main interface for reading a saved file - pass the id number of the file
@ -1633,6 +1649,16 @@ set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id,
Throw ps; Throw ps;
} }
# ifdef PNG_SET_OPTION_SUPPORTED
{
int opt;
for (opt=0; opt<ps->noptions; ++opt)
if (png_set_option(ps->pread, ps->options[opt].option,
ps->options[opt].setting) == PNG_OPTION_INVALID)
png_error(ps->pread, "png option invalid");
}
# endif
store_read_set(ps, id); store_read_set(ps, id);
if (ppi != NULL) if (ppi != NULL)
@ -5988,7 +6014,7 @@ transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn,
Catch(fault) Catch(fault)
{ {
modifier_reset((png_modifier*)fault); modifier_reset(voidcast(png_modifier*,(void*)fault));
} }
} }
@ -7122,7 +7148,7 @@ transform_enable(PNG_CONST char *name)
{ {
fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n", fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n",
name); name);
exit(1); exit(99);
} }
} }
@ -7144,7 +7170,7 @@ transform_disable(PNG_CONST char *name)
fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n", fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n",
name); name);
exit(1); exit(99);
} }
static void static void
@ -8692,7 +8718,7 @@ gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn,
} }
Catch(fault) Catch(fault)
modifier_reset((png_modifier*)fault); modifier_reset(voidcast(png_modifier*,(void*)fault));
} }
static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, static void gamma_threshold_test(png_modifier *pm, png_byte colour_type,
@ -9448,7 +9474,7 @@ perform_interlace_macro_validation(void)
if (m != f) if (m != f)
{ {
fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f); fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f);
exit(1); exit(99);
} }
m = PNG_PASS_START_COL(pass); m = PNG_PASS_START_COL(pass);
@ -9456,7 +9482,7 @@ perform_interlace_macro_validation(void)
if (m != f) if (m != f)
{ {
fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f); fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f);
exit(1); exit(99);
} }
m = PNG_PASS_ROW_SHIFT(pass); m = PNG_PASS_ROW_SHIFT(pass);
@ -9464,7 +9490,7 @@ perform_interlace_macro_validation(void)
if (m != f) if (m != f)
{ {
fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f); fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f);
exit(1); exit(99);
} }
m = PNG_PASS_COL_SHIFT(pass); m = PNG_PASS_COL_SHIFT(pass);
@ -9472,7 +9498,7 @@ perform_interlace_macro_validation(void)
if (m != f) if (m != f)
{ {
fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f); fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f);
exit(1); exit(99);
} }
/* Macros that depend on the image or sub-image height too: /* Macros that depend on the image or sub-image height too:
@ -9493,7 +9519,7 @@ perform_interlace_macro_validation(void)
{ {
fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n", fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n",
v, pass, m, f); v, pass, m, f);
exit(1); exit(99);
} }
m = PNG_COL_FROM_PASS_COL(v, pass); m = PNG_COL_FROM_PASS_COL(v, pass);
@ -9502,7 +9528,7 @@ perform_interlace_macro_validation(void)
{ {
fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n", fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n",
v, pass, m, f); v, pass, m, f);
exit(1); exit(99);
} }
m = PNG_ROW_IN_INTERLACE_PASS(v, pass); m = PNG_ROW_IN_INTERLACE_PASS(v, pass);
@ -9511,7 +9537,7 @@ perform_interlace_macro_validation(void)
{ {
fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
v, pass, m, f); v, pass, m, f);
exit(1); exit(99);
} }
m = PNG_COL_IN_INTERLACE_PASS(v, pass); m = PNG_COL_IN_INTERLACE_PASS(v, pass);
@ -9520,7 +9546,7 @@ perform_interlace_macro_validation(void)
{ {
fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
v, pass, m, f); v, pass, m, f);
exit(1); exit(99);
} }
/* Then the base 1 stuff: */ /* Then the base 1 stuff: */
@ -9531,7 +9557,7 @@ perform_interlace_macro_validation(void)
{ {
fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n", fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n",
v, pass, m, f); v, pass, m, f);
exit(1); exit(99);
} }
m = PNG_PASS_COLS(v, pass); m = PNG_PASS_COLS(v, pass);
@ -9540,7 +9566,7 @@ perform_interlace_macro_validation(void)
{ {
fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n", fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n",
v, pass, m, f); v, pass, m, f);
exit(1); exit(99);
} }
/* Move to the next v - the stepping algorithm starts skipping /* Move to the next v - the stepping algorithm starts skipping
@ -9944,7 +9970,7 @@ int main(int argc, char **argv)
else else
{ {
fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv);
exit(1); exit(99);
} }
catmore = 1; catmore = 1;
@ -9956,10 +9982,51 @@ int main(int argc, char **argv)
else if (strcmp(*argv, "--log16") == 0) else if (strcmp(*argv, "--log16") == 0)
--argc, pm.log16 = atof(*++argv), catmore = 1; --argc, pm.log16 = atof(*++argv), catmore = 1;
#ifdef PNG_SET_OPTION_SUPPORTED
else if (strncmp(*argv, "--option=", 9) == 0)
{
/* Syntax of the argument is <option>:{on|off} */
const char *arg = 9+*argv;
unsigned char option=0, setting=0;
#ifdef PNG_ARM_NEON_API_SUPPORTED
if (strncmp(arg, "arm-neon:", 9) == 0)
option = PNG_ARM_NEON, arg += 9;
else
#endif
if (strncmp(arg, "max-inflate-window:", 19) == 0)
option = PNG_MAXIMUM_INFLATE_WINDOW, arg += 19;
else
{
fprintf(stderr, "pngvalid: %s: %s: unknown option\n", *argv, arg);
exit(99);
}
if (strcmp(arg, "off") == 0)
setting = PNG_OPTION_OFF;
else if (strcmp(arg, "on") == 0)
setting = PNG_OPTION_ON;
else
{
fprintf(stderr,
"pngvalid: %s: %s: unknown setting (use 'on' or 'off')\n",
*argv, arg);
exit(99);
}
pm.this.options[pm.this.noptions].option = option;
pm.this.options[pm.this.noptions++].setting = setting;
}
#endif /* PNG_SET_OPTION_SUPPORTED */
else else
{ {
fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv); fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv);
exit(1); exit(99);
} }
if (catmore) /* consumed an extra *argv */ if (catmore) /* consumed an extra *argv */

View File

@ -1287,7 +1287,9 @@ png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
return; return;
} }
#ifdef PNG_sRGB_SUPPORTED
(void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
#endif
png_colorspace_sync(png_ptr, info_ptr); png_colorspace_sync(png_ptr, info_ptr);
} }
#endif /* PNG_READ_sRGB_SUPPORTED */ #endif /* PNG_READ_sRGB_SUPPORTED */