]> git.cworth.org Git - apitrace/blobdiff - thirdparty/libpng/pngerror.c
Update to libpng 1.5.9.
[apitrace] / thirdparty / libpng / pngerror.c
index 8290bb4106efbd5f18563a7c69f82e73bf47982c..95002f84f704b017f7de90f5e4e19b8561dc128c 100644 (file)
@@ -1,8 +1,8 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.5.1 [February 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.8 [February 1, 2011]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -89,15 +89,121 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
 PNG_FUNCTION(void,PNGAPI
 png_err,(png_structp png_ptr),PNG_NORETURN)
 {
+   /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
+    * erroneously as '\0', instead of the empty string "".  This was
+    * apparently an error, introduced in libpng-1.2.20, and png_default_error
+    * will crash in this case.
+    */
    if (png_ptr != NULL && png_ptr->error_fn != NULL)
-      (*(png_ptr->error_fn))(png_ptr, '\0');
+      (*(png_ptr->error_fn))(png_ptr, "");
 
    /* If the custom handler doesn't exist, or if it returns,
       use the default handler, which will not return. */
-   png_default_error(png_ptr, '\0');
+   png_default_error(png_ptr, "");
 }
 #endif /* PNG_ERROR_TEXT_SUPPORTED */
 
+/* Utility to safely appends strings to a buffer.  This never errors out so
+ * error checking is not required in the caller.
+ */
+size_t
+png_safecat(png_charp buffer, size_t bufsize, size_t pos,
+   png_const_charp string)
+{
+   if (buffer != NULL && pos < bufsize)
+   {
+      if (string != NULL)
+         while (*string != '\0' && pos < bufsize-1)
+           buffer[pos++] = *string++;
+
+      buffer[pos] = '\0';
+   }
+
+   return pos;
+}
+
+#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
+/* Utility to dump an unsigned value into a buffer, given a start pointer and
+ * and end pointer (which should point just *beyond* the end of the buffer!)
+ * Returns the pointer to the start of the formatted string.
+ */
+png_charp
+png_format_number(png_const_charp start, png_charp end, int format,
+   png_alloc_size_t number)
+{
+   int count = 0;    /* number of digits output */
+   int mincount = 1; /* minimum number required */
+   int output = 0;   /* digit output (for the fixed point format) */
+
+   *--end = '\0';
+
+   /* This is written so that the loop always runs at least once, even with
+    * number zero.
+    */
+   while (end > start && (number != 0 || count < mincount))
+   {
+
+      static const char digits[] = "0123456789ABCDEF";
+
+      switch (format)
+      {
+         case PNG_NUMBER_FORMAT_fixed:
+            /* Needs five digits (the fraction) */
+            mincount = 5;
+            if (output || number % 10 != 0)
+            {
+               *--end = digits[number % 10];
+               output = 1;
+            }
+            number /= 10;
+            break;
+
+         case PNG_NUMBER_FORMAT_02u:
+            /* Expects at least 2 digits. */
+            mincount = 2;
+            /* fall through */
+
+         case PNG_NUMBER_FORMAT_u:
+            *--end = digits[number % 10];
+            number /= 10;
+            break;
+
+         case PNG_NUMBER_FORMAT_02x:
+            /* This format expects at least two digits */
+            mincount = 2;
+            /* fall through */
+
+         case PNG_NUMBER_FORMAT_x:
+            *--end = digits[number & 0xf];
+            number >>= 4;
+            break;
+
+         default: /* an error */
+            number = 0;
+            break;
+      }
+
+      /* Keep track of the number of digits added */
+      ++count;
+
+      /* Float a fixed number here: */
+      if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start)
+      {
+         /* End of the fraction, but maybe nothing was output?  In that case
+          * drop the decimal point.  If the number is a true zero handle that
+          * here.
+          */
+         if (output)
+            *--end = '.';
+         else if (number == 0) /* and !output */
+            *--end = '0';
+      }
+   }
+
+   return end;
+}
+#endif
+
 #ifdef PNG_WARNINGS_SUPPORTED
 /* This function is called whenever there is a non-fatal error.  This function
  * should not be changed.  If there is a need to handle warnings differently,
@@ -128,6 +234,124 @@ png_warning(png_structp png_ptr, png_const_charp warning_message)
    else
       png_default_warning(png_ptr, warning_message + offset);
 }
+
+/* These functions support 'formatted' warning messages with up to
+ * PNG_WARNING_PARAMETER_COUNT parameters.  In the format string the parameter
+ * is introduced by @<number>, where 'number' starts at 1.  This follows the
+ * standard established by X/Open for internationalizable error messages.
+ */
+void
+png_warning_parameter(png_warning_parameters p, int number,
+   png_const_charp string)
+{
+   if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
+      (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
+}
+
+void
+png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
+   png_alloc_size_t value)
+{
+   char buffer[PNG_NUMBER_BUFFER_SIZE];
+   png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
+}
+
+void
+png_warning_parameter_signed(png_warning_parameters p, int number, int format,
+   png_int_32 value)
+{
+   png_alloc_size_t u;
+   png_charp str;
+   char buffer[PNG_NUMBER_BUFFER_SIZE];
+
+   /* Avoid overflow by doing the negate in a png_alloc_size_t: */
+   u = (png_alloc_size_t)value;
+   if (value < 0)
+      u = ~u + 1;
+
+   str = PNG_FORMAT_NUMBER(buffer, format, u);
+
+   if (value < 0 && str > buffer)
+      *--str = '-';
+
+   png_warning_parameter(p, number, str);
+}
+
+void
+png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
+   png_const_charp message)
+{
+   /* The internal buffer is just 192 bytes - enough for all our messages,
+    * overflow doesn't happen because this code checks!  If someone figures
+    * out how to send us a message longer than 192 bytes, all that will
+    * happen is that the message will be truncated appropriately.
+    */
+   size_t i = 0; /* Index in the msg[] buffer: */
+   char msg[192];
+
+   /* Each iteration through the following loop writes at most one character
+    * to msg[i++] then returns here to validate that there is still space for
+    * the trailing '\0'.  It may (in the case of a parameter) read more than
+    * one character from message[]; it must check for '\0' and continue to the
+    * test if it finds the end of string.
+    */
+   while (i<(sizeof msg)-1 && *message != '\0')
+   {
+      /* '@' at end of string is now just printed (previously it was skipped);
+       * it is an error in the calling code to terminate the string with @.
+       */
+      if (p != NULL && *message == '@' && message[1] != '\0')
+      {
+         int parameter_char = *++message; /* Consume the '@' */
+         static const char valid_parameters[] = "123456789";
+         int parameter = 0;
+
+         /* Search for the parameter digit, the index in the string is the
+          * parameter to use.
+          */
+         while (valid_parameters[parameter] != parameter_char &&
+            valid_parameters[parameter] != '\0')
+            ++parameter;
+
+         /* If the parameter digit is out of range it will just get printed. */
+         if (parameter < PNG_WARNING_PARAMETER_COUNT)
+         {
+            /* Append this parameter */
+            png_const_charp parm = p[parameter];
+            png_const_charp pend = p[parameter] + (sizeof p[parameter]);
+
+            /* No need to copy the trailing '\0' here, but there is no guarantee
+             * that parm[] has been initialized, so there is no guarantee of a
+             * trailing '\0':
+             */
+            while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
+               msg[i++] = *parm++;
+
+            /* Consume the parameter digit too: */
+            ++message;
+            continue;
+         }
+
+         /* else not a parameter and there is a character after the @ sign; just
+          * copy that.  This is known not to be '\0' because of the test above.
+          */
+      }
+
+      /* At this point *message can't be '\0', even in the bad parameter case
+       * above where there is a lone '@' at the end of the message string.
+       */
+      msg[i++] = *message++;
+   }
+
+   /* i is always less than (sizeof msg), so: */
+   msg[i] = '\0';
+
+   /* And this is the formatted message, it may be larger than
+    * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are
+    * not (currently) formatted.
+    */
+   png_warning(png_ptr, msg);
+}
 #endif /* PNG_WARNINGS_SUPPORTED */
 
 #ifdef PNG_BENIGN_ERRORS_SUPPORTED
@@ -159,11 +383,14 @@ static void /* PRIVATE */
 png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
     error_message)
 {
-   int iout = 0, iin = 0;
+   png_uint_32 chunk_name = png_ptr->chunk_name;
+   int iout = 0, ishift = 24;
 
-   while (iin < 4)
+   while (ishift >= 0)
    {
-      int c = png_ptr->chunk_name[iin++];
+      int c = (int)(chunk_name >> ishift) & 0xff;
+
+      ishift -= 8;
       if (isnonalpha(c))
       {
          buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
@@ -174,7 +401,7 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
 
       else
       {
-         buffer[iout++] = (png_byte)c;
+         buffer[iout++] = (char)c;
       }
    }
 
@@ -183,10 +410,16 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
 
    else
    {
+      int iin = 0;
+
       buffer[iout++] = ':';
       buffer[iout++] = ' ';
-      png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT);
-      buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0';
+
+      while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
+         buffer[iout++] = error_message[iin++];
+
+      /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
+      buffer[iout] = '\0';
    }
 }
 #endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */
@@ -272,7 +505,7 @@ png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn,
       return NULL;
 
    png_ptr->longjmp_fn = longjmp_fn;
-   return &png_ptr->png_jmpbuf;
+   return &png_ptr->longjmp_buffer;
 }
 #endif
 
@@ -287,7 +520,8 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message),
 {
 #ifdef PNG_CONSOLE_IO_SUPPORTED
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if (*error_message == PNG_LITERAL_SHARP)
+   /* Check on NULL only added in 1.5.4 */
+   if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
    {
       /* Strip "#nnnn " from beginning of error message. */
       int offset;
@@ -317,11 +551,11 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message),
    else
 #endif
    {
-      fprintf(stderr, "libpng error: %s", error_message);
+      fprintf(stderr, "libpng error: %s", error_message ? error_message :
+         "undefined");
       fprintf(stderr, PNG_STRING_NEWLINE);
    }
-#endif
-#ifndef PNG_CONSOLE_IO_SUPPORTED
+#else
    PNG_UNUSED(error_message) /* Make compiler happy */
 #endif
    png_longjmp(png_ptr, 1);
@@ -335,13 +569,13 @@ png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
    {
 #  ifdef USE_FAR_KEYWORD
       {
-         jmp_buf png_jmpbuf;
-         png_memcpy(png_jmpbuf, png_ptr->png_jmpbuf, png_sizeof(jmp_buf));
-         png_ptr->longjmp_fn(png_jmpbuf, val);
+         jmp_buf tmp_jmpbuf;
+         png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
+         png_ptr->longjmp_fn(tmp_jmpbuf, val);
       }
 
 #  else
-   png_ptr->longjmp_fn(png_ptr->png_jmpbuf, val);
+   png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val);
 #  endif
    }
 #endif
@@ -403,7 +637,7 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message)
 /* This function is called when the application wants to use another method
  * of handling errors and warnings.  Note that the error function MUST NOT
  * return to the calling routine or serious problems will occur.  The return
- * method used in the default routine calls longjmp(png_ptr->png_jmpbuf, 1)
+ * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1)
  */
 void PNGAPI
 png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
@@ -414,7 +648,11 @@ png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
 
    png_ptr->error_ptr = error_ptr;
    png_ptr->error_fn = error_fn;
+#ifdef PNG_WARNINGS_SUPPORTED
    png_ptr->warning_fn = warning_fn;
+#else
+   PNG_UNUSED(warning_fn)
+#endif
 }