mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
[libpng16] Added "tunknown" test and corrected a logic error in
png_handle_unknown() when SAVE support is absent. Moved the shell test scripts for contrib/libtests from the libpng top directory to contrib/libtests. png_handle_unknown() must always read or skip the chunk, if SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set a user callback an unknown chunk will not be read, leading to a read error, which was revealed by the "tunknown" test.
This commit is contained in:
parent
3c1f6983c5
commit
d0eef28ee1
7
ANNOUNCE
7
ANNOUNCE
@ -462,6 +462,13 @@ Version 1.6.0beta28 [August 17, 2012]
|
|||||||
unsafe-to-copy chunks which were dropped before) and eliminates the
|
unsafe-to-copy chunks which were dropped before) and eliminates the
|
||||||
repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
|
repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
|
||||||
(so the chunks are where libpng would put them).
|
(so the chunks are where libpng would put them).
|
||||||
|
Added "tunknown" test and corrected a logic error in png_handle_unknown()
|
||||||
|
when SAVE support is absent. Moved the shell test scripts for
|
||||||
|
contrib/libtests from the libpng top directory to contrib/libtests.
|
||||||
|
png_handle_unknown() must always read or skip the chunk, if
|
||||||
|
SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set
|
||||||
|
a user callback an unknown chunk will not be read, leading to a read
|
||||||
|
error, which was revealed by the "tunknown" test.
|
||||||
|
|
||||||
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
|
||||||
|
7
CHANGES
7
CHANGES
@ -4213,6 +4213,13 @@ Version 1.6.0beta28 [August 17, 2012]
|
|||||||
unsafe-to-copy chunks which were dropped before) and eliminates the
|
unsafe-to-copy chunks which were dropped before) and eliminates the
|
||||||
repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
|
repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
|
||||||
(so the chunks are where libpng would put them).
|
(so the chunks are where libpng would put them).
|
||||||
|
Added "tunknown" test and corrected a logic error in png_handle_unknown()
|
||||||
|
when SAVE support is absent. Moved the shell test scripts for
|
||||||
|
contrib/libtests from the libpng top directory to contrib/libtests.
|
||||||
|
png_handle_unknown() must always read or skip the chunk, if
|
||||||
|
SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set
|
||||||
|
a user callback an unknown chunk will not be read, leading to a read
|
||||||
|
error, which was revealed by the "tunknown" test.
|
||||||
|
|
||||||
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
|
||||||
|
@ -25,7 +25,7 @@ AC_CONFIG_MACRO_DIR([scripts])
|
|||||||
# color-tests requires automake 1.11 or later
|
# color-tests requires automake 1.11 or later
|
||||||
# silent-rules requires automake 1.11 or later
|
# silent-rules requires automake 1.11 or later
|
||||||
# dist-xz requires automake 1.11 or later
|
# dist-xz requires automake 1.11 or later
|
||||||
# 1.11.1 fixes a security issue in 1.11
|
# 1.12.2 fixes a security issue in 1.11.2 and 1.12.1
|
||||||
AM_INIT_AUTOMAKE([1.12.2 foreign dist-xz dist-bzip2 color-tests silent-rules])
|
AM_INIT_AUTOMAKE([1.12.2 foreign dist-xz dist-bzip2 color-tests silent-rules])
|
||||||
# was:
|
# was:
|
||||||
# AM_INIT_AUTOMAKE
|
# AM_INIT_AUTOMAKE
|
||||||
|
0
contrib/libtests/gentests.sh
Normal file → Executable file
0
contrib/libtests/gentests.sh
Normal file → Executable file
@ -11,12 +11,9 @@
|
|||||||
*
|
*
|
||||||
* NOTES:
|
* NOTES:
|
||||||
* This is a C program that is intended to be linked against libpng. It
|
* This is a C program that is intended to be linked against libpng. It
|
||||||
* generates bitmaps internally, stores them as PNG files (using the
|
* allows the libpng unknown handling code to be tested by interpreting
|
||||||
* sequential write code) then reads them back (using the sequential
|
* arguemnts to save or discard combinations of chunks. The program is
|
||||||
* read code) and validates that the result has the correct data.
|
* currently just a minimal validation for the built-in libpng facilities.
|
||||||
*
|
|
||||||
* The program can be modified and extended to test the correctness of
|
|
||||||
* transformations performed by libpng.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -25,6 +22,8 @@
|
|||||||
|
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
#if PNG_LIBPNG_VER < 10500
|
#if PNG_LIBPNG_VER < 10500
|
||||||
/* This deliberately lacks the PNG_CONST. */
|
/* This deliberately lacks the PNG_CONST. */
|
||||||
typedef png_byte *png_const_bytep;
|
typedef png_byte *png_const_bytep;
|
||||||
@ -365,11 +364,20 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/)
|
|||||||
|
|
||||||
if (chunk >= 0)
|
if (chunk >= 0)
|
||||||
{
|
{
|
||||||
png_byte name[5];
|
/* These #if tests have the effect of skipping the arguments
|
||||||
|
* if SAVE support is unavailable - we can't do a useful test
|
||||||
|
* in this case, so we just check the arguments! This could
|
||||||
|
* be improved in the future by using the read callback.
|
||||||
|
*/
|
||||||
|
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
|
png_byte name[5];
|
||||||
|
|
||||||
memcpy(name, chunk_info[chunk].name, 5);
|
memcpy(name, chunk_info[chunk].name, 5);
|
||||||
png_set_keep_unknown_chunks(png_ptr, option, name, 1);
|
png_set_keep_unknown_chunks(png_ptr, option, name, 1);
|
||||||
chunk_info[chunk].keep = option;
|
chunk_info[chunk].keep = option;
|
||||||
|
# else
|
||||||
|
(void)option;
|
||||||
|
# endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,8 +386,10 @@ 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)
|
||||||
{
|
{
|
||||||
png_set_keep_unknown_chunks(png_ptr, option, NULL, 0);
|
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
def = option;
|
png_set_keep_unknown_chunks(png_ptr, option, NULL, 0);
|
||||||
|
def = option;
|
||||||
|
# endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,15 +398,21 @@ 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)
|
||||||
{
|
{
|
||||||
png_set_keep_unknown_chunks(png_ptr, option, NULL, -1);
|
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
def = option;
|
png_set_keep_unknown_chunks(png_ptr, option, NULL, -1);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* some misplaced = */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,7 +515,7 @@ check_handling(const char *file, int def, png_uint_32 chunks, png_uint_32 known,
|
|||||||
int i = find_by_flag(flag);
|
int i = find_by_flag(flag);
|
||||||
int keep = chunk_info[i].keep;
|
int keep = chunk_info[i].keep;
|
||||||
const char *type;
|
const char *type;
|
||||||
const char *error = NULL;
|
const char *errorx = NULL;
|
||||||
|
|
||||||
if (chunk_info[i].unknown)
|
if (chunk_info[i].unknown)
|
||||||
{
|
{
|
||||||
@ -513,34 +529,38 @@ check_handling(const char *file, int def, png_uint_32 chunks, png_uint_32 known,
|
|||||||
type = "UNKNOWN (specified)";
|
type = "UNKNOWN (specified)";
|
||||||
|
|
||||||
if (flag & known)
|
if (flag & known)
|
||||||
error = "chunk processed";
|
errorx = "chunk processed";
|
||||||
|
|
||||||
else switch (keep)
|
else switch (keep)
|
||||||
{
|
{
|
||||||
case PNG_HANDLE_CHUNK_AS_DEFAULT:
|
case PNG_HANDLE_CHUNK_AS_DEFAULT:
|
||||||
if (flag & unknown)
|
if (flag & unknown)
|
||||||
error = "DEFAULT: unknown chunk saved";
|
errorx = "DEFAULT: unknown chunk saved";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNG_HANDLE_CHUNK_NEVER:
|
case PNG_HANDLE_CHUNK_NEVER:
|
||||||
if (flag & unknown)
|
if (flag & unknown)
|
||||||
error = "DISCARD: unknown chunk saved";
|
errorx = "DISCARD: unknown chunk saved";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNG_HANDLE_CHUNK_IF_SAFE:
|
case PNG_HANDLE_CHUNK_IF_SAFE:
|
||||||
if (ancillary(chunk_info[i].name))
|
if (ancillary(chunk_info[i].name))
|
||||||
{
|
{
|
||||||
if (!(flag & unknown))
|
if (!(flag & unknown))
|
||||||
error = "IF-SAFE: unknown ancillary chunk lost";
|
errorx = "IF-SAFE: unknown ancillary chunk lost";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (flag & unknown)
|
else if (flag & unknown)
|
||||||
error = "IF-SAFE: unknown critical chunk saved";
|
errorx = "IF-SAFE: unknown critical chunk saved";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNG_HANDLE_CHUNK_ALWAYS:
|
case PNG_HANDLE_CHUNK_ALWAYS:
|
||||||
if (!(flag & unknown))
|
if (!(flag & unknown))
|
||||||
error = "SAVE: unknown chunk lost";
|
errorx = "SAVE: unknown chunk lost";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorx = "internal error: bad keep";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} /* unknown chunk */
|
} /* unknown chunk */
|
||||||
@ -555,43 +575,47 @@ check_handling(const char *file, int def, png_uint_32 chunks, png_uint_32 known,
|
|||||||
* caught below when checking for inconsistent processing.
|
* caught below when checking for inconsistent processing.
|
||||||
*/
|
*/
|
||||||
if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
|
if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
|
||||||
error = "!DEFAULT: known chunk processed";
|
errorx = "!DEFAULT: known chunk processed";
|
||||||
}
|
}
|
||||||
|
|
||||||
else /* not processed */ switch (keep)
|
else /* not processed */ switch (keep)
|
||||||
{
|
{
|
||||||
case PNG_HANDLE_CHUNK_AS_DEFAULT:
|
case PNG_HANDLE_CHUNK_AS_DEFAULT:
|
||||||
error = "DEFAULT: known chunk not processed";
|
errorx = "DEFAULT: known chunk not processed";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNG_HANDLE_CHUNK_NEVER:
|
case PNG_HANDLE_CHUNK_NEVER:
|
||||||
if (flag & unknown)
|
if (flag & unknown)
|
||||||
error = "DISCARD: known chunk saved";
|
errorx = "DISCARD: known chunk saved";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNG_HANDLE_CHUNK_IF_SAFE:
|
case PNG_HANDLE_CHUNK_IF_SAFE:
|
||||||
if (ancillary(chunk_info[i].name))
|
if (ancillary(chunk_info[i].name))
|
||||||
{
|
{
|
||||||
if (!(flag & unknown))
|
if (!(flag & unknown))
|
||||||
error = "IF-SAFE: known ancillary chunk lost";
|
errorx = "IF-SAFE: known ancillary chunk lost";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (flag & unknown)
|
else if (flag & unknown)
|
||||||
error = "IF-SAFE: known critical chunk saved";
|
errorx = "IF-SAFE: known critical chunk saved";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNG_HANDLE_CHUNK_ALWAYS:
|
case PNG_HANDLE_CHUNK_ALWAYS:
|
||||||
if (!(flag & unknown))
|
if (!(flag & unknown))
|
||||||
error = "SAVE: known chunk lost";
|
errorx = "SAVE: known chunk lost";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorx = "internal error: bad keep (2)";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != NULL)
|
if (errorx != NULL)
|
||||||
{
|
{
|
||||||
++error_count;
|
++error_count;
|
||||||
fprintf(stderr, "%s: %s %s %s: %s\n",
|
fprintf(stderr, "%s: %s %s %s: %s\n",
|
||||||
file, type, chunk_info[i].name, position, error);
|
file, type, chunk_info[i].name, position, errorx);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunks &= ~flag;
|
chunks &= ~flag;
|
||||||
@ -622,6 +646,10 @@ main(int argc, const char **argv)
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifndef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
|
fprintf(stderr,
|
||||||
|
"test-unknown: warning: no 'save' support so arguments ignored\n");
|
||||||
|
# endif
|
||||||
fp = fopen(argv[argc], "rb");
|
fp = fopen(argv[argc], "rb");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
@ -681,3 +709,13 @@ main(int argc, const char **argv)
|
|||||||
|
|
||||||
return error_count + (strict ? warning_count : 0);
|
return error_count + (strict ? warning_count : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
" test ignored because libpng was not built with unknown chunk support\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
38
contrib/libtests/test-unknown.sh
Executable file
38
contrib/libtests/test-unknown.sh
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Run the unknown API tests
|
||||||
|
err=0
|
||||||
|
image="${srcdir}/pngtest.png"
|
||||||
|
#
|
||||||
|
# stream 4 is used for the output of the shell, pngtest-log.txt gets all the
|
||||||
|
# normal program output.
|
||||||
|
exec 4>&1 1>>pngtest-log.txt 2>&1
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "============ test-unknown.sh =============="
|
||||||
|
|
||||||
|
echo "Running test-unknown.sh" >&4
|
||||||
|
|
||||||
|
for tests in \
|
||||||
|
"discard default=discard"\
|
||||||
|
"save default=save"\
|
||||||
|
"if-safe default=if-safe"\
|
||||||
|
"vpAg vpAg=if-safe"\
|
||||||
|
"sTER sTER=if-safe"\
|
||||||
|
"IDAT default=discard IDAT=save"\
|
||||||
|
"sAPI bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save"
|
||||||
|
do
|
||||||
|
set $tests
|
||||||
|
test="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if ./tunknown "$@" "$image" 4>&-
|
||||||
|
then
|
||||||
|
echo " PASS: test-unknown $test" >&4
|
||||||
|
else
|
||||||
|
echo " FAIL: test-unknown $test" >&4
|
||||||
|
err=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $err
|
18
pngrutil.c
18
pngrutil.c
@ -2883,9 +2883,8 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
|
|||||||
keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
|
keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
else
|
||||||
else
|
/* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
|
||||||
# endif
|
|
||||||
# endif /* PNG_READ_USER_CHUNKS_SUPPORTED */
|
# endif /* PNG_READ_USER_CHUNKS_SUPPORTED */
|
||||||
|
|
||||||
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
@ -2913,6 +2912,19 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
|
|||||||
# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
|
# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
|
||||||
# error no method to support READ_UNKNOWN_CHUNKS
|
# error no method to support READ_UNKNOWN_CHUNKS
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
{
|
||||||
|
/* If here there is no read callback pointer set and no support is
|
||||||
|
* compiled in to just save the unknown chunks, so simply skip this
|
||||||
|
* chunk. If 'keep' is something other than AS_DEFAULT or NEVER then
|
||||||
|
* the app has erroneously asked for unknown chunk saving when there
|
||||||
|
* is no support.
|
||||||
|
*/
|
||||||
|
if (keep > PNG_HANDLE_CHUNK_NEVER)
|
||||||
|
png_app_error(png_ptr, "no unknown chunk support available");
|
||||||
|
|
||||||
|
png_crc_finish(png_ptr, length);
|
||||||
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
|
Loading…
x
Reference in New Issue
Block a user