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