1cb93a386Sopenharmony_ci 2cb93a386Sopenharmony_ci/* pngerror.c - stub functions for i/o and memory allocation 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Copyright (c) 2018 Cosmin Truta 5cb93a386Sopenharmony_ci * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson 6cb93a386Sopenharmony_ci * Copyright (c) 1996-1997 Andreas Dilger 7cb93a386Sopenharmony_ci * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. 8cb93a386Sopenharmony_ci * 9cb93a386Sopenharmony_ci * This code is released under the libpng license. 10cb93a386Sopenharmony_ci * For conditions of distribution and use, see the disclaimer 11cb93a386Sopenharmony_ci * and license in png.h 12cb93a386Sopenharmony_ci * 13cb93a386Sopenharmony_ci * This file provides a location for all error handling. Users who 14cb93a386Sopenharmony_ci * need special error handling are expected to write replacement functions 15cb93a386Sopenharmony_ci * and use png_set_error_fn() to use those functions. See the instructions 16cb93a386Sopenharmony_ci * at each function. 17cb93a386Sopenharmony_ci */ 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include "pngpriv.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cistatic PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, 24cb93a386Sopenharmony_ci png_const_charp error_message)),PNG_NORETURN); 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED 27cb93a386Sopenharmony_cistatic void /* PRIVATE */ 28cb93a386Sopenharmony_cipng_default_warning PNGARG((png_const_structrp png_ptr, 29cb93a386Sopenharmony_ci png_const_charp warning_message)); 30cb93a386Sopenharmony_ci#endif /* WARNINGS */ 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci/* This function is called whenever there is a fatal error. This function 33cb93a386Sopenharmony_ci * should not be changed. If there is a need to handle errors differently, 34cb93a386Sopenharmony_ci * you should supply a replacement error function and use png_set_error_fn() 35cb93a386Sopenharmony_ci * to replace the error function at run-time. 36cb93a386Sopenharmony_ci */ 37cb93a386Sopenharmony_ci#ifdef PNG_ERROR_TEXT_SUPPORTED 38cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI 39cb93a386Sopenharmony_cipng_error,(png_const_structrp png_ptr, png_const_charp error_message), 40cb93a386Sopenharmony_ci PNG_NORETURN) 41cb93a386Sopenharmony_ci{ 42cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED 43cb93a386Sopenharmony_ci char msg[16]; 44cb93a386Sopenharmony_ci if (png_ptr != NULL) 45cb93a386Sopenharmony_ci { 46cb93a386Sopenharmony_ci if ((png_ptr->flags & 47cb93a386Sopenharmony_ci (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) 48cb93a386Sopenharmony_ci { 49cb93a386Sopenharmony_ci if (*error_message == PNG_LITERAL_SHARP) 50cb93a386Sopenharmony_ci { 51cb93a386Sopenharmony_ci /* Strip "#nnnn " from beginning of error message. */ 52cb93a386Sopenharmony_ci int offset; 53cb93a386Sopenharmony_ci for (offset = 1; offset<15; offset++) 54cb93a386Sopenharmony_ci if (error_message[offset] == ' ') 55cb93a386Sopenharmony_ci break; 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) 58cb93a386Sopenharmony_ci { 59cb93a386Sopenharmony_ci int i; 60cb93a386Sopenharmony_ci for (i = 0; i < offset - 1; i++) 61cb93a386Sopenharmony_ci msg[i] = error_message[i + 1]; 62cb93a386Sopenharmony_ci msg[i - 1] = '\0'; 63cb93a386Sopenharmony_ci error_message = msg; 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci else 67cb93a386Sopenharmony_ci error_message += offset; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci else 71cb93a386Sopenharmony_ci { 72cb93a386Sopenharmony_ci if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) 73cb93a386Sopenharmony_ci { 74cb93a386Sopenharmony_ci msg[0] = '0'; 75cb93a386Sopenharmony_ci msg[1] = '\0'; 76cb93a386Sopenharmony_ci error_message = msg; 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci#endif 82cb93a386Sopenharmony_ci if (png_ptr != NULL && png_ptr->error_fn != NULL) 83cb93a386Sopenharmony_ci (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), 84cb93a386Sopenharmony_ci error_message); 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci /* If the custom handler doesn't exist, or if it returns, 87cb93a386Sopenharmony_ci use the default handler, which will not return. */ 88cb93a386Sopenharmony_ci png_default_error(png_ptr, error_message); 89cb93a386Sopenharmony_ci} 90cb93a386Sopenharmony_ci#else 91cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI 92cb93a386Sopenharmony_cipng_err,(png_const_structrp png_ptr),PNG_NORETURN) 93cb93a386Sopenharmony_ci{ 94cb93a386Sopenharmony_ci /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed 95cb93a386Sopenharmony_ci * erroneously as '\0', instead of the empty string "". This was 96cb93a386Sopenharmony_ci * apparently an error, introduced in libpng-1.2.20, and png_default_error 97cb93a386Sopenharmony_ci * will crash in this case. 98cb93a386Sopenharmony_ci */ 99cb93a386Sopenharmony_ci if (png_ptr != NULL && png_ptr->error_fn != NULL) 100cb93a386Sopenharmony_ci (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), ""); 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci /* If the custom handler doesn't exist, or if it returns, 103cb93a386Sopenharmony_ci use the default handler, which will not return. */ 104cb93a386Sopenharmony_ci png_default_error(png_ptr, ""); 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci#endif /* ERROR_TEXT */ 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci/* Utility to safely appends strings to a buffer. This never errors out so 109cb93a386Sopenharmony_ci * error checking is not required in the caller. 110cb93a386Sopenharmony_ci */ 111cb93a386Sopenharmony_cisize_t 112cb93a386Sopenharmony_cipng_safecat(png_charp buffer, size_t bufsize, size_t pos, 113cb93a386Sopenharmony_ci png_const_charp string) 114cb93a386Sopenharmony_ci{ 115cb93a386Sopenharmony_ci if (buffer != NULL && pos < bufsize) 116cb93a386Sopenharmony_ci { 117cb93a386Sopenharmony_ci if (string != NULL) 118cb93a386Sopenharmony_ci while (*string != '\0' && pos < bufsize-1) 119cb93a386Sopenharmony_ci buffer[pos++] = *string++; 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci buffer[pos] = '\0'; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci return pos; 125cb93a386Sopenharmony_ci} 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) 128cb93a386Sopenharmony_ci/* Utility to dump an unsigned value into a buffer, given a start pointer and 129cb93a386Sopenharmony_ci * and end pointer (which should point just *beyond* the end of the buffer!) 130cb93a386Sopenharmony_ci * Returns the pointer to the start of the formatted string. 131cb93a386Sopenharmony_ci */ 132cb93a386Sopenharmony_cipng_charp 133cb93a386Sopenharmony_cipng_format_number(png_const_charp start, png_charp end, int format, 134cb93a386Sopenharmony_ci png_alloc_size_t number) 135cb93a386Sopenharmony_ci{ 136cb93a386Sopenharmony_ci int count = 0; /* number of digits output */ 137cb93a386Sopenharmony_ci int mincount = 1; /* minimum number required */ 138cb93a386Sopenharmony_ci int output = 0; /* digit output (for the fixed point format) */ 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci *--end = '\0'; 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci /* This is written so that the loop always runs at least once, even with 143cb93a386Sopenharmony_ci * number zero. 144cb93a386Sopenharmony_ci */ 145cb93a386Sopenharmony_ci while (end > start && (number != 0 || count < mincount)) 146cb93a386Sopenharmony_ci { 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci static const char digits[] = "0123456789ABCDEF"; 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci switch (format) 151cb93a386Sopenharmony_ci { 152cb93a386Sopenharmony_ci case PNG_NUMBER_FORMAT_fixed: 153cb93a386Sopenharmony_ci /* Needs five digits (the fraction) */ 154cb93a386Sopenharmony_ci mincount = 5; 155cb93a386Sopenharmony_ci if (output != 0 || number % 10 != 0) 156cb93a386Sopenharmony_ci { 157cb93a386Sopenharmony_ci *--end = digits[number % 10]; 158cb93a386Sopenharmony_ci output = 1; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci number /= 10; 161cb93a386Sopenharmony_ci break; 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci case PNG_NUMBER_FORMAT_02u: 164cb93a386Sopenharmony_ci /* Expects at least 2 digits. */ 165cb93a386Sopenharmony_ci mincount = 2; 166cb93a386Sopenharmony_ci /* FALLTHROUGH */ 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci case PNG_NUMBER_FORMAT_u: 169cb93a386Sopenharmony_ci *--end = digits[number % 10]; 170cb93a386Sopenharmony_ci number /= 10; 171cb93a386Sopenharmony_ci break; 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci case PNG_NUMBER_FORMAT_02x: 174cb93a386Sopenharmony_ci /* This format expects at least two digits */ 175cb93a386Sopenharmony_ci mincount = 2; 176cb93a386Sopenharmony_ci /* FALLTHROUGH */ 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci case PNG_NUMBER_FORMAT_x: 179cb93a386Sopenharmony_ci *--end = digits[number & 0xf]; 180cb93a386Sopenharmony_ci number >>= 4; 181cb93a386Sopenharmony_ci break; 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci default: /* an error */ 184cb93a386Sopenharmony_ci number = 0; 185cb93a386Sopenharmony_ci break; 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci /* Keep track of the number of digits added */ 189cb93a386Sopenharmony_ci ++count; 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci /* Float a fixed number here: */ 192cb93a386Sopenharmony_ci if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start)) 193cb93a386Sopenharmony_ci { 194cb93a386Sopenharmony_ci /* End of the fraction, but maybe nothing was output? In that case 195cb93a386Sopenharmony_ci * drop the decimal point. If the number is a true zero handle that 196cb93a386Sopenharmony_ci * here. 197cb93a386Sopenharmony_ci */ 198cb93a386Sopenharmony_ci if (output != 0) 199cb93a386Sopenharmony_ci *--end = '.'; 200cb93a386Sopenharmony_ci else if (number == 0) /* and !output */ 201cb93a386Sopenharmony_ci *--end = '0'; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci return end; 206cb93a386Sopenharmony_ci} 207cb93a386Sopenharmony_ci#endif 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED 210cb93a386Sopenharmony_ci/* This function is called whenever there is a non-fatal error. This function 211cb93a386Sopenharmony_ci * should not be changed. If there is a need to handle warnings differently, 212cb93a386Sopenharmony_ci * you should supply a replacement warning function and use 213cb93a386Sopenharmony_ci * png_set_error_fn() to replace the warning function at run-time. 214cb93a386Sopenharmony_ci */ 215cb93a386Sopenharmony_civoid PNGAPI 216cb93a386Sopenharmony_cipng_warning(png_const_structrp png_ptr, png_const_charp warning_message) 217cb93a386Sopenharmony_ci{ 218cb93a386Sopenharmony_ci int offset = 0; 219cb93a386Sopenharmony_ci if (png_ptr != NULL) 220cb93a386Sopenharmony_ci { 221cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED 222cb93a386Sopenharmony_ci if ((png_ptr->flags & 223cb93a386Sopenharmony_ci (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) 224cb93a386Sopenharmony_ci#endif 225cb93a386Sopenharmony_ci { 226cb93a386Sopenharmony_ci if (*warning_message == PNG_LITERAL_SHARP) 227cb93a386Sopenharmony_ci { 228cb93a386Sopenharmony_ci for (offset = 1; offset < 15; offset++) 229cb93a386Sopenharmony_ci if (warning_message[offset] == ' ') 230cb93a386Sopenharmony_ci break; 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci } 234cb93a386Sopenharmony_ci if (png_ptr != NULL && png_ptr->warning_fn != NULL) 235cb93a386Sopenharmony_ci (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), 236cb93a386Sopenharmony_ci warning_message + offset); 237cb93a386Sopenharmony_ci else 238cb93a386Sopenharmony_ci png_default_warning(png_ptr, warning_message + offset); 239cb93a386Sopenharmony_ci} 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci/* These functions support 'formatted' warning messages with up to 242cb93a386Sopenharmony_ci * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter 243cb93a386Sopenharmony_ci * is introduced by @<number>, where 'number' starts at 1. This follows the 244cb93a386Sopenharmony_ci * standard established by X/Open for internationalizable error messages. 245cb93a386Sopenharmony_ci */ 246cb93a386Sopenharmony_civoid 247cb93a386Sopenharmony_cipng_warning_parameter(png_warning_parameters p, int number, 248cb93a386Sopenharmony_ci png_const_charp string) 249cb93a386Sopenharmony_ci{ 250cb93a386Sopenharmony_ci if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) 251cb93a386Sopenharmony_ci (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); 252cb93a386Sopenharmony_ci} 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_civoid 255cb93a386Sopenharmony_cipng_warning_parameter_unsigned(png_warning_parameters p, int number, int format, 256cb93a386Sopenharmony_ci png_alloc_size_t value) 257cb93a386Sopenharmony_ci{ 258cb93a386Sopenharmony_ci char buffer[PNG_NUMBER_BUFFER_SIZE]; 259cb93a386Sopenharmony_ci png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); 260cb93a386Sopenharmony_ci} 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_civoid 263cb93a386Sopenharmony_cipng_warning_parameter_signed(png_warning_parameters p, int number, int format, 264cb93a386Sopenharmony_ci png_int_32 value) 265cb93a386Sopenharmony_ci{ 266cb93a386Sopenharmony_ci png_alloc_size_t u; 267cb93a386Sopenharmony_ci png_charp str; 268cb93a386Sopenharmony_ci char buffer[PNG_NUMBER_BUFFER_SIZE]; 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci /* Avoid overflow by doing the negate in a png_alloc_size_t: */ 271cb93a386Sopenharmony_ci u = (png_alloc_size_t)value; 272cb93a386Sopenharmony_ci if (value < 0) 273cb93a386Sopenharmony_ci u = ~u + 1; 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci str = PNG_FORMAT_NUMBER(buffer, format, u); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci if (value < 0 && str > buffer) 278cb93a386Sopenharmony_ci *--str = '-'; 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci png_warning_parameter(p, number, str); 281cb93a386Sopenharmony_ci} 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_civoid 284cb93a386Sopenharmony_cipng_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, 285cb93a386Sopenharmony_ci png_const_charp message) 286cb93a386Sopenharmony_ci{ 287cb93a386Sopenharmony_ci /* The internal buffer is just 192 bytes - enough for all our messages, 288cb93a386Sopenharmony_ci * overflow doesn't happen because this code checks! If someone figures 289cb93a386Sopenharmony_ci * out how to send us a message longer than 192 bytes, all that will 290cb93a386Sopenharmony_ci * happen is that the message will be truncated appropriately. 291cb93a386Sopenharmony_ci */ 292cb93a386Sopenharmony_ci size_t i = 0; /* Index in the msg[] buffer: */ 293cb93a386Sopenharmony_ci char msg[192]; 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci /* Each iteration through the following loop writes at most one character 296cb93a386Sopenharmony_ci * to msg[i++] then returns here to validate that there is still space for 297cb93a386Sopenharmony_ci * the trailing '\0'. It may (in the case of a parameter) read more than 298cb93a386Sopenharmony_ci * one character from message[]; it must check for '\0' and continue to the 299cb93a386Sopenharmony_ci * test if it finds the end of string. 300cb93a386Sopenharmony_ci */ 301cb93a386Sopenharmony_ci while (i<(sizeof msg)-1 && *message != '\0') 302cb93a386Sopenharmony_ci { 303cb93a386Sopenharmony_ci /* '@' at end of string is now just printed (previously it was skipped); 304cb93a386Sopenharmony_ci * it is an error in the calling code to terminate the string with @. 305cb93a386Sopenharmony_ci */ 306cb93a386Sopenharmony_ci if (p != NULL && *message == '@' && message[1] != '\0') 307cb93a386Sopenharmony_ci { 308cb93a386Sopenharmony_ci int parameter_char = *++message; /* Consume the '@' */ 309cb93a386Sopenharmony_ci static const char valid_parameters[] = "123456789"; 310cb93a386Sopenharmony_ci int parameter = 0; 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_ci /* Search for the parameter digit, the index in the string is the 313cb93a386Sopenharmony_ci * parameter to use. 314cb93a386Sopenharmony_ci */ 315cb93a386Sopenharmony_ci while (valid_parameters[parameter] != parameter_char && 316cb93a386Sopenharmony_ci valid_parameters[parameter] != '\0') 317cb93a386Sopenharmony_ci ++parameter; 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ci /* If the parameter digit is out of range it will just get printed. */ 320cb93a386Sopenharmony_ci if (parameter < PNG_WARNING_PARAMETER_COUNT) 321cb93a386Sopenharmony_ci { 322cb93a386Sopenharmony_ci /* Append this parameter */ 323cb93a386Sopenharmony_ci png_const_charp parm = p[parameter]; 324cb93a386Sopenharmony_ci png_const_charp pend = p[parameter] + (sizeof p[parameter]); 325cb93a386Sopenharmony_ci 326cb93a386Sopenharmony_ci /* No need to copy the trailing '\0' here, but there is no guarantee 327cb93a386Sopenharmony_ci * that parm[] has been initialized, so there is no guarantee of a 328cb93a386Sopenharmony_ci * trailing '\0': 329cb93a386Sopenharmony_ci */ 330cb93a386Sopenharmony_ci while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend) 331cb93a386Sopenharmony_ci msg[i++] = *parm++; 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_ci /* Consume the parameter digit too: */ 334cb93a386Sopenharmony_ci ++message; 335cb93a386Sopenharmony_ci continue; 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ci /* else not a parameter and there is a character after the @ sign; just 339cb93a386Sopenharmony_ci * copy that. This is known not to be '\0' because of the test above. 340cb93a386Sopenharmony_ci */ 341cb93a386Sopenharmony_ci } 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci /* At this point *message can't be '\0', even in the bad parameter case 344cb93a386Sopenharmony_ci * above where there is a lone '@' at the end of the message string. 345cb93a386Sopenharmony_ci */ 346cb93a386Sopenharmony_ci msg[i++] = *message++; 347cb93a386Sopenharmony_ci } 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ci /* i is always less than (sizeof msg), so: */ 350cb93a386Sopenharmony_ci msg[i] = '\0'; 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_ci /* And this is the formatted message. It may be larger than 353cb93a386Sopenharmony_ci * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these 354cb93a386Sopenharmony_ci * are not (currently) formatted. 355cb93a386Sopenharmony_ci */ 356cb93a386Sopenharmony_ci png_warning(png_ptr, msg); 357cb93a386Sopenharmony_ci} 358cb93a386Sopenharmony_ci#endif /* WARNINGS */ 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ci#ifdef PNG_BENIGN_ERRORS_SUPPORTED 361cb93a386Sopenharmony_civoid PNGAPI 362cb93a386Sopenharmony_cipng_benign_error(png_const_structrp png_ptr, png_const_charp error_message) 363cb93a386Sopenharmony_ci{ 364cb93a386Sopenharmony_ci if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) 365cb93a386Sopenharmony_ci { 366cb93a386Sopenharmony_ci# ifdef PNG_READ_SUPPORTED 367cb93a386Sopenharmony_ci if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && 368cb93a386Sopenharmony_ci png_ptr->chunk_name != 0) 369cb93a386Sopenharmony_ci png_chunk_warning(png_ptr, error_message); 370cb93a386Sopenharmony_ci else 371cb93a386Sopenharmony_ci# endif 372cb93a386Sopenharmony_ci png_warning(png_ptr, error_message); 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci 375cb93a386Sopenharmony_ci else 376cb93a386Sopenharmony_ci { 377cb93a386Sopenharmony_ci# ifdef PNG_READ_SUPPORTED 378cb93a386Sopenharmony_ci if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && 379cb93a386Sopenharmony_ci png_ptr->chunk_name != 0) 380cb93a386Sopenharmony_ci png_chunk_error(png_ptr, error_message); 381cb93a386Sopenharmony_ci else 382cb93a386Sopenharmony_ci# endif 383cb93a386Sopenharmony_ci png_error(png_ptr, error_message); 384cb93a386Sopenharmony_ci } 385cb93a386Sopenharmony_ci 386cb93a386Sopenharmony_ci# ifndef PNG_ERROR_TEXT_SUPPORTED 387cb93a386Sopenharmony_ci PNG_UNUSED(error_message) 388cb93a386Sopenharmony_ci# endif 389cb93a386Sopenharmony_ci} 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_civoid /* PRIVATE */ 392cb93a386Sopenharmony_cipng_app_warning(png_const_structrp png_ptr, png_const_charp error_message) 393cb93a386Sopenharmony_ci{ 394cb93a386Sopenharmony_ci if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0) 395cb93a386Sopenharmony_ci png_warning(png_ptr, error_message); 396cb93a386Sopenharmony_ci else 397cb93a386Sopenharmony_ci png_error(png_ptr, error_message); 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_ci# ifndef PNG_ERROR_TEXT_SUPPORTED 400cb93a386Sopenharmony_ci PNG_UNUSED(error_message) 401cb93a386Sopenharmony_ci# endif 402cb93a386Sopenharmony_ci} 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_civoid /* PRIVATE */ 405cb93a386Sopenharmony_cipng_app_error(png_const_structrp png_ptr, png_const_charp error_message) 406cb93a386Sopenharmony_ci{ 407cb93a386Sopenharmony_ci if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0) 408cb93a386Sopenharmony_ci png_warning(png_ptr, error_message); 409cb93a386Sopenharmony_ci else 410cb93a386Sopenharmony_ci png_error(png_ptr, error_message); 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ci# ifndef PNG_ERROR_TEXT_SUPPORTED 413cb93a386Sopenharmony_ci PNG_UNUSED(error_message) 414cb93a386Sopenharmony_ci# endif 415cb93a386Sopenharmony_ci} 416cb93a386Sopenharmony_ci#endif /* BENIGN_ERRORS */ 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */ 419cb93a386Sopenharmony_ci#if defined(PNG_WARNINGS_SUPPORTED) || \ 420cb93a386Sopenharmony_ci (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)) 421cb93a386Sopenharmony_ci/* These utilities are used internally to build an error message that relates 422cb93a386Sopenharmony_ci * to the current chunk. The chunk name comes from png_ptr->chunk_name, 423cb93a386Sopenharmony_ci * which is used to prefix the message. The message is limited in length 424cb93a386Sopenharmony_ci * to 63 bytes. The name characters are output as hex digits wrapped in [] 425cb93a386Sopenharmony_ci * if the character is invalid. 426cb93a386Sopenharmony_ci */ 427cb93a386Sopenharmony_ci#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) 428cb93a386Sopenharmony_cistatic const char png_digit[16] = { 429cb93a386Sopenharmony_ci '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 430cb93a386Sopenharmony_ci 'A', 'B', 'C', 'D', 'E', 'F' 431cb93a386Sopenharmony_ci}; 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_cistatic void /* PRIVATE */ 434cb93a386Sopenharmony_cipng_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp 435cb93a386Sopenharmony_ci error_message) 436cb93a386Sopenharmony_ci{ 437cb93a386Sopenharmony_ci png_uint_32 chunk_name = png_ptr->chunk_name; 438cb93a386Sopenharmony_ci int iout = 0, ishift = 24; 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_ci while (ishift >= 0) 441cb93a386Sopenharmony_ci { 442cb93a386Sopenharmony_ci int c = (int)(chunk_name >> ishift) & 0xff; 443cb93a386Sopenharmony_ci 444cb93a386Sopenharmony_ci ishift -= 8; 445cb93a386Sopenharmony_ci if (isnonalpha(c) != 0) 446cb93a386Sopenharmony_ci { 447cb93a386Sopenharmony_ci buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; 448cb93a386Sopenharmony_ci buffer[iout++] = png_digit[(c & 0xf0) >> 4]; 449cb93a386Sopenharmony_ci buffer[iout++] = png_digit[c & 0x0f]; 450cb93a386Sopenharmony_ci buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; 451cb93a386Sopenharmony_ci } 452cb93a386Sopenharmony_ci 453cb93a386Sopenharmony_ci else 454cb93a386Sopenharmony_ci { 455cb93a386Sopenharmony_ci buffer[iout++] = (char)c; 456cb93a386Sopenharmony_ci } 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci 459cb93a386Sopenharmony_ci if (error_message == NULL) 460cb93a386Sopenharmony_ci buffer[iout] = '\0'; 461cb93a386Sopenharmony_ci 462cb93a386Sopenharmony_ci else 463cb93a386Sopenharmony_ci { 464cb93a386Sopenharmony_ci int iin = 0; 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci buffer[iout++] = ':'; 467cb93a386Sopenharmony_ci buffer[iout++] = ' '; 468cb93a386Sopenharmony_ci 469cb93a386Sopenharmony_ci while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') 470cb93a386Sopenharmony_ci buffer[iout++] = error_message[iin++]; 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ 473cb93a386Sopenharmony_ci buffer[iout] = '\0'; 474cb93a386Sopenharmony_ci } 475cb93a386Sopenharmony_ci} 476cb93a386Sopenharmony_ci#endif /* WARNINGS || ERROR_TEXT */ 477cb93a386Sopenharmony_ci 478cb93a386Sopenharmony_ci#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) 479cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI 480cb93a386Sopenharmony_cipng_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), 481cb93a386Sopenharmony_ci PNG_NORETURN) 482cb93a386Sopenharmony_ci{ 483cb93a386Sopenharmony_ci char msg[18+PNG_MAX_ERROR_TEXT]; 484cb93a386Sopenharmony_ci if (png_ptr == NULL) 485cb93a386Sopenharmony_ci png_error(png_ptr, error_message); 486cb93a386Sopenharmony_ci 487cb93a386Sopenharmony_ci else 488cb93a386Sopenharmony_ci { 489cb93a386Sopenharmony_ci png_format_buffer(png_ptr, msg, error_message); 490cb93a386Sopenharmony_ci png_error(png_ptr, msg); 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci} 493cb93a386Sopenharmony_ci#endif /* READ && ERROR_TEXT */ 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED 496cb93a386Sopenharmony_civoid PNGAPI 497cb93a386Sopenharmony_cipng_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) 498cb93a386Sopenharmony_ci{ 499cb93a386Sopenharmony_ci char msg[18+PNG_MAX_ERROR_TEXT]; 500cb93a386Sopenharmony_ci if (png_ptr == NULL) 501cb93a386Sopenharmony_ci png_warning(png_ptr, warning_message); 502cb93a386Sopenharmony_ci 503cb93a386Sopenharmony_ci else 504cb93a386Sopenharmony_ci { 505cb93a386Sopenharmony_ci png_format_buffer(png_ptr, msg, warning_message); 506cb93a386Sopenharmony_ci png_warning(png_ptr, msg); 507cb93a386Sopenharmony_ci } 508cb93a386Sopenharmony_ci} 509cb93a386Sopenharmony_ci#endif /* WARNINGS */ 510cb93a386Sopenharmony_ci 511cb93a386Sopenharmony_ci#ifdef PNG_READ_SUPPORTED 512cb93a386Sopenharmony_ci#ifdef PNG_BENIGN_ERRORS_SUPPORTED 513cb93a386Sopenharmony_civoid PNGAPI 514cb93a386Sopenharmony_cipng_chunk_benign_error(png_const_structrp png_ptr, png_const_charp 515cb93a386Sopenharmony_ci error_message) 516cb93a386Sopenharmony_ci{ 517cb93a386Sopenharmony_ci if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) 518cb93a386Sopenharmony_ci png_chunk_warning(png_ptr, error_message); 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci else 521cb93a386Sopenharmony_ci png_chunk_error(png_ptr, error_message); 522cb93a386Sopenharmony_ci 523cb93a386Sopenharmony_ci# ifndef PNG_ERROR_TEXT_SUPPORTED 524cb93a386Sopenharmony_ci PNG_UNUSED(error_message) 525cb93a386Sopenharmony_ci# endif 526cb93a386Sopenharmony_ci} 527cb93a386Sopenharmony_ci#endif 528cb93a386Sopenharmony_ci#endif /* READ */ 529cb93a386Sopenharmony_ci 530cb93a386Sopenharmony_civoid /* PRIVATE */ 531cb93a386Sopenharmony_cipng_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) 532cb93a386Sopenharmony_ci{ 533cb93a386Sopenharmony_ci# ifndef PNG_WARNINGS_SUPPORTED 534cb93a386Sopenharmony_ci PNG_UNUSED(message) 535cb93a386Sopenharmony_ci# endif 536cb93a386Sopenharmony_ci 537cb93a386Sopenharmony_ci /* This is always supported, but for just read or just write it 538cb93a386Sopenharmony_ci * unconditionally does the right thing. 539cb93a386Sopenharmony_ci */ 540cb93a386Sopenharmony_ci# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) 541cb93a386Sopenharmony_ci if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) 542cb93a386Sopenharmony_ci# endif 543cb93a386Sopenharmony_ci 544cb93a386Sopenharmony_ci# ifdef PNG_READ_SUPPORTED 545cb93a386Sopenharmony_ci { 546cb93a386Sopenharmony_ci if (error < PNG_CHUNK_ERROR) 547cb93a386Sopenharmony_ci png_chunk_warning(png_ptr, message); 548cb93a386Sopenharmony_ci 549cb93a386Sopenharmony_ci else 550cb93a386Sopenharmony_ci png_chunk_benign_error(png_ptr, message); 551cb93a386Sopenharmony_ci } 552cb93a386Sopenharmony_ci# endif 553cb93a386Sopenharmony_ci 554cb93a386Sopenharmony_ci# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) 555cb93a386Sopenharmony_ci else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) 556cb93a386Sopenharmony_ci# endif 557cb93a386Sopenharmony_ci 558cb93a386Sopenharmony_ci# ifdef PNG_WRITE_SUPPORTED 559cb93a386Sopenharmony_ci { 560cb93a386Sopenharmony_ci if (error < PNG_CHUNK_WRITE_ERROR) 561cb93a386Sopenharmony_ci png_app_warning(png_ptr, message); 562cb93a386Sopenharmony_ci 563cb93a386Sopenharmony_ci else 564cb93a386Sopenharmony_ci png_app_error(png_ptr, message); 565cb93a386Sopenharmony_ci } 566cb93a386Sopenharmony_ci# endif 567cb93a386Sopenharmony_ci} 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci#ifdef PNG_ERROR_TEXT_SUPPORTED 570cb93a386Sopenharmony_ci#ifdef PNG_FLOATING_POINT_SUPPORTED 571cb93a386Sopenharmony_ciPNG_FUNCTION(void, 572cb93a386Sopenharmony_cipng_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) 573cb93a386Sopenharmony_ci{ 574cb93a386Sopenharmony_ci# define fixed_message "fixed point overflow in " 575cb93a386Sopenharmony_ci# define fixed_message_ln ((sizeof fixed_message)-1) 576cb93a386Sopenharmony_ci unsigned int iin; 577cb93a386Sopenharmony_ci char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; 578cb93a386Sopenharmony_ci memcpy(msg, fixed_message, fixed_message_ln); 579cb93a386Sopenharmony_ci iin = 0; 580cb93a386Sopenharmony_ci if (name != NULL) 581cb93a386Sopenharmony_ci while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) 582cb93a386Sopenharmony_ci { 583cb93a386Sopenharmony_ci msg[fixed_message_ln + iin] = name[iin]; 584cb93a386Sopenharmony_ci ++iin; 585cb93a386Sopenharmony_ci } 586cb93a386Sopenharmony_ci msg[fixed_message_ln + iin] = 0; 587cb93a386Sopenharmony_ci png_error(png_ptr, msg); 588cb93a386Sopenharmony_ci} 589cb93a386Sopenharmony_ci#endif 590cb93a386Sopenharmony_ci#endif 591cb93a386Sopenharmony_ci 592cb93a386Sopenharmony_ci#ifdef PNG_SETJMP_SUPPORTED 593cb93a386Sopenharmony_ci/* This API only exists if ANSI-C style error handling is used, 594cb93a386Sopenharmony_ci * otherwise it is necessary for png_default_error to be overridden. 595cb93a386Sopenharmony_ci */ 596cb93a386Sopenharmony_cijmp_buf* PNGAPI 597cb93a386Sopenharmony_cipng_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, 598cb93a386Sopenharmony_ci size_t jmp_buf_size) 599cb93a386Sopenharmony_ci{ 600cb93a386Sopenharmony_ci /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value 601cb93a386Sopenharmony_ci * and it must not change after that. Libpng doesn't care how big the 602cb93a386Sopenharmony_ci * buffer is, just that it doesn't change. 603cb93a386Sopenharmony_ci * 604cb93a386Sopenharmony_ci * If the buffer size is no *larger* than the size of jmp_buf when libpng is 605cb93a386Sopenharmony_ci * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0 606cb93a386Sopenharmony_ci * semantics that this call will not fail. If the size is larger, however, 607cb93a386Sopenharmony_ci * the buffer is allocated and this may fail, causing the function to return 608cb93a386Sopenharmony_ci * NULL. 609cb93a386Sopenharmony_ci */ 610cb93a386Sopenharmony_ci if (png_ptr == NULL) 611cb93a386Sopenharmony_ci return NULL; 612cb93a386Sopenharmony_ci 613cb93a386Sopenharmony_ci if (png_ptr->jmp_buf_ptr == NULL) 614cb93a386Sopenharmony_ci { 615cb93a386Sopenharmony_ci png_ptr->jmp_buf_size = 0; /* not allocated */ 616cb93a386Sopenharmony_ci 617cb93a386Sopenharmony_ci if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local)) 618cb93a386Sopenharmony_ci png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; 619cb93a386Sopenharmony_ci 620cb93a386Sopenharmony_ci else 621cb93a386Sopenharmony_ci { 622cb93a386Sopenharmony_ci png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, 623cb93a386Sopenharmony_ci png_malloc_warn(png_ptr, jmp_buf_size)); 624cb93a386Sopenharmony_ci 625cb93a386Sopenharmony_ci if (png_ptr->jmp_buf_ptr == NULL) 626cb93a386Sopenharmony_ci return NULL; /* new NULL return on OOM */ 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_ci png_ptr->jmp_buf_size = jmp_buf_size; 629cb93a386Sopenharmony_ci } 630cb93a386Sopenharmony_ci } 631cb93a386Sopenharmony_ci 632cb93a386Sopenharmony_ci else /* Already allocated: check the size */ 633cb93a386Sopenharmony_ci { 634cb93a386Sopenharmony_ci size_t size = png_ptr->jmp_buf_size; 635cb93a386Sopenharmony_ci 636cb93a386Sopenharmony_ci if (size == 0) 637cb93a386Sopenharmony_ci { 638cb93a386Sopenharmony_ci size = (sizeof png_ptr->jmp_buf_local); 639cb93a386Sopenharmony_ci if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local) 640cb93a386Sopenharmony_ci { 641cb93a386Sopenharmony_ci /* This is an internal error in libpng: somehow we have been left 642cb93a386Sopenharmony_ci * with a stack allocated jmp_buf when the application regained 643cb93a386Sopenharmony_ci * control. It's always possible to fix this up, but for the moment 644cb93a386Sopenharmony_ci * this is a png_error because that makes it easy to detect. 645cb93a386Sopenharmony_ci */ 646cb93a386Sopenharmony_ci png_error(png_ptr, "Libpng jmp_buf still allocated"); 647cb93a386Sopenharmony_ci /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */ 648cb93a386Sopenharmony_ci } 649cb93a386Sopenharmony_ci } 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_ci if (size != jmp_buf_size) 652cb93a386Sopenharmony_ci { 653cb93a386Sopenharmony_ci png_warning(png_ptr, "Application jmp_buf size changed"); 654cb93a386Sopenharmony_ci return NULL; /* caller will probably crash: no choice here */ 655cb93a386Sopenharmony_ci } 656cb93a386Sopenharmony_ci } 657cb93a386Sopenharmony_ci 658cb93a386Sopenharmony_ci /* Finally fill in the function, now we have a satisfactory buffer. It is 659cb93a386Sopenharmony_ci * valid to change the function on every call. 660cb93a386Sopenharmony_ci */ 661cb93a386Sopenharmony_ci png_ptr->longjmp_fn = longjmp_fn; 662cb93a386Sopenharmony_ci return png_ptr->jmp_buf_ptr; 663cb93a386Sopenharmony_ci} 664cb93a386Sopenharmony_ci 665cb93a386Sopenharmony_civoid /* PRIVATE */ 666cb93a386Sopenharmony_cipng_free_jmpbuf(png_structrp png_ptr) 667cb93a386Sopenharmony_ci{ 668cb93a386Sopenharmony_ci if (png_ptr != NULL) 669cb93a386Sopenharmony_ci { 670cb93a386Sopenharmony_ci jmp_buf *jb = png_ptr->jmp_buf_ptr; 671cb93a386Sopenharmony_ci 672cb93a386Sopenharmony_ci /* A size of 0 is used to indicate a local, stack, allocation of the 673cb93a386Sopenharmony_ci * pointer; used here and in png.c 674cb93a386Sopenharmony_ci */ 675cb93a386Sopenharmony_ci if (jb != NULL && png_ptr->jmp_buf_size > 0) 676cb93a386Sopenharmony_ci { 677cb93a386Sopenharmony_ci 678cb93a386Sopenharmony_ci /* This stuff is so that a failure to free the error control structure 679cb93a386Sopenharmony_ci * does not leave libpng in a state with no valid error handling: the 680cb93a386Sopenharmony_ci * free always succeeds, if there is an error it gets ignored. 681cb93a386Sopenharmony_ci */ 682cb93a386Sopenharmony_ci if (jb != &png_ptr->jmp_buf_local) 683cb93a386Sopenharmony_ci { 684cb93a386Sopenharmony_ci /* Make an internal, libpng, jmp_buf to return here */ 685cb93a386Sopenharmony_ci jmp_buf free_jmp_buf; 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_ci if (!setjmp(free_jmp_buf)) 688cb93a386Sopenharmony_ci { 689cb93a386Sopenharmony_ci png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */ 690cb93a386Sopenharmony_ci png_ptr->jmp_buf_size = 0; /* stack allocation */ 691cb93a386Sopenharmony_ci png_ptr->longjmp_fn = longjmp; 692cb93a386Sopenharmony_ci png_free(png_ptr, jb); /* Return to setjmp on error */ 693cb93a386Sopenharmony_ci } 694cb93a386Sopenharmony_ci } 695cb93a386Sopenharmony_ci } 696cb93a386Sopenharmony_ci 697cb93a386Sopenharmony_ci /* *Always* cancel everything out: */ 698cb93a386Sopenharmony_ci png_ptr->jmp_buf_size = 0; 699cb93a386Sopenharmony_ci png_ptr->jmp_buf_ptr = NULL; 700cb93a386Sopenharmony_ci png_ptr->longjmp_fn = 0; 701cb93a386Sopenharmony_ci } 702cb93a386Sopenharmony_ci} 703cb93a386Sopenharmony_ci#endif 704cb93a386Sopenharmony_ci 705cb93a386Sopenharmony_ci/* This is the default error handling function. Note that replacements for 706cb93a386Sopenharmony_ci * this function MUST NOT RETURN, or the program will likely crash. This 707cb93a386Sopenharmony_ci * function is used by default, or if the program supplies NULL for the 708cb93a386Sopenharmony_ci * error function pointer in png_set_error_fn(). 709cb93a386Sopenharmony_ci */ 710cb93a386Sopenharmony_cistatic PNG_FUNCTION(void /* PRIVATE */, 711cb93a386Sopenharmony_cipng_default_error,(png_const_structrp png_ptr, png_const_charp error_message), 712cb93a386Sopenharmony_ci PNG_NORETURN) 713cb93a386Sopenharmony_ci{ 714cb93a386Sopenharmony_ci#ifdef PNG_CONSOLE_IO_SUPPORTED 715cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED 716cb93a386Sopenharmony_ci /* Check on NULL only added in 1.5.4 */ 717cb93a386Sopenharmony_ci if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) 718cb93a386Sopenharmony_ci { 719cb93a386Sopenharmony_ci /* Strip "#nnnn " from beginning of error message. */ 720cb93a386Sopenharmony_ci int offset; 721cb93a386Sopenharmony_ci char error_number[16]; 722cb93a386Sopenharmony_ci for (offset = 0; offset<15; offset++) 723cb93a386Sopenharmony_ci { 724cb93a386Sopenharmony_ci error_number[offset] = error_message[offset + 1]; 725cb93a386Sopenharmony_ci if (error_message[offset] == ' ') 726cb93a386Sopenharmony_ci break; 727cb93a386Sopenharmony_ci } 728cb93a386Sopenharmony_ci 729cb93a386Sopenharmony_ci if ((offset > 1) && (offset < 15)) 730cb93a386Sopenharmony_ci { 731cb93a386Sopenharmony_ci error_number[offset - 1] = '\0'; 732cb93a386Sopenharmony_ci fprintf(stderr, "libpng error no. %s: %s", 733cb93a386Sopenharmony_ci error_number, error_message + offset + 1); 734cb93a386Sopenharmony_ci fprintf(stderr, PNG_STRING_NEWLINE); 735cb93a386Sopenharmony_ci } 736cb93a386Sopenharmony_ci 737cb93a386Sopenharmony_ci else 738cb93a386Sopenharmony_ci { 739cb93a386Sopenharmony_ci fprintf(stderr, "libpng error: %s, offset=%d", 740cb93a386Sopenharmony_ci error_message, offset); 741cb93a386Sopenharmony_ci fprintf(stderr, PNG_STRING_NEWLINE); 742cb93a386Sopenharmony_ci } 743cb93a386Sopenharmony_ci } 744cb93a386Sopenharmony_ci else 745cb93a386Sopenharmony_ci#endif 746cb93a386Sopenharmony_ci { 747cb93a386Sopenharmony_ci fprintf(stderr, "libpng error: %s", error_message ? error_message : 748cb93a386Sopenharmony_ci "undefined"); 749cb93a386Sopenharmony_ci fprintf(stderr, PNG_STRING_NEWLINE); 750cb93a386Sopenharmony_ci } 751cb93a386Sopenharmony_ci#else 752cb93a386Sopenharmony_ci PNG_UNUSED(error_message) /* Make compiler happy */ 753cb93a386Sopenharmony_ci#endif 754cb93a386Sopenharmony_ci png_longjmp(png_ptr, 1); 755cb93a386Sopenharmony_ci} 756cb93a386Sopenharmony_ci 757cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI 758cb93a386Sopenharmony_cipng_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) 759cb93a386Sopenharmony_ci{ 760cb93a386Sopenharmony_ci#ifdef PNG_SETJMP_SUPPORTED 761cb93a386Sopenharmony_ci if (png_ptr != NULL && png_ptr->longjmp_fn != NULL && 762cb93a386Sopenharmony_ci png_ptr->jmp_buf_ptr != NULL) 763cb93a386Sopenharmony_ci png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val); 764cb93a386Sopenharmony_ci#else 765cb93a386Sopenharmony_ci PNG_UNUSED(png_ptr) 766cb93a386Sopenharmony_ci PNG_UNUSED(val) 767cb93a386Sopenharmony_ci#endif 768cb93a386Sopenharmony_ci 769cb93a386Sopenharmony_ci /* If control reaches this point, png_longjmp() must not return. The only 770cb93a386Sopenharmony_ci * choice is to terminate the whole process (or maybe the thread); to do 771cb93a386Sopenharmony_ci * this the ANSI-C abort() function is used unless a different method is 772cb93a386Sopenharmony_ci * implemented by overriding the default configuration setting for 773cb93a386Sopenharmony_ci * PNG_ABORT(). 774cb93a386Sopenharmony_ci */ 775cb93a386Sopenharmony_ci PNG_ABORT(); 776cb93a386Sopenharmony_ci} 777cb93a386Sopenharmony_ci 778cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED 779cb93a386Sopenharmony_ci/* This function is called when there is a warning, but the library thinks 780cb93a386Sopenharmony_ci * it can continue anyway. Replacement functions don't have to do anything 781cb93a386Sopenharmony_ci * here if you don't want them to. In the default configuration, png_ptr is 782cb93a386Sopenharmony_ci * not used, but it is passed in case it may be useful. 783cb93a386Sopenharmony_ci */ 784cb93a386Sopenharmony_cistatic void /* PRIVATE */ 785cb93a386Sopenharmony_cipng_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) 786cb93a386Sopenharmony_ci{ 787cb93a386Sopenharmony_ci#ifdef PNG_CONSOLE_IO_SUPPORTED 788cb93a386Sopenharmony_ci# ifdef PNG_ERROR_NUMBERS_SUPPORTED 789cb93a386Sopenharmony_ci if (*warning_message == PNG_LITERAL_SHARP) 790cb93a386Sopenharmony_ci { 791cb93a386Sopenharmony_ci int offset; 792cb93a386Sopenharmony_ci char warning_number[16]; 793cb93a386Sopenharmony_ci for (offset = 0; offset < 15; offset++) 794cb93a386Sopenharmony_ci { 795cb93a386Sopenharmony_ci warning_number[offset] = warning_message[offset + 1]; 796cb93a386Sopenharmony_ci if (warning_message[offset] == ' ') 797cb93a386Sopenharmony_ci break; 798cb93a386Sopenharmony_ci } 799cb93a386Sopenharmony_ci 800cb93a386Sopenharmony_ci if ((offset > 1) && (offset < 15)) 801cb93a386Sopenharmony_ci { 802cb93a386Sopenharmony_ci warning_number[offset + 1] = '\0'; 803cb93a386Sopenharmony_ci fprintf(stderr, "libpng warning no. %s: %s", 804cb93a386Sopenharmony_ci warning_number, warning_message + offset); 805cb93a386Sopenharmony_ci fprintf(stderr, PNG_STRING_NEWLINE); 806cb93a386Sopenharmony_ci } 807cb93a386Sopenharmony_ci 808cb93a386Sopenharmony_ci else 809cb93a386Sopenharmony_ci { 810cb93a386Sopenharmony_ci fprintf(stderr, "libpng warning: %s", 811cb93a386Sopenharmony_ci warning_message); 812cb93a386Sopenharmony_ci fprintf(stderr, PNG_STRING_NEWLINE); 813cb93a386Sopenharmony_ci } 814cb93a386Sopenharmony_ci } 815cb93a386Sopenharmony_ci else 816cb93a386Sopenharmony_ci# endif 817cb93a386Sopenharmony_ci 818cb93a386Sopenharmony_ci { 819cb93a386Sopenharmony_ci fprintf(stderr, "libpng warning: %s", warning_message); 820cb93a386Sopenharmony_ci fprintf(stderr, PNG_STRING_NEWLINE); 821cb93a386Sopenharmony_ci } 822cb93a386Sopenharmony_ci#else 823cb93a386Sopenharmony_ci PNG_UNUSED(warning_message) /* Make compiler happy */ 824cb93a386Sopenharmony_ci#endif 825cb93a386Sopenharmony_ci PNG_UNUSED(png_ptr) /* Make compiler happy */ 826cb93a386Sopenharmony_ci} 827cb93a386Sopenharmony_ci#endif /* WARNINGS */ 828cb93a386Sopenharmony_ci 829cb93a386Sopenharmony_ci/* This function is called when the application wants to use another method 830cb93a386Sopenharmony_ci * of handling errors and warnings. Note that the error function MUST NOT 831cb93a386Sopenharmony_ci * return to the calling routine or serious problems will occur. The return 832cb93a386Sopenharmony_ci * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1) 833cb93a386Sopenharmony_ci */ 834cb93a386Sopenharmony_civoid PNGAPI 835cb93a386Sopenharmony_cipng_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, 836cb93a386Sopenharmony_ci png_error_ptr error_fn, png_error_ptr warning_fn) 837cb93a386Sopenharmony_ci{ 838cb93a386Sopenharmony_ci if (png_ptr == NULL) 839cb93a386Sopenharmony_ci return; 840cb93a386Sopenharmony_ci 841cb93a386Sopenharmony_ci png_ptr->error_ptr = error_ptr; 842cb93a386Sopenharmony_ci png_ptr->error_fn = error_fn; 843cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED 844cb93a386Sopenharmony_ci png_ptr->warning_fn = warning_fn; 845cb93a386Sopenharmony_ci#else 846cb93a386Sopenharmony_ci PNG_UNUSED(warning_fn) 847cb93a386Sopenharmony_ci#endif 848cb93a386Sopenharmony_ci} 849cb93a386Sopenharmony_ci 850cb93a386Sopenharmony_ci 851cb93a386Sopenharmony_ci/* This function returns a pointer to the error_ptr associated with the user 852cb93a386Sopenharmony_ci * functions. The application should free any memory associated with this 853cb93a386Sopenharmony_ci * pointer before png_write_destroy and png_read_destroy are called. 854cb93a386Sopenharmony_ci */ 855cb93a386Sopenharmony_cipng_voidp PNGAPI 856cb93a386Sopenharmony_cipng_get_error_ptr(png_const_structrp png_ptr) 857cb93a386Sopenharmony_ci{ 858cb93a386Sopenharmony_ci if (png_ptr == NULL) 859cb93a386Sopenharmony_ci return NULL; 860cb93a386Sopenharmony_ci 861cb93a386Sopenharmony_ci return ((png_voidp)png_ptr->error_ptr); 862cb93a386Sopenharmony_ci} 863cb93a386Sopenharmony_ci 864cb93a386Sopenharmony_ci 865cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED 866cb93a386Sopenharmony_civoid PNGAPI 867cb93a386Sopenharmony_cipng_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) 868cb93a386Sopenharmony_ci{ 869cb93a386Sopenharmony_ci if (png_ptr != NULL) 870cb93a386Sopenharmony_ci { 871cb93a386Sopenharmony_ci png_ptr->flags &= 872cb93a386Sopenharmony_ci ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | 873cb93a386Sopenharmony_ci PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); 874cb93a386Sopenharmony_ci } 875cb93a386Sopenharmony_ci} 876cb93a386Sopenharmony_ci#endif 877cb93a386Sopenharmony_ci 878cb93a386Sopenharmony_ci#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ 879cb93a386Sopenharmony_ci defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) 880cb93a386Sopenharmony_ci /* Currently the above both depend on SETJMP_SUPPORTED, however it would be 881cb93a386Sopenharmony_ci * possible to implement without setjmp support just so long as there is some 882cb93a386Sopenharmony_ci * way to handle the error return here: 883cb93a386Sopenharmony_ci */ 884cb93a386Sopenharmony_ciPNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI 885cb93a386Sopenharmony_cipng_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), 886cb93a386Sopenharmony_ci PNG_NORETURN) 887cb93a386Sopenharmony_ci{ 888cb93a386Sopenharmony_ci png_const_structrp png_ptr = png_nonconst_ptr; 889cb93a386Sopenharmony_ci png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); 890cb93a386Sopenharmony_ci 891cb93a386Sopenharmony_ci /* An error is always logged here, overwriting anything (typically a warning) 892cb93a386Sopenharmony_ci * that is already there: 893cb93a386Sopenharmony_ci */ 894cb93a386Sopenharmony_ci if (image != NULL) 895cb93a386Sopenharmony_ci { 896cb93a386Sopenharmony_ci png_safecat(image->message, (sizeof image->message), 0, error_message); 897cb93a386Sopenharmony_ci image->warning_or_error |= PNG_IMAGE_ERROR; 898cb93a386Sopenharmony_ci 899cb93a386Sopenharmony_ci /* Retrieve the jmp_buf from within the png_control, making this work for 900cb93a386Sopenharmony_ci * C++ compilation too is pretty tricky: C++ wants a pointer to the first 901cb93a386Sopenharmony_ci * element of a jmp_buf, but C doesn't tell us the type of that. 902cb93a386Sopenharmony_ci */ 903cb93a386Sopenharmony_ci if (image->opaque != NULL && image->opaque->error_buf != NULL) 904cb93a386Sopenharmony_ci longjmp(png_control_jmp_buf(image->opaque), 1); 905cb93a386Sopenharmony_ci 906cb93a386Sopenharmony_ci /* Missing longjmp buffer, the following is to help debugging: */ 907cb93a386Sopenharmony_ci { 908cb93a386Sopenharmony_ci size_t pos = png_safecat(image->message, (sizeof image->message), 0, 909cb93a386Sopenharmony_ci "bad longjmp: "); 910cb93a386Sopenharmony_ci png_safecat(image->message, (sizeof image->message), pos, 911cb93a386Sopenharmony_ci error_message); 912cb93a386Sopenharmony_ci } 913cb93a386Sopenharmony_ci } 914cb93a386Sopenharmony_ci 915cb93a386Sopenharmony_ci /* Here on an internal programming error. */ 916cb93a386Sopenharmony_ci abort(); 917cb93a386Sopenharmony_ci} 918cb93a386Sopenharmony_ci 919cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED 920cb93a386Sopenharmony_civoid /* PRIVATE */ PNGCBAPI 921cb93a386Sopenharmony_cipng_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) 922cb93a386Sopenharmony_ci{ 923cb93a386Sopenharmony_ci png_const_structrp png_ptr = png_nonconst_ptr; 924cb93a386Sopenharmony_ci png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); 925cb93a386Sopenharmony_ci 926cb93a386Sopenharmony_ci /* A warning is only logged if there is no prior warning or error. */ 927cb93a386Sopenharmony_ci if (image->warning_or_error == 0) 928cb93a386Sopenharmony_ci { 929cb93a386Sopenharmony_ci png_safecat(image->message, (sizeof image->message), 0, warning_message); 930cb93a386Sopenharmony_ci image->warning_or_error |= PNG_IMAGE_WARNING; 931cb93a386Sopenharmony_ci } 932cb93a386Sopenharmony_ci} 933cb93a386Sopenharmony_ci#endif 934cb93a386Sopenharmony_ci 935cb93a386Sopenharmony_ciint /* PRIVATE */ 936cb93a386Sopenharmony_cipng_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) 937cb93a386Sopenharmony_ci{ 938cb93a386Sopenharmony_ci volatile png_imagep image = image_in; 939cb93a386Sopenharmony_ci volatile int result; 940cb93a386Sopenharmony_ci volatile png_voidp saved_error_buf; 941cb93a386Sopenharmony_ci jmp_buf safe_jmpbuf; 942cb93a386Sopenharmony_ci 943cb93a386Sopenharmony_ci /* Safely execute function(arg) with png_error returning to this function. */ 944cb93a386Sopenharmony_ci saved_error_buf = image->opaque->error_buf; 945cb93a386Sopenharmony_ci result = setjmp(safe_jmpbuf) == 0; 946cb93a386Sopenharmony_ci 947cb93a386Sopenharmony_ci if (result != 0) 948cb93a386Sopenharmony_ci { 949cb93a386Sopenharmony_ci 950cb93a386Sopenharmony_ci image->opaque->error_buf = safe_jmpbuf; 951cb93a386Sopenharmony_ci result = function(arg); 952cb93a386Sopenharmony_ci } 953cb93a386Sopenharmony_ci 954cb93a386Sopenharmony_ci image->opaque->error_buf = saved_error_buf; 955cb93a386Sopenharmony_ci 956cb93a386Sopenharmony_ci /* And do the cleanup prior to any failure return. */ 957cb93a386Sopenharmony_ci if (result == 0) 958cb93a386Sopenharmony_ci png_image_free(image); 959cb93a386Sopenharmony_ci 960cb93a386Sopenharmony_ci return result; 961cb93a386Sopenharmony_ci} 962cb93a386Sopenharmony_ci#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */ 963cb93a386Sopenharmony_ci#endif /* READ || WRITE */ 964