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