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