1cb93a386Sopenharmony_ci
2cb93a386Sopenharmony_ci/* pngerror.c - stub functions for i/o and memory allocation
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Copyright (c) 2018 Cosmin Truta
5cb93a386Sopenharmony_ci * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
6cb93a386Sopenharmony_ci * Copyright (c) 1996-1997 Andreas Dilger
7cb93a386Sopenharmony_ci * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
8cb93a386Sopenharmony_ci *
9cb93a386Sopenharmony_ci * This code is released under the libpng license.
10cb93a386Sopenharmony_ci * For conditions of distribution and use, see the disclaimer
11cb93a386Sopenharmony_ci * and license in png.h
12cb93a386Sopenharmony_ci *
13cb93a386Sopenharmony_ci * This file provides a location for all error handling.  Users who
14cb93a386Sopenharmony_ci * need special error handling are expected to write replacement functions
15cb93a386Sopenharmony_ci * and use png_set_error_fn() to use those functions.  See the instructions
16cb93a386Sopenharmony_ci * at each function.
17cb93a386Sopenharmony_ci */
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci#include "pngpriv.h"
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_cistatic PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
24cb93a386Sopenharmony_ci    png_const_charp error_message)),PNG_NORETURN);
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED
27cb93a386Sopenharmony_cistatic void /* PRIVATE */
28cb93a386Sopenharmony_cipng_default_warning PNGARG((png_const_structrp png_ptr,
29cb93a386Sopenharmony_ci    png_const_charp warning_message));
30cb93a386Sopenharmony_ci#endif /* WARNINGS */
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci/* This function is called whenever there is a fatal error.  This function
33cb93a386Sopenharmony_ci * should not be changed.  If there is a need to handle errors differently,
34cb93a386Sopenharmony_ci * you should supply a replacement error function and use png_set_error_fn()
35cb93a386Sopenharmony_ci * to replace the error function at run-time.
36cb93a386Sopenharmony_ci */
37cb93a386Sopenharmony_ci#ifdef PNG_ERROR_TEXT_SUPPORTED
38cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI
39cb93a386Sopenharmony_cipng_error,(png_const_structrp png_ptr, png_const_charp error_message),
40cb93a386Sopenharmony_ci    PNG_NORETURN)
41cb93a386Sopenharmony_ci{
42cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED
43cb93a386Sopenharmony_ci   char msg[16];
44cb93a386Sopenharmony_ci   if (png_ptr != NULL)
45cb93a386Sopenharmony_ci   {
46cb93a386Sopenharmony_ci      if ((png_ptr->flags &
47cb93a386Sopenharmony_ci         (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
48cb93a386Sopenharmony_ci      {
49cb93a386Sopenharmony_ci         if (*error_message == PNG_LITERAL_SHARP)
50cb93a386Sopenharmony_ci         {
51cb93a386Sopenharmony_ci            /* Strip "#nnnn " from beginning of error message. */
52cb93a386Sopenharmony_ci            int offset;
53cb93a386Sopenharmony_ci            for (offset = 1; offset<15; offset++)
54cb93a386Sopenharmony_ci               if (error_message[offset] == ' ')
55cb93a386Sopenharmony_ci                  break;
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
58cb93a386Sopenharmony_ci            {
59cb93a386Sopenharmony_ci               int i;
60cb93a386Sopenharmony_ci               for (i = 0; i < offset - 1; i++)
61cb93a386Sopenharmony_ci                  msg[i] = error_message[i + 1];
62cb93a386Sopenharmony_ci               msg[i - 1] = '\0';
63cb93a386Sopenharmony_ci               error_message = msg;
64cb93a386Sopenharmony_ci            }
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci            else
67cb93a386Sopenharmony_ci               error_message += offset;
68cb93a386Sopenharmony_ci         }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci         else
71cb93a386Sopenharmony_ci         {
72cb93a386Sopenharmony_ci            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
73cb93a386Sopenharmony_ci            {
74cb93a386Sopenharmony_ci               msg[0] = '0';
75cb93a386Sopenharmony_ci               msg[1] = '\0';
76cb93a386Sopenharmony_ci               error_message = msg;
77cb93a386Sopenharmony_ci            }
78cb93a386Sopenharmony_ci         }
79cb93a386Sopenharmony_ci      }
80cb93a386Sopenharmony_ci   }
81cb93a386Sopenharmony_ci#endif
82cb93a386Sopenharmony_ci   if (png_ptr != NULL && png_ptr->error_fn != NULL)
83cb93a386Sopenharmony_ci      (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
84cb93a386Sopenharmony_ci          error_message);
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci   /* If the custom handler doesn't exist, or if it returns,
87cb93a386Sopenharmony_ci      use the default handler, which will not return. */
88cb93a386Sopenharmony_ci   png_default_error(png_ptr, error_message);
89cb93a386Sopenharmony_ci}
90cb93a386Sopenharmony_ci#else
91cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI
92cb93a386Sopenharmony_cipng_err,(png_const_structrp png_ptr),PNG_NORETURN)
93cb93a386Sopenharmony_ci{
94cb93a386Sopenharmony_ci   /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
95cb93a386Sopenharmony_ci    * erroneously as '\0', instead of the empty string "".  This was
96cb93a386Sopenharmony_ci    * apparently an error, introduced in libpng-1.2.20, and png_default_error
97cb93a386Sopenharmony_ci    * will crash in this case.
98cb93a386Sopenharmony_ci    */
99cb93a386Sopenharmony_ci   if (png_ptr != NULL && png_ptr->error_fn != NULL)
100cb93a386Sopenharmony_ci      (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci   /* If the custom handler doesn't exist, or if it returns,
103cb93a386Sopenharmony_ci      use the default handler, which will not return. */
104cb93a386Sopenharmony_ci   png_default_error(png_ptr, "");
105cb93a386Sopenharmony_ci}
106cb93a386Sopenharmony_ci#endif /* ERROR_TEXT */
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci/* Utility to safely appends strings to a buffer.  This never errors out so
109cb93a386Sopenharmony_ci * error checking is not required in the caller.
110cb93a386Sopenharmony_ci */
111cb93a386Sopenharmony_cisize_t
112cb93a386Sopenharmony_cipng_safecat(png_charp buffer, size_t bufsize, size_t pos,
113cb93a386Sopenharmony_ci    png_const_charp string)
114cb93a386Sopenharmony_ci{
115cb93a386Sopenharmony_ci   if (buffer != NULL && pos < bufsize)
116cb93a386Sopenharmony_ci   {
117cb93a386Sopenharmony_ci      if (string != NULL)
118cb93a386Sopenharmony_ci         while (*string != '\0' && pos < bufsize-1)
119cb93a386Sopenharmony_ci           buffer[pos++] = *string++;
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci      buffer[pos] = '\0';
122cb93a386Sopenharmony_ci   }
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci   return pos;
125cb93a386Sopenharmony_ci}
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
128cb93a386Sopenharmony_ci/* Utility to dump an unsigned value into a buffer, given a start pointer and
129cb93a386Sopenharmony_ci * and end pointer (which should point just *beyond* the end of the buffer!)
130cb93a386Sopenharmony_ci * Returns the pointer to the start of the formatted string.
131cb93a386Sopenharmony_ci */
132cb93a386Sopenharmony_cipng_charp
133cb93a386Sopenharmony_cipng_format_number(png_const_charp start, png_charp end, int format,
134cb93a386Sopenharmony_ci    png_alloc_size_t number)
135cb93a386Sopenharmony_ci{
136cb93a386Sopenharmony_ci   int count = 0;    /* number of digits output */
137cb93a386Sopenharmony_ci   int mincount = 1; /* minimum number required */
138cb93a386Sopenharmony_ci   int output = 0;   /* digit output (for the fixed point format) */
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci   *--end = '\0';
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci   /* This is written so that the loop always runs at least once, even with
143cb93a386Sopenharmony_ci    * number zero.
144cb93a386Sopenharmony_ci    */
145cb93a386Sopenharmony_ci   while (end > start && (number != 0 || count < mincount))
146cb93a386Sopenharmony_ci   {
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci      static const char digits[] = "0123456789ABCDEF";
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ci      switch (format)
151cb93a386Sopenharmony_ci      {
152cb93a386Sopenharmony_ci         case PNG_NUMBER_FORMAT_fixed:
153cb93a386Sopenharmony_ci            /* Needs five digits (the fraction) */
154cb93a386Sopenharmony_ci            mincount = 5;
155cb93a386Sopenharmony_ci            if (output != 0 || number % 10 != 0)
156cb93a386Sopenharmony_ci            {
157cb93a386Sopenharmony_ci               *--end = digits[number % 10];
158cb93a386Sopenharmony_ci               output = 1;
159cb93a386Sopenharmony_ci            }
160cb93a386Sopenharmony_ci            number /= 10;
161cb93a386Sopenharmony_ci            break;
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci         case PNG_NUMBER_FORMAT_02u:
164cb93a386Sopenharmony_ci            /* Expects at least 2 digits. */
165cb93a386Sopenharmony_ci            mincount = 2;
166cb93a386Sopenharmony_ci            /* FALLTHROUGH */
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci         case PNG_NUMBER_FORMAT_u:
169cb93a386Sopenharmony_ci            *--end = digits[number % 10];
170cb93a386Sopenharmony_ci            number /= 10;
171cb93a386Sopenharmony_ci            break;
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_ci         case PNG_NUMBER_FORMAT_02x:
174cb93a386Sopenharmony_ci            /* This format expects at least two digits */
175cb93a386Sopenharmony_ci            mincount = 2;
176cb93a386Sopenharmony_ci            /* FALLTHROUGH */
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci         case PNG_NUMBER_FORMAT_x:
179cb93a386Sopenharmony_ci            *--end = digits[number & 0xf];
180cb93a386Sopenharmony_ci            number >>= 4;
181cb93a386Sopenharmony_ci            break;
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci         default: /* an error */
184cb93a386Sopenharmony_ci            number = 0;
185cb93a386Sopenharmony_ci            break;
186cb93a386Sopenharmony_ci      }
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci      /* Keep track of the number of digits added */
189cb93a386Sopenharmony_ci      ++count;
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci      /* Float a fixed number here: */
192cb93a386Sopenharmony_ci      if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
193cb93a386Sopenharmony_ci      {
194cb93a386Sopenharmony_ci         /* End of the fraction, but maybe nothing was output?  In that case
195cb93a386Sopenharmony_ci          * drop the decimal point.  If the number is a true zero handle that
196cb93a386Sopenharmony_ci          * here.
197cb93a386Sopenharmony_ci          */
198cb93a386Sopenharmony_ci         if (output != 0)
199cb93a386Sopenharmony_ci            *--end = '.';
200cb93a386Sopenharmony_ci         else if (number == 0) /* and !output */
201cb93a386Sopenharmony_ci            *--end = '0';
202cb93a386Sopenharmony_ci      }
203cb93a386Sopenharmony_ci   }
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_ci   return end;
206cb93a386Sopenharmony_ci}
207cb93a386Sopenharmony_ci#endif
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED
210cb93a386Sopenharmony_ci/* This function is called whenever there is a non-fatal error.  This function
211cb93a386Sopenharmony_ci * should not be changed.  If there is a need to handle warnings differently,
212cb93a386Sopenharmony_ci * you should supply a replacement warning function and use
213cb93a386Sopenharmony_ci * png_set_error_fn() to replace the warning function at run-time.
214cb93a386Sopenharmony_ci */
215cb93a386Sopenharmony_civoid PNGAPI
216cb93a386Sopenharmony_cipng_warning(png_const_structrp png_ptr, png_const_charp warning_message)
217cb93a386Sopenharmony_ci{
218cb93a386Sopenharmony_ci   int offset = 0;
219cb93a386Sopenharmony_ci   if (png_ptr != NULL)
220cb93a386Sopenharmony_ci   {
221cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED
222cb93a386Sopenharmony_ci   if ((png_ptr->flags &
223cb93a386Sopenharmony_ci       (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
224cb93a386Sopenharmony_ci#endif
225cb93a386Sopenharmony_ci      {
226cb93a386Sopenharmony_ci         if (*warning_message == PNG_LITERAL_SHARP)
227cb93a386Sopenharmony_ci         {
228cb93a386Sopenharmony_ci            for (offset = 1; offset < 15; offset++)
229cb93a386Sopenharmony_ci               if (warning_message[offset] == ' ')
230cb93a386Sopenharmony_ci                  break;
231cb93a386Sopenharmony_ci         }
232cb93a386Sopenharmony_ci      }
233cb93a386Sopenharmony_ci   }
234cb93a386Sopenharmony_ci   if (png_ptr != NULL && png_ptr->warning_fn != NULL)
235cb93a386Sopenharmony_ci      (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
236cb93a386Sopenharmony_ci          warning_message + offset);
237cb93a386Sopenharmony_ci   else
238cb93a386Sopenharmony_ci      png_default_warning(png_ptr, warning_message + offset);
239cb93a386Sopenharmony_ci}
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_ci/* These functions support 'formatted' warning messages with up to
242cb93a386Sopenharmony_ci * PNG_WARNING_PARAMETER_COUNT parameters.  In the format string the parameter
243cb93a386Sopenharmony_ci * is introduced by @<number>, where 'number' starts at 1.  This follows the
244cb93a386Sopenharmony_ci * standard established by X/Open for internationalizable error messages.
245cb93a386Sopenharmony_ci */
246cb93a386Sopenharmony_civoid
247cb93a386Sopenharmony_cipng_warning_parameter(png_warning_parameters p, int number,
248cb93a386Sopenharmony_ci    png_const_charp string)
249cb93a386Sopenharmony_ci{
250cb93a386Sopenharmony_ci   if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
251cb93a386Sopenharmony_ci      (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
252cb93a386Sopenharmony_ci}
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_civoid
255cb93a386Sopenharmony_cipng_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
256cb93a386Sopenharmony_ci    png_alloc_size_t value)
257cb93a386Sopenharmony_ci{
258cb93a386Sopenharmony_ci   char buffer[PNG_NUMBER_BUFFER_SIZE];
259cb93a386Sopenharmony_ci   png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
260cb93a386Sopenharmony_ci}
261cb93a386Sopenharmony_ci
262cb93a386Sopenharmony_civoid
263cb93a386Sopenharmony_cipng_warning_parameter_signed(png_warning_parameters p, int number, int format,
264cb93a386Sopenharmony_ci    png_int_32 value)
265cb93a386Sopenharmony_ci{
266cb93a386Sopenharmony_ci   png_alloc_size_t u;
267cb93a386Sopenharmony_ci   png_charp str;
268cb93a386Sopenharmony_ci   char buffer[PNG_NUMBER_BUFFER_SIZE];
269cb93a386Sopenharmony_ci
270cb93a386Sopenharmony_ci   /* Avoid overflow by doing the negate in a png_alloc_size_t: */
271cb93a386Sopenharmony_ci   u = (png_alloc_size_t)value;
272cb93a386Sopenharmony_ci   if (value < 0)
273cb93a386Sopenharmony_ci      u = ~u + 1;
274cb93a386Sopenharmony_ci
275cb93a386Sopenharmony_ci   str = PNG_FORMAT_NUMBER(buffer, format, u);
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci   if (value < 0 && str > buffer)
278cb93a386Sopenharmony_ci      *--str = '-';
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci   png_warning_parameter(p, number, str);
281cb93a386Sopenharmony_ci}
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_civoid
284cb93a386Sopenharmony_cipng_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
285cb93a386Sopenharmony_ci    png_const_charp message)
286cb93a386Sopenharmony_ci{
287cb93a386Sopenharmony_ci   /* The internal buffer is just 192 bytes - enough for all our messages,
288cb93a386Sopenharmony_ci    * overflow doesn't happen because this code checks!  If someone figures
289cb93a386Sopenharmony_ci    * out how to send us a message longer than 192 bytes, all that will
290cb93a386Sopenharmony_ci    * happen is that the message will be truncated appropriately.
291cb93a386Sopenharmony_ci    */
292cb93a386Sopenharmony_ci   size_t i = 0; /* Index in the msg[] buffer: */
293cb93a386Sopenharmony_ci   char msg[192];
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ci   /* Each iteration through the following loop writes at most one character
296cb93a386Sopenharmony_ci    * to msg[i++] then returns here to validate that there is still space for
297cb93a386Sopenharmony_ci    * the trailing '\0'.  It may (in the case of a parameter) read more than
298cb93a386Sopenharmony_ci    * one character from message[]; it must check for '\0' and continue to the
299cb93a386Sopenharmony_ci    * test if it finds the end of string.
300cb93a386Sopenharmony_ci    */
301cb93a386Sopenharmony_ci   while (i<(sizeof msg)-1 && *message != '\0')
302cb93a386Sopenharmony_ci   {
303cb93a386Sopenharmony_ci      /* '@' at end of string is now just printed (previously it was skipped);
304cb93a386Sopenharmony_ci       * it is an error in the calling code to terminate the string with @.
305cb93a386Sopenharmony_ci       */
306cb93a386Sopenharmony_ci      if (p != NULL && *message == '@' && message[1] != '\0')
307cb93a386Sopenharmony_ci      {
308cb93a386Sopenharmony_ci         int parameter_char = *++message; /* Consume the '@' */
309cb93a386Sopenharmony_ci         static const char valid_parameters[] = "123456789";
310cb93a386Sopenharmony_ci         int parameter = 0;
311cb93a386Sopenharmony_ci
312cb93a386Sopenharmony_ci         /* Search for the parameter digit, the index in the string is the
313cb93a386Sopenharmony_ci          * parameter to use.
314cb93a386Sopenharmony_ci          */
315cb93a386Sopenharmony_ci         while (valid_parameters[parameter] != parameter_char &&
316cb93a386Sopenharmony_ci            valid_parameters[parameter] != '\0')
317cb93a386Sopenharmony_ci            ++parameter;
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci         /* If the parameter digit is out of range it will just get printed. */
320cb93a386Sopenharmony_ci         if (parameter < PNG_WARNING_PARAMETER_COUNT)
321cb93a386Sopenharmony_ci         {
322cb93a386Sopenharmony_ci            /* Append this parameter */
323cb93a386Sopenharmony_ci            png_const_charp parm = p[parameter];
324cb93a386Sopenharmony_ci            png_const_charp pend = p[parameter] + (sizeof p[parameter]);
325cb93a386Sopenharmony_ci
326cb93a386Sopenharmony_ci            /* No need to copy the trailing '\0' here, but there is no guarantee
327cb93a386Sopenharmony_ci             * that parm[] has been initialized, so there is no guarantee of a
328cb93a386Sopenharmony_ci             * trailing '\0':
329cb93a386Sopenharmony_ci             */
330cb93a386Sopenharmony_ci            while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
331cb93a386Sopenharmony_ci               msg[i++] = *parm++;
332cb93a386Sopenharmony_ci
333cb93a386Sopenharmony_ci            /* Consume the parameter digit too: */
334cb93a386Sopenharmony_ci            ++message;
335cb93a386Sopenharmony_ci            continue;
336cb93a386Sopenharmony_ci         }
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_ci         /* else not a parameter and there is a character after the @ sign; just
339cb93a386Sopenharmony_ci          * copy that.  This is known not to be '\0' because of the test above.
340cb93a386Sopenharmony_ci          */
341cb93a386Sopenharmony_ci      }
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci      /* At this point *message can't be '\0', even in the bad parameter case
344cb93a386Sopenharmony_ci       * above where there is a lone '@' at the end of the message string.
345cb93a386Sopenharmony_ci       */
346cb93a386Sopenharmony_ci      msg[i++] = *message++;
347cb93a386Sopenharmony_ci   }
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci   /* i is always less than (sizeof msg), so: */
350cb93a386Sopenharmony_ci   msg[i] = '\0';
351cb93a386Sopenharmony_ci
352cb93a386Sopenharmony_ci   /* And this is the formatted message. It may be larger than
353cb93a386Sopenharmony_ci    * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
354cb93a386Sopenharmony_ci    * are not (currently) formatted.
355cb93a386Sopenharmony_ci    */
356cb93a386Sopenharmony_ci   png_warning(png_ptr, msg);
357cb93a386Sopenharmony_ci}
358cb93a386Sopenharmony_ci#endif /* WARNINGS */
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci#ifdef PNG_BENIGN_ERRORS_SUPPORTED
361cb93a386Sopenharmony_civoid PNGAPI
362cb93a386Sopenharmony_cipng_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
363cb93a386Sopenharmony_ci{
364cb93a386Sopenharmony_ci   if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
365cb93a386Sopenharmony_ci   {
366cb93a386Sopenharmony_ci#     ifdef PNG_READ_SUPPORTED
367cb93a386Sopenharmony_ci         if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
368cb93a386Sopenharmony_ci            png_ptr->chunk_name != 0)
369cb93a386Sopenharmony_ci            png_chunk_warning(png_ptr, error_message);
370cb93a386Sopenharmony_ci         else
371cb93a386Sopenharmony_ci#     endif
372cb93a386Sopenharmony_ci      png_warning(png_ptr, error_message);
373cb93a386Sopenharmony_ci   }
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ci   else
376cb93a386Sopenharmony_ci   {
377cb93a386Sopenharmony_ci#     ifdef PNG_READ_SUPPORTED
378cb93a386Sopenharmony_ci         if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
379cb93a386Sopenharmony_ci            png_ptr->chunk_name != 0)
380cb93a386Sopenharmony_ci            png_chunk_error(png_ptr, error_message);
381cb93a386Sopenharmony_ci         else
382cb93a386Sopenharmony_ci#     endif
383cb93a386Sopenharmony_ci      png_error(png_ptr, error_message);
384cb93a386Sopenharmony_ci   }
385cb93a386Sopenharmony_ci
386cb93a386Sopenharmony_ci#  ifndef PNG_ERROR_TEXT_SUPPORTED
387cb93a386Sopenharmony_ci      PNG_UNUSED(error_message)
388cb93a386Sopenharmony_ci#  endif
389cb93a386Sopenharmony_ci}
390cb93a386Sopenharmony_ci
391cb93a386Sopenharmony_civoid /* PRIVATE */
392cb93a386Sopenharmony_cipng_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
393cb93a386Sopenharmony_ci{
394cb93a386Sopenharmony_ci   if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
395cb93a386Sopenharmony_ci      png_warning(png_ptr, error_message);
396cb93a386Sopenharmony_ci   else
397cb93a386Sopenharmony_ci      png_error(png_ptr, error_message);
398cb93a386Sopenharmony_ci
399cb93a386Sopenharmony_ci#  ifndef PNG_ERROR_TEXT_SUPPORTED
400cb93a386Sopenharmony_ci      PNG_UNUSED(error_message)
401cb93a386Sopenharmony_ci#  endif
402cb93a386Sopenharmony_ci}
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_civoid /* PRIVATE */
405cb93a386Sopenharmony_cipng_app_error(png_const_structrp png_ptr, png_const_charp error_message)
406cb93a386Sopenharmony_ci{
407cb93a386Sopenharmony_ci   if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0)
408cb93a386Sopenharmony_ci      png_warning(png_ptr, error_message);
409cb93a386Sopenharmony_ci   else
410cb93a386Sopenharmony_ci      png_error(png_ptr, error_message);
411cb93a386Sopenharmony_ci
412cb93a386Sopenharmony_ci#  ifndef PNG_ERROR_TEXT_SUPPORTED
413cb93a386Sopenharmony_ci      PNG_UNUSED(error_message)
414cb93a386Sopenharmony_ci#  endif
415cb93a386Sopenharmony_ci}
416cb93a386Sopenharmony_ci#endif /* BENIGN_ERRORS */
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
419cb93a386Sopenharmony_ci#if defined(PNG_WARNINGS_SUPPORTED) || \
420cb93a386Sopenharmony_ci   (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
421cb93a386Sopenharmony_ci/* These utilities are used internally to build an error message that relates
422cb93a386Sopenharmony_ci * to the current chunk.  The chunk name comes from png_ptr->chunk_name,
423cb93a386Sopenharmony_ci * which is used to prefix the message.  The message is limited in length
424cb93a386Sopenharmony_ci * to 63 bytes. The name characters are output as hex digits wrapped in []
425cb93a386Sopenharmony_ci * if the character is invalid.
426cb93a386Sopenharmony_ci */
427cb93a386Sopenharmony_ci#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
428cb93a386Sopenharmony_cistatic const char png_digit[16] = {
429cb93a386Sopenharmony_ci   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
430cb93a386Sopenharmony_ci   'A', 'B', 'C', 'D', 'E', 'F'
431cb93a386Sopenharmony_ci};
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_cistatic void /* PRIVATE */
434cb93a386Sopenharmony_cipng_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
435cb93a386Sopenharmony_ci    error_message)
436cb93a386Sopenharmony_ci{
437cb93a386Sopenharmony_ci   png_uint_32 chunk_name = png_ptr->chunk_name;
438cb93a386Sopenharmony_ci   int iout = 0, ishift = 24;
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_ci   while (ishift >= 0)
441cb93a386Sopenharmony_ci   {
442cb93a386Sopenharmony_ci      int c = (int)(chunk_name >> ishift) & 0xff;
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ci      ishift -= 8;
445cb93a386Sopenharmony_ci      if (isnonalpha(c) != 0)
446cb93a386Sopenharmony_ci      {
447cb93a386Sopenharmony_ci         buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
448cb93a386Sopenharmony_ci         buffer[iout++] = png_digit[(c & 0xf0) >> 4];
449cb93a386Sopenharmony_ci         buffer[iout++] = png_digit[c & 0x0f];
450cb93a386Sopenharmony_ci         buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
451cb93a386Sopenharmony_ci      }
452cb93a386Sopenharmony_ci
453cb93a386Sopenharmony_ci      else
454cb93a386Sopenharmony_ci      {
455cb93a386Sopenharmony_ci         buffer[iout++] = (char)c;
456cb93a386Sopenharmony_ci      }
457cb93a386Sopenharmony_ci   }
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_ci   if (error_message == NULL)
460cb93a386Sopenharmony_ci      buffer[iout] = '\0';
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ci   else
463cb93a386Sopenharmony_ci   {
464cb93a386Sopenharmony_ci      int iin = 0;
465cb93a386Sopenharmony_ci
466cb93a386Sopenharmony_ci      buffer[iout++] = ':';
467cb93a386Sopenharmony_ci      buffer[iout++] = ' ';
468cb93a386Sopenharmony_ci
469cb93a386Sopenharmony_ci      while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
470cb93a386Sopenharmony_ci         buffer[iout++] = error_message[iin++];
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci      /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
473cb93a386Sopenharmony_ci      buffer[iout] = '\0';
474cb93a386Sopenharmony_ci   }
475cb93a386Sopenharmony_ci}
476cb93a386Sopenharmony_ci#endif /* WARNINGS || ERROR_TEXT */
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ci#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
479cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI
480cb93a386Sopenharmony_cipng_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message),
481cb93a386Sopenharmony_ci    PNG_NORETURN)
482cb93a386Sopenharmony_ci{
483cb93a386Sopenharmony_ci   char msg[18+PNG_MAX_ERROR_TEXT];
484cb93a386Sopenharmony_ci   if (png_ptr == NULL)
485cb93a386Sopenharmony_ci      png_error(png_ptr, error_message);
486cb93a386Sopenharmony_ci
487cb93a386Sopenharmony_ci   else
488cb93a386Sopenharmony_ci   {
489cb93a386Sopenharmony_ci      png_format_buffer(png_ptr, msg, error_message);
490cb93a386Sopenharmony_ci      png_error(png_ptr, msg);
491cb93a386Sopenharmony_ci   }
492cb93a386Sopenharmony_ci}
493cb93a386Sopenharmony_ci#endif /* READ && ERROR_TEXT */
494cb93a386Sopenharmony_ci
495cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED
496cb93a386Sopenharmony_civoid PNGAPI
497cb93a386Sopenharmony_cipng_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
498cb93a386Sopenharmony_ci{
499cb93a386Sopenharmony_ci   char msg[18+PNG_MAX_ERROR_TEXT];
500cb93a386Sopenharmony_ci   if (png_ptr == NULL)
501cb93a386Sopenharmony_ci      png_warning(png_ptr, warning_message);
502cb93a386Sopenharmony_ci
503cb93a386Sopenharmony_ci   else
504cb93a386Sopenharmony_ci   {
505cb93a386Sopenharmony_ci      png_format_buffer(png_ptr, msg, warning_message);
506cb93a386Sopenharmony_ci      png_warning(png_ptr, msg);
507cb93a386Sopenharmony_ci   }
508cb93a386Sopenharmony_ci}
509cb93a386Sopenharmony_ci#endif /* WARNINGS */
510cb93a386Sopenharmony_ci
511cb93a386Sopenharmony_ci#ifdef PNG_READ_SUPPORTED
512cb93a386Sopenharmony_ci#ifdef PNG_BENIGN_ERRORS_SUPPORTED
513cb93a386Sopenharmony_civoid PNGAPI
514cb93a386Sopenharmony_cipng_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
515cb93a386Sopenharmony_ci    error_message)
516cb93a386Sopenharmony_ci{
517cb93a386Sopenharmony_ci   if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
518cb93a386Sopenharmony_ci      png_chunk_warning(png_ptr, error_message);
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci   else
521cb93a386Sopenharmony_ci      png_chunk_error(png_ptr, error_message);
522cb93a386Sopenharmony_ci
523cb93a386Sopenharmony_ci#  ifndef PNG_ERROR_TEXT_SUPPORTED
524cb93a386Sopenharmony_ci      PNG_UNUSED(error_message)
525cb93a386Sopenharmony_ci#  endif
526cb93a386Sopenharmony_ci}
527cb93a386Sopenharmony_ci#endif
528cb93a386Sopenharmony_ci#endif /* READ */
529cb93a386Sopenharmony_ci
530cb93a386Sopenharmony_civoid /* PRIVATE */
531cb93a386Sopenharmony_cipng_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
532cb93a386Sopenharmony_ci{
533cb93a386Sopenharmony_ci#  ifndef PNG_WARNINGS_SUPPORTED
534cb93a386Sopenharmony_ci      PNG_UNUSED(message)
535cb93a386Sopenharmony_ci#  endif
536cb93a386Sopenharmony_ci
537cb93a386Sopenharmony_ci   /* This is always supported, but for just read or just write it
538cb93a386Sopenharmony_ci    * unconditionally does the right thing.
539cb93a386Sopenharmony_ci    */
540cb93a386Sopenharmony_ci#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
541cb93a386Sopenharmony_ci      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
542cb93a386Sopenharmony_ci#  endif
543cb93a386Sopenharmony_ci
544cb93a386Sopenharmony_ci#  ifdef PNG_READ_SUPPORTED
545cb93a386Sopenharmony_ci      {
546cb93a386Sopenharmony_ci         if (error < PNG_CHUNK_ERROR)
547cb93a386Sopenharmony_ci            png_chunk_warning(png_ptr, message);
548cb93a386Sopenharmony_ci
549cb93a386Sopenharmony_ci         else
550cb93a386Sopenharmony_ci            png_chunk_benign_error(png_ptr, message);
551cb93a386Sopenharmony_ci      }
552cb93a386Sopenharmony_ci#  endif
553cb93a386Sopenharmony_ci
554cb93a386Sopenharmony_ci#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
555cb93a386Sopenharmony_ci      else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
556cb93a386Sopenharmony_ci#  endif
557cb93a386Sopenharmony_ci
558cb93a386Sopenharmony_ci#  ifdef PNG_WRITE_SUPPORTED
559cb93a386Sopenharmony_ci      {
560cb93a386Sopenharmony_ci         if (error < PNG_CHUNK_WRITE_ERROR)
561cb93a386Sopenharmony_ci            png_app_warning(png_ptr, message);
562cb93a386Sopenharmony_ci
563cb93a386Sopenharmony_ci         else
564cb93a386Sopenharmony_ci            png_app_error(png_ptr, message);
565cb93a386Sopenharmony_ci      }
566cb93a386Sopenharmony_ci#  endif
567cb93a386Sopenharmony_ci}
568cb93a386Sopenharmony_ci
569cb93a386Sopenharmony_ci#ifdef PNG_ERROR_TEXT_SUPPORTED
570cb93a386Sopenharmony_ci#ifdef PNG_FLOATING_POINT_SUPPORTED
571cb93a386Sopenharmony_ciPNG_FUNCTION(void,
572cb93a386Sopenharmony_cipng_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
573cb93a386Sopenharmony_ci{
574cb93a386Sopenharmony_ci#  define fixed_message "fixed point overflow in "
575cb93a386Sopenharmony_ci#  define fixed_message_ln ((sizeof fixed_message)-1)
576cb93a386Sopenharmony_ci   unsigned int  iin;
577cb93a386Sopenharmony_ci   char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
578cb93a386Sopenharmony_ci   memcpy(msg, fixed_message, fixed_message_ln);
579cb93a386Sopenharmony_ci   iin = 0;
580cb93a386Sopenharmony_ci   if (name != NULL)
581cb93a386Sopenharmony_ci      while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
582cb93a386Sopenharmony_ci      {
583cb93a386Sopenharmony_ci         msg[fixed_message_ln + iin] = name[iin];
584cb93a386Sopenharmony_ci         ++iin;
585cb93a386Sopenharmony_ci      }
586cb93a386Sopenharmony_ci   msg[fixed_message_ln + iin] = 0;
587cb93a386Sopenharmony_ci   png_error(png_ptr, msg);
588cb93a386Sopenharmony_ci}
589cb93a386Sopenharmony_ci#endif
590cb93a386Sopenharmony_ci#endif
591cb93a386Sopenharmony_ci
592cb93a386Sopenharmony_ci#ifdef PNG_SETJMP_SUPPORTED
593cb93a386Sopenharmony_ci/* This API only exists if ANSI-C style error handling is used,
594cb93a386Sopenharmony_ci * otherwise it is necessary for png_default_error to be overridden.
595cb93a386Sopenharmony_ci */
596cb93a386Sopenharmony_cijmp_buf* PNGAPI
597cb93a386Sopenharmony_cipng_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
598cb93a386Sopenharmony_ci    size_t jmp_buf_size)
599cb93a386Sopenharmony_ci{
600cb93a386Sopenharmony_ci   /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
601cb93a386Sopenharmony_ci    * and it must not change after that.  Libpng doesn't care how big the
602cb93a386Sopenharmony_ci    * buffer is, just that it doesn't change.
603cb93a386Sopenharmony_ci    *
604cb93a386Sopenharmony_ci    * If the buffer size is no *larger* than the size of jmp_buf when libpng is
605cb93a386Sopenharmony_ci    * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
606cb93a386Sopenharmony_ci    * semantics that this call will not fail.  If the size is larger, however,
607cb93a386Sopenharmony_ci    * the buffer is allocated and this may fail, causing the function to return
608cb93a386Sopenharmony_ci    * NULL.
609cb93a386Sopenharmony_ci    */
610cb93a386Sopenharmony_ci   if (png_ptr == NULL)
611cb93a386Sopenharmony_ci      return NULL;
612cb93a386Sopenharmony_ci
613cb93a386Sopenharmony_ci   if (png_ptr->jmp_buf_ptr == NULL)
614cb93a386Sopenharmony_ci   {
615cb93a386Sopenharmony_ci      png_ptr->jmp_buf_size = 0; /* not allocated */
616cb93a386Sopenharmony_ci
617cb93a386Sopenharmony_ci      if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
618cb93a386Sopenharmony_ci         png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
619cb93a386Sopenharmony_ci
620cb93a386Sopenharmony_ci      else
621cb93a386Sopenharmony_ci      {
622cb93a386Sopenharmony_ci         png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
623cb93a386Sopenharmony_ci             png_malloc_warn(png_ptr, jmp_buf_size));
624cb93a386Sopenharmony_ci
625cb93a386Sopenharmony_ci         if (png_ptr->jmp_buf_ptr == NULL)
626cb93a386Sopenharmony_ci            return NULL; /* new NULL return on OOM */
627cb93a386Sopenharmony_ci
628cb93a386Sopenharmony_ci         png_ptr->jmp_buf_size = jmp_buf_size;
629cb93a386Sopenharmony_ci      }
630cb93a386Sopenharmony_ci   }
631cb93a386Sopenharmony_ci
632cb93a386Sopenharmony_ci   else /* Already allocated: check the size */
633cb93a386Sopenharmony_ci   {
634cb93a386Sopenharmony_ci      size_t size = png_ptr->jmp_buf_size;
635cb93a386Sopenharmony_ci
636cb93a386Sopenharmony_ci      if (size == 0)
637cb93a386Sopenharmony_ci      {
638cb93a386Sopenharmony_ci         size = (sizeof png_ptr->jmp_buf_local);
639cb93a386Sopenharmony_ci         if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
640cb93a386Sopenharmony_ci         {
641cb93a386Sopenharmony_ci            /* This is an internal error in libpng: somehow we have been left
642cb93a386Sopenharmony_ci             * with a stack allocated jmp_buf when the application regained
643cb93a386Sopenharmony_ci             * control.  It's always possible to fix this up, but for the moment
644cb93a386Sopenharmony_ci             * this is a png_error because that makes it easy to detect.
645cb93a386Sopenharmony_ci             */
646cb93a386Sopenharmony_ci            png_error(png_ptr, "Libpng jmp_buf still allocated");
647cb93a386Sopenharmony_ci            /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
648cb93a386Sopenharmony_ci         }
649cb93a386Sopenharmony_ci      }
650cb93a386Sopenharmony_ci
651cb93a386Sopenharmony_ci      if (size != jmp_buf_size)
652cb93a386Sopenharmony_ci      {
653cb93a386Sopenharmony_ci         png_warning(png_ptr, "Application jmp_buf size changed");
654cb93a386Sopenharmony_ci         return NULL; /* caller will probably crash: no choice here */
655cb93a386Sopenharmony_ci      }
656cb93a386Sopenharmony_ci   }
657cb93a386Sopenharmony_ci
658cb93a386Sopenharmony_ci   /* Finally fill in the function, now we have a satisfactory buffer. It is
659cb93a386Sopenharmony_ci    * valid to change the function on every call.
660cb93a386Sopenharmony_ci    */
661cb93a386Sopenharmony_ci   png_ptr->longjmp_fn = longjmp_fn;
662cb93a386Sopenharmony_ci   return png_ptr->jmp_buf_ptr;
663cb93a386Sopenharmony_ci}
664cb93a386Sopenharmony_ci
665cb93a386Sopenharmony_civoid /* PRIVATE */
666cb93a386Sopenharmony_cipng_free_jmpbuf(png_structrp png_ptr)
667cb93a386Sopenharmony_ci{
668cb93a386Sopenharmony_ci   if (png_ptr != NULL)
669cb93a386Sopenharmony_ci   {
670cb93a386Sopenharmony_ci      jmp_buf *jb = png_ptr->jmp_buf_ptr;
671cb93a386Sopenharmony_ci
672cb93a386Sopenharmony_ci      /* A size of 0 is used to indicate a local, stack, allocation of the
673cb93a386Sopenharmony_ci       * pointer; used here and in png.c
674cb93a386Sopenharmony_ci       */
675cb93a386Sopenharmony_ci      if (jb != NULL && png_ptr->jmp_buf_size > 0)
676cb93a386Sopenharmony_ci      {
677cb93a386Sopenharmony_ci
678cb93a386Sopenharmony_ci         /* This stuff is so that a failure to free the error control structure
679cb93a386Sopenharmony_ci          * does not leave libpng in a state with no valid error handling: the
680cb93a386Sopenharmony_ci          * free always succeeds, if there is an error it gets ignored.
681cb93a386Sopenharmony_ci          */
682cb93a386Sopenharmony_ci         if (jb != &png_ptr->jmp_buf_local)
683cb93a386Sopenharmony_ci         {
684cb93a386Sopenharmony_ci            /* Make an internal, libpng, jmp_buf to return here */
685cb93a386Sopenharmony_ci            jmp_buf free_jmp_buf;
686cb93a386Sopenharmony_ci
687cb93a386Sopenharmony_ci            if (!setjmp(free_jmp_buf))
688cb93a386Sopenharmony_ci            {
689cb93a386Sopenharmony_ci               png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
690cb93a386Sopenharmony_ci               png_ptr->jmp_buf_size = 0; /* stack allocation */
691cb93a386Sopenharmony_ci               png_ptr->longjmp_fn = longjmp;
692cb93a386Sopenharmony_ci               png_free(png_ptr, jb); /* Return to setjmp on error */
693cb93a386Sopenharmony_ci            }
694cb93a386Sopenharmony_ci         }
695cb93a386Sopenharmony_ci      }
696cb93a386Sopenharmony_ci
697cb93a386Sopenharmony_ci      /* *Always* cancel everything out: */
698cb93a386Sopenharmony_ci      png_ptr->jmp_buf_size = 0;
699cb93a386Sopenharmony_ci      png_ptr->jmp_buf_ptr = NULL;
700cb93a386Sopenharmony_ci      png_ptr->longjmp_fn = 0;
701cb93a386Sopenharmony_ci   }
702cb93a386Sopenharmony_ci}
703cb93a386Sopenharmony_ci#endif
704cb93a386Sopenharmony_ci
705cb93a386Sopenharmony_ci/* This is the default error handling function.  Note that replacements for
706cb93a386Sopenharmony_ci * this function MUST NOT RETURN, or the program will likely crash.  This
707cb93a386Sopenharmony_ci * function is used by default, or if the program supplies NULL for the
708cb93a386Sopenharmony_ci * error function pointer in png_set_error_fn().
709cb93a386Sopenharmony_ci */
710cb93a386Sopenharmony_cistatic PNG_FUNCTION(void /* PRIVATE */,
711cb93a386Sopenharmony_cipng_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
712cb93a386Sopenharmony_ci    PNG_NORETURN)
713cb93a386Sopenharmony_ci{
714cb93a386Sopenharmony_ci#ifdef PNG_CONSOLE_IO_SUPPORTED
715cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED
716cb93a386Sopenharmony_ci   /* Check on NULL only added in 1.5.4 */
717cb93a386Sopenharmony_ci   if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
718cb93a386Sopenharmony_ci   {
719cb93a386Sopenharmony_ci      /* Strip "#nnnn " from beginning of error message. */
720cb93a386Sopenharmony_ci      int offset;
721cb93a386Sopenharmony_ci      char error_number[16];
722cb93a386Sopenharmony_ci      for (offset = 0; offset<15; offset++)
723cb93a386Sopenharmony_ci      {
724cb93a386Sopenharmony_ci         error_number[offset] = error_message[offset + 1];
725cb93a386Sopenharmony_ci         if (error_message[offset] == ' ')
726cb93a386Sopenharmony_ci            break;
727cb93a386Sopenharmony_ci      }
728cb93a386Sopenharmony_ci
729cb93a386Sopenharmony_ci      if ((offset > 1) && (offset < 15))
730cb93a386Sopenharmony_ci      {
731cb93a386Sopenharmony_ci         error_number[offset - 1] = '\0';
732cb93a386Sopenharmony_ci         fprintf(stderr, "libpng error no. %s: %s",
733cb93a386Sopenharmony_ci             error_number, error_message + offset + 1);
734cb93a386Sopenharmony_ci         fprintf(stderr, PNG_STRING_NEWLINE);
735cb93a386Sopenharmony_ci      }
736cb93a386Sopenharmony_ci
737cb93a386Sopenharmony_ci      else
738cb93a386Sopenharmony_ci      {
739cb93a386Sopenharmony_ci         fprintf(stderr, "libpng error: %s, offset=%d",
740cb93a386Sopenharmony_ci             error_message, offset);
741cb93a386Sopenharmony_ci         fprintf(stderr, PNG_STRING_NEWLINE);
742cb93a386Sopenharmony_ci      }
743cb93a386Sopenharmony_ci   }
744cb93a386Sopenharmony_ci   else
745cb93a386Sopenharmony_ci#endif
746cb93a386Sopenharmony_ci   {
747cb93a386Sopenharmony_ci      fprintf(stderr, "libpng error: %s", error_message ? error_message :
748cb93a386Sopenharmony_ci         "undefined");
749cb93a386Sopenharmony_ci      fprintf(stderr, PNG_STRING_NEWLINE);
750cb93a386Sopenharmony_ci   }
751cb93a386Sopenharmony_ci#else
752cb93a386Sopenharmony_ci   PNG_UNUSED(error_message) /* Make compiler happy */
753cb93a386Sopenharmony_ci#endif
754cb93a386Sopenharmony_ci   png_longjmp(png_ptr, 1);
755cb93a386Sopenharmony_ci}
756cb93a386Sopenharmony_ci
757cb93a386Sopenharmony_ciPNG_FUNCTION(void,PNGAPI
758cb93a386Sopenharmony_cipng_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
759cb93a386Sopenharmony_ci{
760cb93a386Sopenharmony_ci#ifdef PNG_SETJMP_SUPPORTED
761cb93a386Sopenharmony_ci   if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
762cb93a386Sopenharmony_ci       png_ptr->jmp_buf_ptr != NULL)
763cb93a386Sopenharmony_ci      png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
764cb93a386Sopenharmony_ci#else
765cb93a386Sopenharmony_ci   PNG_UNUSED(png_ptr)
766cb93a386Sopenharmony_ci   PNG_UNUSED(val)
767cb93a386Sopenharmony_ci#endif
768cb93a386Sopenharmony_ci
769cb93a386Sopenharmony_ci   /* If control reaches this point, png_longjmp() must not return. The only
770cb93a386Sopenharmony_ci    * choice is to terminate the whole process (or maybe the thread); to do
771cb93a386Sopenharmony_ci    * this the ANSI-C abort() function is used unless a different method is
772cb93a386Sopenharmony_ci    * implemented by overriding the default configuration setting for
773cb93a386Sopenharmony_ci    * PNG_ABORT().
774cb93a386Sopenharmony_ci    */
775cb93a386Sopenharmony_ci   PNG_ABORT();
776cb93a386Sopenharmony_ci}
777cb93a386Sopenharmony_ci
778cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED
779cb93a386Sopenharmony_ci/* This function is called when there is a warning, but the library thinks
780cb93a386Sopenharmony_ci * it can continue anyway.  Replacement functions don't have to do anything
781cb93a386Sopenharmony_ci * here if you don't want them to.  In the default configuration, png_ptr is
782cb93a386Sopenharmony_ci * not used, but it is passed in case it may be useful.
783cb93a386Sopenharmony_ci */
784cb93a386Sopenharmony_cistatic void /* PRIVATE */
785cb93a386Sopenharmony_cipng_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
786cb93a386Sopenharmony_ci{
787cb93a386Sopenharmony_ci#ifdef PNG_CONSOLE_IO_SUPPORTED
788cb93a386Sopenharmony_ci#  ifdef PNG_ERROR_NUMBERS_SUPPORTED
789cb93a386Sopenharmony_ci   if (*warning_message == PNG_LITERAL_SHARP)
790cb93a386Sopenharmony_ci   {
791cb93a386Sopenharmony_ci      int offset;
792cb93a386Sopenharmony_ci      char warning_number[16];
793cb93a386Sopenharmony_ci      for (offset = 0; offset < 15; offset++)
794cb93a386Sopenharmony_ci      {
795cb93a386Sopenharmony_ci         warning_number[offset] = warning_message[offset + 1];
796cb93a386Sopenharmony_ci         if (warning_message[offset] == ' ')
797cb93a386Sopenharmony_ci            break;
798cb93a386Sopenharmony_ci      }
799cb93a386Sopenharmony_ci
800cb93a386Sopenharmony_ci      if ((offset > 1) && (offset < 15))
801cb93a386Sopenharmony_ci      {
802cb93a386Sopenharmony_ci         warning_number[offset + 1] = '\0';
803cb93a386Sopenharmony_ci         fprintf(stderr, "libpng warning no. %s: %s",
804cb93a386Sopenharmony_ci             warning_number, warning_message + offset);
805cb93a386Sopenharmony_ci         fprintf(stderr, PNG_STRING_NEWLINE);
806cb93a386Sopenharmony_ci      }
807cb93a386Sopenharmony_ci
808cb93a386Sopenharmony_ci      else
809cb93a386Sopenharmony_ci      {
810cb93a386Sopenharmony_ci         fprintf(stderr, "libpng warning: %s",
811cb93a386Sopenharmony_ci             warning_message);
812cb93a386Sopenharmony_ci         fprintf(stderr, PNG_STRING_NEWLINE);
813cb93a386Sopenharmony_ci      }
814cb93a386Sopenharmony_ci   }
815cb93a386Sopenharmony_ci   else
816cb93a386Sopenharmony_ci#  endif
817cb93a386Sopenharmony_ci
818cb93a386Sopenharmony_ci   {
819cb93a386Sopenharmony_ci      fprintf(stderr, "libpng warning: %s", warning_message);
820cb93a386Sopenharmony_ci      fprintf(stderr, PNG_STRING_NEWLINE);
821cb93a386Sopenharmony_ci   }
822cb93a386Sopenharmony_ci#else
823cb93a386Sopenharmony_ci   PNG_UNUSED(warning_message) /* Make compiler happy */
824cb93a386Sopenharmony_ci#endif
825cb93a386Sopenharmony_ci   PNG_UNUSED(png_ptr) /* Make compiler happy */
826cb93a386Sopenharmony_ci}
827cb93a386Sopenharmony_ci#endif /* WARNINGS */
828cb93a386Sopenharmony_ci
829cb93a386Sopenharmony_ci/* This function is called when the application wants to use another method
830cb93a386Sopenharmony_ci * of handling errors and warnings.  Note that the error function MUST NOT
831cb93a386Sopenharmony_ci * return to the calling routine or serious problems will occur.  The return
832cb93a386Sopenharmony_ci * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
833cb93a386Sopenharmony_ci */
834cb93a386Sopenharmony_civoid PNGAPI
835cb93a386Sopenharmony_cipng_set_error_fn(png_structrp png_ptr, png_voidp error_ptr,
836cb93a386Sopenharmony_ci    png_error_ptr error_fn, png_error_ptr warning_fn)
837cb93a386Sopenharmony_ci{
838cb93a386Sopenharmony_ci   if (png_ptr == NULL)
839cb93a386Sopenharmony_ci      return;
840cb93a386Sopenharmony_ci
841cb93a386Sopenharmony_ci   png_ptr->error_ptr = error_ptr;
842cb93a386Sopenharmony_ci   png_ptr->error_fn = error_fn;
843cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED
844cb93a386Sopenharmony_ci   png_ptr->warning_fn = warning_fn;
845cb93a386Sopenharmony_ci#else
846cb93a386Sopenharmony_ci   PNG_UNUSED(warning_fn)
847cb93a386Sopenharmony_ci#endif
848cb93a386Sopenharmony_ci}
849cb93a386Sopenharmony_ci
850cb93a386Sopenharmony_ci
851cb93a386Sopenharmony_ci/* This function returns a pointer to the error_ptr associated with the user
852cb93a386Sopenharmony_ci * functions.  The application should free any memory associated with this
853cb93a386Sopenharmony_ci * pointer before png_write_destroy and png_read_destroy are called.
854cb93a386Sopenharmony_ci */
855cb93a386Sopenharmony_cipng_voidp PNGAPI
856cb93a386Sopenharmony_cipng_get_error_ptr(png_const_structrp png_ptr)
857cb93a386Sopenharmony_ci{
858cb93a386Sopenharmony_ci   if (png_ptr == NULL)
859cb93a386Sopenharmony_ci      return NULL;
860cb93a386Sopenharmony_ci
861cb93a386Sopenharmony_ci   return ((png_voidp)png_ptr->error_ptr);
862cb93a386Sopenharmony_ci}
863cb93a386Sopenharmony_ci
864cb93a386Sopenharmony_ci
865cb93a386Sopenharmony_ci#ifdef PNG_ERROR_NUMBERS_SUPPORTED
866cb93a386Sopenharmony_civoid PNGAPI
867cb93a386Sopenharmony_cipng_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
868cb93a386Sopenharmony_ci{
869cb93a386Sopenharmony_ci   if (png_ptr != NULL)
870cb93a386Sopenharmony_ci   {
871cb93a386Sopenharmony_ci      png_ptr->flags &=
872cb93a386Sopenharmony_ci         ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
873cb93a386Sopenharmony_ci         PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
874cb93a386Sopenharmony_ci   }
875cb93a386Sopenharmony_ci}
876cb93a386Sopenharmony_ci#endif
877cb93a386Sopenharmony_ci
878cb93a386Sopenharmony_ci#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
879cb93a386Sopenharmony_ci   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
880cb93a386Sopenharmony_ci   /* Currently the above both depend on SETJMP_SUPPORTED, however it would be
881cb93a386Sopenharmony_ci    * possible to implement without setjmp support just so long as there is some
882cb93a386Sopenharmony_ci    * way to handle the error return here:
883cb93a386Sopenharmony_ci    */
884cb93a386Sopenharmony_ciPNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
885cb93a386Sopenharmony_cipng_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
886cb93a386Sopenharmony_ci    PNG_NORETURN)
887cb93a386Sopenharmony_ci{
888cb93a386Sopenharmony_ci   png_const_structrp png_ptr = png_nonconst_ptr;
889cb93a386Sopenharmony_ci   png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
890cb93a386Sopenharmony_ci
891cb93a386Sopenharmony_ci   /* An error is always logged here, overwriting anything (typically a warning)
892cb93a386Sopenharmony_ci    * that is already there:
893cb93a386Sopenharmony_ci    */
894cb93a386Sopenharmony_ci   if (image != NULL)
895cb93a386Sopenharmony_ci   {
896cb93a386Sopenharmony_ci      png_safecat(image->message, (sizeof image->message), 0, error_message);
897cb93a386Sopenharmony_ci      image->warning_or_error |= PNG_IMAGE_ERROR;
898cb93a386Sopenharmony_ci
899cb93a386Sopenharmony_ci      /* Retrieve the jmp_buf from within the png_control, making this work for
900cb93a386Sopenharmony_ci       * C++ compilation too is pretty tricky: C++ wants a pointer to the first
901cb93a386Sopenharmony_ci       * element of a jmp_buf, but C doesn't tell us the type of that.
902cb93a386Sopenharmony_ci       */
903cb93a386Sopenharmony_ci      if (image->opaque != NULL && image->opaque->error_buf != NULL)
904cb93a386Sopenharmony_ci         longjmp(png_control_jmp_buf(image->opaque), 1);
905cb93a386Sopenharmony_ci
906cb93a386Sopenharmony_ci      /* Missing longjmp buffer, the following is to help debugging: */
907cb93a386Sopenharmony_ci      {
908cb93a386Sopenharmony_ci         size_t pos = png_safecat(image->message, (sizeof image->message), 0,
909cb93a386Sopenharmony_ci             "bad longjmp: ");
910cb93a386Sopenharmony_ci         png_safecat(image->message, (sizeof image->message), pos,
911cb93a386Sopenharmony_ci             error_message);
912cb93a386Sopenharmony_ci      }
913cb93a386Sopenharmony_ci   }
914cb93a386Sopenharmony_ci
915cb93a386Sopenharmony_ci   /* Here on an internal programming error. */
916cb93a386Sopenharmony_ci   abort();
917cb93a386Sopenharmony_ci}
918cb93a386Sopenharmony_ci
919cb93a386Sopenharmony_ci#ifdef PNG_WARNINGS_SUPPORTED
920cb93a386Sopenharmony_civoid /* PRIVATE */ PNGCBAPI
921cb93a386Sopenharmony_cipng_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
922cb93a386Sopenharmony_ci{
923cb93a386Sopenharmony_ci   png_const_structrp png_ptr = png_nonconst_ptr;
924cb93a386Sopenharmony_ci   png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
925cb93a386Sopenharmony_ci
926cb93a386Sopenharmony_ci   /* A warning is only logged if there is no prior warning or error. */
927cb93a386Sopenharmony_ci   if (image->warning_or_error == 0)
928cb93a386Sopenharmony_ci   {
929cb93a386Sopenharmony_ci      png_safecat(image->message, (sizeof image->message), 0, warning_message);
930cb93a386Sopenharmony_ci      image->warning_or_error |= PNG_IMAGE_WARNING;
931cb93a386Sopenharmony_ci   }
932cb93a386Sopenharmony_ci}
933cb93a386Sopenharmony_ci#endif
934cb93a386Sopenharmony_ci
935cb93a386Sopenharmony_ciint /* PRIVATE */
936cb93a386Sopenharmony_cipng_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
937cb93a386Sopenharmony_ci{
938cb93a386Sopenharmony_ci   volatile png_imagep image = image_in;
939cb93a386Sopenharmony_ci   volatile int result;
940cb93a386Sopenharmony_ci   volatile png_voidp saved_error_buf;
941cb93a386Sopenharmony_ci   jmp_buf safe_jmpbuf;
942cb93a386Sopenharmony_ci
943cb93a386Sopenharmony_ci   /* Safely execute function(arg) with png_error returning to this function. */
944cb93a386Sopenharmony_ci   saved_error_buf = image->opaque->error_buf;
945cb93a386Sopenharmony_ci   result = setjmp(safe_jmpbuf) == 0;
946cb93a386Sopenharmony_ci
947cb93a386Sopenharmony_ci   if (result != 0)
948cb93a386Sopenharmony_ci   {
949cb93a386Sopenharmony_ci
950cb93a386Sopenharmony_ci      image->opaque->error_buf = safe_jmpbuf;
951cb93a386Sopenharmony_ci      result = function(arg);
952cb93a386Sopenharmony_ci   }
953cb93a386Sopenharmony_ci
954cb93a386Sopenharmony_ci   image->opaque->error_buf = saved_error_buf;
955cb93a386Sopenharmony_ci
956cb93a386Sopenharmony_ci   /* And do the cleanup prior to any failure return. */
957cb93a386Sopenharmony_ci   if (result == 0)
958cb93a386Sopenharmony_ci      png_image_free(image);
959cb93a386Sopenharmony_ci
960cb93a386Sopenharmony_ci   return result;
961cb93a386Sopenharmony_ci}
962cb93a386Sopenharmony_ci#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
963cb93a386Sopenharmony_ci#endif /* READ || WRITE */
964