diff options
author | J08nY <johny@neuromancer.sk> | 2016-06-22 19:33:52 +0200 |
---|---|---|
committer | J08nY <johny@neuromancer.sk> | 2016-06-22 20:57:30 +0200 |
commit | f0290e643be514d15f29382a5b07a3d3bbd182f2 (patch) | |
tree | 203f7096b7042a7c3d035effe009af92f6e68511 /drivers/png/pngerror.c | |
parent | 842e7bfc2f81cda73fd9f16a1ade323a1a5d0292 (diff) |
libpng: New version 1.6.27
Warning: libpng 1.6 is strict about iCCp chunks being incorrect,
solution is to fix the profile. On *nix ImageMagicks "convert" works
on windows optiPNG.
Diffstat (limited to 'drivers/png/pngerror.c')
-rw-r--r-- | drivers/png/pngerror.c | 427 |
1 files changed, 351 insertions, 76 deletions
diff --git a/drivers/png/pngerror.c b/drivers/png/pngerror.c index 372d1b6fbd..3fc8092fa6 100644 --- a/drivers/png/pngerror.c +++ b/drivers/png/pngerror.c @@ -1,7 +1,7 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.5.19 [August 21, 2014] + * Last changed in libpng 1.6.15 [November 20, 2014] * Copyright (c) 1998-2002,2004,2006-2014 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.) @@ -20,14 +20,14 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -static PNG_FUNCTION(void, png_default_error,PNGARG((png_structp png_ptr, +static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, png_const_charp error_message)),PNG_NORETURN); #ifdef PNG_WARNINGS_SUPPORTED static void /* PRIVATE */ -png_default_warning PNGARG((png_structp png_ptr, +png_default_warning PNGARG((png_const_structrp png_ptr, png_const_charp warning_message)); -#endif /* PNG_WARNINGS_SUPPORTED */ +#endif /* WARNINGS */ /* This function is called whenever there is a fatal error. This function * should not be changed. If there is a need to handle errors differently, @@ -36,14 +36,15 @@ png_default_warning PNGARG((png_structp png_ptr, */ #ifdef PNG_ERROR_TEXT_SUPPORTED PNG_FUNCTION(void,PNGAPI -png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) +png_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) { #ifdef PNG_ERROR_NUMBERS_SUPPORTED char msg[16]; if (png_ptr != NULL) { - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + if ((png_ptr->flags & + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) { if (*error_message == PNG_LITERAL_SHARP) { @@ -53,7 +54,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) if (error_message[offset] == ' ') break; - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) { int i; for (i = 0; i < offset - 1; i++) @@ -68,7 +69,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) else { - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) { msg[0] = '0'; msg[1] = '\0'; @@ -79,7 +80,8 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) } #endif if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, error_message); + (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), + error_message); /* If the custom handler doesn't exist, or if it returns, use the default handler, which will not return. */ @@ -87,7 +89,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) } #else PNG_FUNCTION(void,PNGAPI -png_err,(png_structp png_ptr),PNG_NORETURN) +png_err,(png_const_structrp png_ptr),PNG_NORETURN) { /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed * erroneously as '\0', instead of the empty string "". This was @@ -95,13 +97,13 @@ png_err,(png_structp png_ptr),PNG_NORETURN) * will crash in this case. */ if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, ""); + (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), ""); /* If the custom handler doesn't exist, or if it returns, use the default handler, which will not return. */ png_default_error(png_ptr, ""); } -#endif /* PNG_ERROR_TEXT_SUPPORTED */ +#endif /* ERROR_TEXT */ /* Utility to safely appends strings to a buffer. This never errors out so * error checking is not required in the caller. @@ -150,7 +152,7 @@ png_format_number(png_const_charp start, png_charp end, int format, case PNG_NUMBER_FORMAT_fixed: /* Needs five digits (the fraction) */ mincount = 5; - if (output || number % 10 != 0) + if (output != 0 || number % 10 != 0) { *--end = digits[number % 10]; output = 1; @@ -187,7 +189,7 @@ png_format_number(png_const_charp start, png_charp end, int format, ++count; /* Float a fixed number here: */ - if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) + if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start)) { /* End of the fraction, but maybe nothing was output? In that case * drop the decimal point. If the number is a true zero handle that @@ -211,14 +213,14 @@ png_format_number(png_const_charp start, png_charp end, int format, * png_set_error_fn() to replace the warning function at run-time. */ void PNGAPI -png_warning(png_structp png_ptr, png_const_charp warning_message) +png_warning(png_const_structrp png_ptr, png_const_charp warning_message) { int offset = 0; if (png_ptr != NULL) { #ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + if ((png_ptr->flags & + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) #endif { if (*warning_message == PNG_LITERAL_SHARP) @@ -230,7 +232,8 @@ png_warning(png_structp png_ptr, png_const_charp warning_message) } } if (png_ptr != NULL && png_ptr->warning_fn != NULL) - (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), + warning_message + offset); else png_default_warning(png_ptr, warning_message + offset); } @@ -278,7 +281,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format, } void -png_formatted_warning(png_structp png_ptr, png_warning_parameters p, +png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, png_const_charp message) { /* The internal buffer is just 192 bytes - enough for all our messages, @@ -346,29 +349,79 @@ png_formatted_warning(png_structp png_ptr, png_warning_parameters p, /* i is always less than (sizeof msg), so: */ msg[i] = '\0'; - /* And this is the formatted message, it may be larger than - * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are - * not (currently) formatted. + /* And this is the formatted message. It may be larger than + * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these + * are not (currently) formatted. */ png_warning(png_ptr, msg); } -#endif /* PNG_WARNINGS_SUPPORTED */ +#endif /* WARNINGS */ #ifdef PNG_BENIGN_ERRORS_SUPPORTED void PNGAPI -png_benign_error(png_structp png_ptr, png_const_charp error_message) +png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) { - if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) + { +# ifdef PNG_READ_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + png_ptr->chunk_name != 0) + png_chunk_warning(png_ptr, error_message); + else +# endif + png_warning(png_ptr, error_message); + } + + else + { +# ifdef PNG_READ_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + png_ptr->chunk_name != 0) + png_chunk_error(png_ptr, error_message); + else +# endif + png_error(png_ptr, error_message); + } + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif +} + +void /* PRIVATE */ +png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) +{ + if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0) png_warning(png_ptr, error_message); else png_error(png_ptr, error_message); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif } -#endif +void /* PRIVATE */ +png_app_error(png_const_structrp png_ptr, png_const_charp error_message) +{ + if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif +} +#endif /* BENIGN_ERRORS */ + +#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */ +#if defined(PNG_WARNINGS_SUPPORTED) || \ + (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)) /* These utilities are used internally to build an error message that relates * to the current chunk. The chunk name comes from png_ptr->chunk_name, - * this is used to prefix the message. The message is limited in length - * to 63 bytes, the name characters are output as hex digits wrapped in [] + * which is used to prefix the message. The message is limited in length + * to 63 bytes. The name characters are output as hex digits wrapped in [] * if the character is invalid. */ #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) @@ -377,10 +430,8 @@ static PNG_CONST char png_digit[16] = { 'A', 'B', 'C', 'D', 'E', 'F' }; -#define PNG_MAX_ERROR_TEXT 64 -#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) static void /* PRIVATE */ -png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp +png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp error_message) { png_uint_32 chunk_name = png_ptr->chunk_name; @@ -391,7 +442,7 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp int c = (int)(chunk_name >> ishift) & 0xff; ishift -= 8; - if (isnonalpha(c)) + if (isnonalpha(c) != 0) { buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; buffer[iout++] = png_digit[(c & 0xf0) >> 4]; @@ -422,11 +473,11 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp buffer[iout] = '\0'; } } -#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ +#endif /* WARNINGS || ERROR_TEXT */ #if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) PNG_FUNCTION(void,PNGAPI -png_chunk_error,(png_structp png_ptr, png_const_charp error_message), +png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), PNG_NORETURN) { char msg[18+PNG_MAX_ERROR_TEXT]; @@ -439,11 +490,11 @@ png_chunk_error,(png_structp png_ptr, png_const_charp error_message), png_error(png_ptr, msg); } } -#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ +#endif /* READ && ERROR_TEXT */ #ifdef PNG_WARNINGS_SUPPORTED void PNGAPI -png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) { char msg[18+PNG_MAX_ERROR_TEXT]; if (png_ptr == NULL) @@ -455,38 +506,83 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) png_warning(png_ptr, msg); } } -#endif /* PNG_WARNINGS_SUPPORTED */ +#endif /* WARNINGS */ #ifdef PNG_READ_SUPPORTED #ifdef PNG_BENIGN_ERRORS_SUPPORTED void PNGAPI -png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) +png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp + error_message) { - if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) png_chunk_warning(png_ptr, error_message); else png_chunk_error(png_ptr, error_message); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif } #endif -#endif /* PNG_READ_SUPPORTED */ +#endif /* READ */ + +void /* PRIVATE */ +png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) +{ +# ifndef PNG_WARNINGS_SUPPORTED + PNG_UNUSED(message) +# endif + + /* This is always supported, but for just read or just write it + * unconditionally does the right thing. + */ +# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) +# endif + +# ifdef PNG_READ_SUPPORTED + { + if (error < PNG_CHUNK_ERROR) + png_chunk_warning(png_ptr, message); + + else + png_chunk_benign_error(png_ptr, message); + } +# endif + +# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) + else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) +# endif + +# ifdef PNG_WRITE_SUPPORTED + { + if (error < PNG_CHUNK_WRITE_ERROR) + png_app_warning(png_ptr, message); + + else + png_app_error(png_ptr, message); + } +# endif +} #ifdef PNG_ERROR_TEXT_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_FUNCTION(void, -png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) +png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) { # define fixed_message "fixed point overflow in " # define fixed_message_ln ((sizeof fixed_message)-1) int iin; char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; - png_memcpy(msg, fixed_message, fixed_message_ln); + memcpy(msg, fixed_message, fixed_message_ln); iin = 0; - if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) - { - msg[fixed_message_ln + iin] = name[iin]; - ++iin; - } + if (name != NULL) + while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } msg[fixed_message_ln + iin] = 0; png_error(png_ptr, msg); } @@ -498,14 +594,111 @@ png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) * otherwise it is necessary for png_default_error to be overridden. */ jmp_buf* PNGAPI -png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, +png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, size_t jmp_buf_size) { - if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) + /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value + * and it must not change after that. Libpng doesn't care how big the + * buffer is, just that it doesn't change. + * + * If the buffer size is no *larger* than the size of jmp_buf when libpng is + * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0 + * semantics that this call will not fail. If the size is larger, however, + * the buffer is allocated and this may fail, causing the function to return + * NULL. + */ + if (png_ptr == NULL) return NULL; + if (png_ptr->jmp_buf_ptr == NULL) + { + png_ptr->jmp_buf_size = 0; /* not allocated */ + + if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local)) + png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; + + else + { + png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, + png_malloc_warn(png_ptr, jmp_buf_size)); + + if (png_ptr->jmp_buf_ptr == NULL) + return NULL; /* new NULL return on OOM */ + + png_ptr->jmp_buf_size = jmp_buf_size; + } + } + + else /* Already allocated: check the size */ + { + size_t size = png_ptr->jmp_buf_size; + + if (size == 0) + { + size = (sizeof png_ptr->jmp_buf_local); + if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local) + { + /* This is an internal error in libpng: somehow we have been left + * with a stack allocated jmp_buf when the application regained + * control. It's always possible to fix this up, but for the moment + * this is a png_error because that makes it easy to detect. + */ + png_error(png_ptr, "Libpng jmp_buf still allocated"); + /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */ + } + } + + if (size != jmp_buf_size) + { + png_warning(png_ptr, "Application jmp_buf size changed"); + return NULL; /* caller will probably crash: no choice here */ + } + } + + /* Finally fill in the function, now we have a satisfactory buffer. It is + * valid to change the function on every call. + */ png_ptr->longjmp_fn = longjmp_fn; - return &png_ptr->longjmp_buffer; + return png_ptr->jmp_buf_ptr; +} + +void /* PRIVATE */ +png_free_jmpbuf(png_structrp png_ptr) +{ + if (png_ptr != NULL) + { + jmp_buf *jb = png_ptr->jmp_buf_ptr; + + /* A size of 0 is used to indicate a local, stack, allocation of the + * pointer; used here and in png.c + */ + if (jb != NULL && png_ptr->jmp_buf_size > 0) + { + + /* This stuff is so that a failure to free the error control structure + * does not leave libpng in a state with no valid error handling: the + * free always succeeds, if there is an error it gets ignored. + */ + if (jb != &png_ptr->jmp_buf_local) + { + /* Make an internal, libpng, jmp_buf to return here */ + jmp_buf free_jmp_buf; + + if (!setjmp(free_jmp_buf)) + { + png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */ + png_ptr->jmp_buf_size = 0; /* stack allocation */ + png_ptr->longjmp_fn = longjmp; + png_free(png_ptr, jb); /* Return to setjmp on error */ + } + } + } + + /* *Always* cancel everything out: */ + png_ptr->jmp_buf_size = 0; + png_ptr->jmp_buf_ptr = NULL; + png_ptr->longjmp_fn = 0; + } } #endif @@ -515,7 +708,7 @@ png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, * error function pointer in png_set_error_fn(). */ static PNG_FUNCTION(void /* PRIVATE */, -png_default_error,(png_structp png_ptr, png_const_charp error_message), +png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), PNG_NORETURN) { #ifdef PNG_CONSOLE_IO_SUPPORTED @@ -562,27 +755,23 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message), } PNG_FUNCTION(void,PNGAPI -png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) +png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) { #ifdef PNG_SETJMP_SUPPORTED - if (png_ptr && png_ptr->longjmp_fn) - { -# ifdef USE_FAR_KEYWORD - { - jmp_buf tmp_jmpbuf; - png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); - png_ptr->longjmp_fn(tmp_jmpbuf, val); - } - -# else - png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val); -# endif - } + if (png_ptr != NULL && png_ptr->longjmp_fn != NULL && + png_ptr->jmp_buf_ptr != NULL) + png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val); #else - PNG_UNUSED(png_ptr); - PNG_UNUSED(val); + PNG_UNUSED(png_ptr) + PNG_UNUSED(val) #endif - /* Here if not setjmp support or if png_ptr is null. */ + + /* If control reaches this point, png_longjmp() must not return. The only + * choice is to terminate the whole process (or maybe the thread); to do + * this the ANSI-C abort() function is used unless a different method is + * implemented by overriding the default configuration setting for + * PNG_ABORT(). + */ PNG_ABORT(); } @@ -593,7 +782,7 @@ png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) * not used, but it is passed in case it may be useful. */ static void /* PRIVATE */ -png_default_warning(png_structp png_ptr, png_const_charp warning_message) +png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) { #ifdef PNG_CONSOLE_IO_SUPPORTED # ifdef PNG_ERROR_NUMBERS_SUPPORTED @@ -635,15 +824,15 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) #endif PNG_UNUSED(png_ptr) /* Make compiler happy */ } -#endif /* PNG_WARNINGS_SUPPORTED */ +#endif /* WARNINGS */ /* This function is called when the application wants to use another method * of handling errors and warnings. Note that the error function MUST NOT * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1) + * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1) */ void PNGAPI -png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, +png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn) { if (png_ptr == NULL) @@ -664,7 +853,7 @@ png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, * pointer before png_write_destroy and png_read_destroy are called. */ png_voidp PNGAPI -png_get_error_ptr(png_const_structp png_ptr) +png_get_error_ptr(png_const_structrp png_ptr) { if (png_ptr == NULL) return NULL; @@ -675,7 +864,7 @@ png_get_error_ptr(png_const_structp png_ptr) #ifdef PNG_ERROR_NUMBERS_SUPPORTED void PNGAPI -png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) { if (png_ptr != NULL) { @@ -685,4 +874,90 @@ png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) } } #endif -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ + +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + /* Currently the above both depend on SETJMP_SUPPORTED, however it would be + * possible to implement without setjmp support just so long as there is some + * way to handle the error return here: + */ +PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI +png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + const png_const_structrp png_ptr = png_nonconst_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* An error is always logged here, overwriting anything (typically a warning) + * that is already there: + */ + if (image != NULL) + { + png_safecat(image->message, (sizeof image->message), 0, error_message); + image->warning_or_error |= PNG_IMAGE_ERROR; + + /* Retrieve the jmp_buf from within the png_control, making this work for + * C++ compilation too is pretty tricky: C++ wants a pointer to the first + * element of a jmp_buf, but C doesn't tell us the type of that. + */ + if (image->opaque != NULL && image->opaque->error_buf != NULL) + longjmp(png_control_jmp_buf(image->opaque), 1); + + /* Missing longjmp buffer, the following is to help debugging: */ + { + size_t pos = png_safecat(image->message, (sizeof image->message), 0, + "bad longjmp: "); + png_safecat(image->message, (sizeof image->message), pos, + error_message); + } + } + + /* Here on an internal programming error. */ + abort(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +void /* PRIVATE */ PNGCBAPI +png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) +{ + const png_const_structrp png_ptr = png_nonconst_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* A warning is only logged if there is no prior warning or error. */ + if (image->warning_or_error == 0) + { + png_safecat(image->message, (sizeof image->message), 0, warning_message); + image->warning_or_error |= PNG_IMAGE_WARNING; + } +} +#endif + +int /* PRIVATE */ +png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) +{ + volatile png_imagep image = image_in; + volatile int result; + volatile png_voidp saved_error_buf; + jmp_buf safe_jmpbuf; + + /* Safely execute function(arg) with png_error returning to this function. */ + saved_error_buf = image->opaque->error_buf; + result = setjmp(safe_jmpbuf) == 0; + + if (result != 0) + { + + image->opaque->error_buf = safe_jmpbuf; + result = function(arg); + } + + image->opaque->error_buf = saved_error_buf; + + /* And do the cleanup prior to any failure return. */ + if (result == 0) + png_image_free(image); + + return result; +} +#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */ +#endif /* READ || WRITE */ |