1 2 /* pngerror.c - stub functions for i/o and memory allocation 3 * 4 * Last changed in libpng 1.2.45 [July 7, 2011] 5 * Copyright (c) 1998-2011 Glenn Randers-Pehrson 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8 * 9 * This code is released under the libpng license. 10 * For conditions of distribution and use, see the disclaimer 11 * and license in png.h 12 * 13 * This file provides a location for all error handling. Users who 14 * need special error handling are expected to write replacement functions 15 * and use png_set_error_fn() to use those functions. See the instructions 16 * at each function. 17 */ 18 19 #define PNG_INTERNAL 20 #define PNG_NO_PEDANTIC_WARNINGS 21 #include "png.h" 22 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) 23 24 static void /* PRIVATE */ 25 png_default_error PNGARG((png_structp png_ptr, 26 png_const_charp error_message)) PNG_NORETURN; 27 #ifdef PNG_WARNINGS_SUPPORTED 28 static void /* PRIVATE */ 29 png_default_warning PNGARG((png_structp png_ptr, 30 png_const_charp warning_message)); 31 #endif /* PNG_WARNINGS_SUPPORTED */ 32 33 /* This function is called whenever there is a fatal error. This function 34 * should not be changed. If there is a need to handle errors differently, 35 * you should supply a replacement error function and use png_set_error_fn() 36 * to replace the error function at run-time. 37 */ 38 #ifdef PNG_ERROR_TEXT_SUPPORTED 39 void PNGAPI 40 png_error(png_structp png_ptr, png_const_charp error_message) 41 { 42 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 43 char msg[16]; 44 if (png_ptr != NULL) 45 { 46 if (png_ptr->flags& 47 (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) 48 { 49 if (*error_message == PNG_LITERAL_SHARP) 50 { 51 /* Strip "#nnnn " from beginning of error message. */ 52 int offset; 53 for (offset = 1; offset<15; offset++) 54 if (error_message[offset] == ' ') 55 break; 56 if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) 57 { 58 int i; 59 for (i = 0; i < offset - 1; i++) 60 msg[i] = error_message[i + 1]; 61 msg[i - 1] = '\0'; 62 error_message = msg; 63 } 64 else 65 error_message += offset; 66 } 67 else 68 { 69 if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) 70 { 71 msg[0] = '0'; 72 msg[1] = '\0'; 73 error_message = msg; 74 } 75 } 76 } 77 } 78 #endif 79 if (png_ptr != NULL && png_ptr->error_fn != NULL) 80 (*(png_ptr->error_fn))(png_ptr, error_message); 81 82 /* If the custom handler doesn't exist, or if it returns, 83 use the default handler, which will not return. */ 84 png_default_error(png_ptr, error_message); 85 } 86 #else 87 void PNGAPI 88 png_err(png_structp png_ptr) 89 { 90 /* Prior to 1.2.45 the error_fn received a NULL pointer, expressed 91 * erroneously as '\0', instead of the empty string "". This was 92 * apparently an error, introduced in libpng-1.2.20, and png_default_error 93 * will crash in this case. 94 */ 95 if (png_ptr != NULL && png_ptr->error_fn != NULL) 96 (*(png_ptr->error_fn))(png_ptr, ""); 97 98 /* If the custom handler doesn't exist, or if it returns, 99 use the default handler, which will not return. */ 100 png_default_error(png_ptr, ""); 101 } 102 #endif /* PNG_ERROR_TEXT_SUPPORTED */ 103 104 #ifdef PNG_WARNINGS_SUPPORTED 105 /* This function is called whenever there is a non-fatal error. This function 106 * should not be changed. If there is a need to handle warnings differently, 107 * you should supply a replacement warning function and use 108 * png_set_error_fn() to replace the warning function at run-time. 109 */ 110 void PNGAPI 111 png_warning(png_structp png_ptr, png_const_charp warning_message) 112 { 113 int offset = 0; 114 if (png_ptr != NULL) 115 { 116 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 117 if (png_ptr->flags& 118 (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) 119 #endif 120 { 121 if (*warning_message == PNG_LITERAL_SHARP) 122 { 123 for (offset = 1; offset < 15; offset++) 124 if (warning_message[offset] == ' ') 125 break; 126 } 127 } 128 } 129 if (png_ptr != NULL && png_ptr->warning_fn != NULL) 130 (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); 131 else 132 png_default_warning(png_ptr, warning_message + offset); 133 } 134 #endif /* PNG_WARNINGS_SUPPORTED */ 135 136 #ifdef PNG_BENIGN_ERRORS_SUPPORTED 137 void PNGAPI 138 png_benign_error(png_structp png_ptr, png_const_charp error_message) 139 { 140 if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) 141 png_warning(png_ptr, error_message); 142 else 143 png_error(png_ptr, error_message); 144 } 145 #endif 146 147 /* These utilities are used internally to build an error message that relates 148 * to the current chunk. The chunk name comes from png_ptr->chunk_name, 149 * this is used to prefix the message. The message is limited in length 150 * to 63 bytes, the name characters are output as hex digits wrapped in [] 151 * if the character is invalid. 152 */ 153 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) 154 static PNG_CONST char png_digit[16] = { 155 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 156 'A', 'B', 'C', 'D', 'E', 'F' 157 }; 158 159 #define PNG_MAX_ERROR_TEXT 64 160 #if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) 161 static void /* PRIVATE */ 162 png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp 163 error_message) 164 { 165 int iout = 0, iin = 0; 166 167 while (iin < 4) 168 { 169 int c = png_ptr->chunk_name[iin++]; 170 if (isnonalpha(c)) 171 { 172 buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; 173 buffer[iout++] = png_digit[(c & 0xf0) >> 4]; 174 buffer[iout++] = png_digit[c & 0x0f]; 175 buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; 176 } 177 else 178 { 179 buffer[iout++] = (png_byte)c; 180 } 181 } 182 183 if (error_message == NULL) 184 buffer[iout] = '\0'; 185 else 186 { 187 buffer[iout++] = ':'; 188 buffer[iout++] = ' '; 189 190 iin = 0; 191 while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') 192 buffer[iout++] = error_message[iin++]; 193 194 /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ 195 buffer[iout] = '\0'; 196 } 197 } 198 199 #ifdef PNG_READ_SUPPORTED 200 void PNGAPI 201 png_chunk_error(png_structp png_ptr, png_const_charp error_message) 202 { 203 char msg[18+PNG_MAX_ERROR_TEXT]; 204 if (png_ptr == NULL) 205 png_error(png_ptr, error_message); 206 else 207 { 208 png_format_buffer(png_ptr, msg, error_message); 209 png_error(png_ptr, msg); 210 } 211 } 212 #endif /* PNG_READ_SUPPORTED */ 213 #endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ 214 215 #ifdef PNG_WARNINGS_SUPPORTED 216 void PNGAPI 217 png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) 218 { 219 char msg[18+PNG_MAX_ERROR_TEXT]; 220 if (png_ptr == NULL) 221 png_warning(png_ptr, warning_message); 222 else 223 { 224 png_format_buffer(png_ptr, msg, warning_message); 225 png_warning(png_ptr, msg); 226 } 227 } 228 #endif /* PNG_WARNINGS_SUPPORTED */ 229 230 #ifdef PNG_READ_SUPPORTED 231 #ifdef PNG_BENIGN_ERRORS_SUPPORTED 232 void PNGAPI 233 png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) 234 { 235 if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) 236 png_chunk_warning(png_ptr, error_message); 237 else 238 png_chunk_error(png_ptr, error_message); 239 } 240 #endif 241 #endif /* PNG_READ_SUPPORTED */ 242 243 /* This is the default error handling function. Note that replacements for 244 * this function MUST NOT RETURN, or the program will likely crash. This 245 * function is used by default, or if the program supplies NULL for the 246 * error function pointer in png_set_error_fn(). 247 */ 248 static void /* PRIVATE */ 249 png_default_error(png_structp png_ptr, png_const_charp error_message) 250 { 251 #ifdef PNG_CONSOLE_IO_SUPPORTED 252 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 253 if (*error_message == PNG_LITERAL_SHARP) 254 { 255 /* Strip "#nnnn " from beginning of error message. */ 256 int offset; 257 char error_number[16]; 258 for (offset = 0; offset<15; offset++) 259 { 260 error_number[offset] = error_message[offset + 1]; 261 if (error_message[offset] == ' ') 262 break; 263 } 264 if ((offset > 1) && (offset < 15)) 265 { 266 error_number[offset - 1] = '\0'; 267 fprintf(stderr, "libpng error no. %s: %s", 268 error_number, error_message + offset + 1); 269 fprintf(stderr, PNG_STRING_NEWLINE); 270 } 271 else 272 { 273 fprintf(stderr, "libpng error: %s, offset=%d", 274 error_message, offset); 275 fprintf(stderr, PNG_STRING_NEWLINE); 276 } 277 } 278 else 279 #endif 280 { 281 fprintf(stderr, "libpng error: %s", error_message); 282 fprintf(stderr, PNG_STRING_NEWLINE); 283 } 284 #endif 285 286 #ifdef PNG_SETJMP_SUPPORTED 287 if (png_ptr) 288 { 289 # ifdef USE_FAR_KEYWORD 290 { 291 jmp_buf jmpbuf; 292 png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); 293 longjmp(jmpbuf,1); 294 } 295 # else 296 longjmp(png_ptr->jmpbuf, 1); 297 # endif 298 } 299 #endif 300 /* Here if not setjmp support or if png_ptr is null. */ 301 PNG_ABORT(); 302 #ifndef PNG_CONSOLE_IO_SUPPORTED 303 error_message = error_message; /* Make compiler happy */ 304 #endif 305 } 306 307 #ifdef PNG_WARNINGS_SUPPORTED 308 /* This function is called when there is a warning, but the library thinks 309 * it can continue anyway. Replacement functions don't have to do anything 310 * here if you don't want them to. In the default configuration, png_ptr is 311 * not used, but it is passed in case it may be useful. 312 */ 313 static void /* PRIVATE */ 314 png_default_warning(png_structp png_ptr, png_const_charp warning_message) 315 { 316 #ifdef PNG_CONSOLE_IO_SUPPORTED 317 # ifdef PNG_ERROR_NUMBERS_SUPPORTED 318 if (*warning_message == PNG_LITERAL_SHARP) 319 { 320 int offset; 321 char warning_number[16]; 322 for (offset = 0; offset < 15; offset++) 323 { 324 warning_number[offset] = warning_message[offset + 1]; 325 if (warning_message[offset] == ' ') 326 break; 327 } 328 if ((offset > 1) && (offset < 15)) 329 { 330 warning_number[offset + 1] = '\0'; 331 fprintf(stderr, "libpng warning no. %s: %s", 332 warning_number, warning_message + offset); 333 fprintf(stderr, PNG_STRING_NEWLINE); 334 } 335 else 336 { 337 fprintf(stderr, "libpng warning: %s", 338 warning_message); 339 fprintf(stderr, PNG_STRING_NEWLINE); 340 } 341 } 342 else 343 # endif 344 { 345 fprintf(stderr, "libpng warning: %s", warning_message); 346 fprintf(stderr, PNG_STRING_NEWLINE); 347 } 348 #else 349 warning_message = warning_message; /* Make compiler happy */ 350 #endif 351 png_ptr = png_ptr; /* Make compiler happy */ 352 } 353 #endif /* PNG_WARNINGS_SUPPORTED */ 354 355 /* This function is called when the application wants to use another method 356 * of handling errors and warnings. Note that the error function MUST NOT 357 * return to the calling routine or serious problems will occur. The return 358 * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) 359 */ 360 void PNGAPI 361 png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, 362 png_error_ptr error_fn, png_error_ptr warning_fn) 363 { 364 if (png_ptr == NULL) 365 return; 366 png_ptr->error_ptr = error_ptr; 367 png_ptr->error_fn = error_fn; 368 png_ptr->warning_fn = warning_fn; 369 } 370 371 372 /* This function returns a pointer to the error_ptr associated with the user 373 * functions. The application should free any memory associated with this 374 * pointer before png_write_destroy and png_read_destroy are called. 375 */ 376 png_voidp PNGAPI 377 png_get_error_ptr(png_structp png_ptr) 378 { 379 if (png_ptr == NULL) 380 return NULL; 381 return ((png_voidp)png_ptr->error_ptr); 382 } 383 384 385 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 386 void PNGAPI 387 png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) 388 { 389 if (png_ptr != NULL) 390 { 391 png_ptr->flags &= 392 ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); 393 } 394 } 395 #endif 396 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ 397