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