+ 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_const_structrp 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
+void PNGAPI
+png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
+{
+ if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ {
+# ifdef PNG_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ png_ptr->chunk_name != 0)
+ png_chunk_warning(png_ptr, error_message);
+ else
+# endif
+ png_warning(png_ptr, error_message);
+ }
+