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