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