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