CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/libpng17/pngerror.c
Views: 1401
1
2
/* pngerror.c - stub functions for i/o and memory allocation
3
*
4
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
5
* Copyright (c) 1998-2002,2004,2006-2016 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
#include "pngpriv.h"
20
#define PNG_SRC_FILE PNG_SRC_FILE_pngerror
21
22
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
23
24
static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
25
png_const_charp error_message)),PNG_NORETURN);
26
27
#ifdef PNG_WARNINGS_SUPPORTED
28
static void /* PRIVATE */
29
png_default_warning PNGARG((png_const_structrp png_ptr,
30
png_const_charp warning_message));
31
#endif /* WARNINGS */
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
PNG_FUNCTION(void,PNGAPI
40
png_error,(png_const_structrp png_ptr, png_const_charp error_message),
41
PNG_NORETURN)
42
{
43
if (png_ptr != NULL && png_ptr->error_fn != NULL)
44
(*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
45
error_message);
46
47
/* If the custom handler doesn't exist, or if it returns,
48
use the default handler, which will not return. */
49
png_default_error(png_ptr, error_message);
50
}
51
#else
52
PNG_FUNCTION(void,PNGAPI
53
png_err,(png_const_structrp png_ptr),PNG_NORETURN)
54
{
55
/* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
56
* erroneously as '\0', instead of the empty string "". This was
57
* apparently an error, introduced in libpng-1.2.20, and png_default_error
58
* will crash in this case.
59
*/
60
if (png_ptr != NULL && png_ptr->error_fn != NULL)
61
(*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
62
63
/* If the custom handler doesn't exist, or if it returns,
64
use the default handler, which will not return. */
65
png_default_error(png_ptr, "");
66
}
67
#endif /* ERROR_TEXT */
68
69
/* Utility to safely appends strings to a buffer. This never errors out so
70
* error checking is not required in the caller.
71
*/
72
size_t
73
png_safecat(png_charp buffer, size_t bufsize, size_t pos,
74
png_const_charp string)
75
{
76
if (buffer != NULL && pos < bufsize)
77
{
78
if (string != NULL)
79
while (*string != '\0' && pos < bufsize-1)
80
buffer[pos++] = *string++;
81
82
buffer[pos] = '\0';
83
}
84
85
return pos;
86
}
87
88
#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
89
/* Utility to dump an unsigned value into a buffer, given a start pointer and
90
* and end pointer (which should point just *beyond* the end of the buffer!)
91
* Returns the pointer to the start of the formatted string.
92
*/
93
#define PNG_HAVE_FORMAT_NUMBER /* for the code below */
94
png_charp
95
png_format_number(png_const_charp start, png_charp end, int format,
96
png_alloc_size_t number)
97
{
98
int count = 0; /* number of digits output */
99
int mincount = 1; /* minimum number required */
100
int output = 0; /* digit output (for the fixed point format) */
101
102
*--end = '\0';
103
104
/* This is written so that the loop always runs at least once, even with
105
* number zero.
106
*/
107
while (end > start && (number != 0 || count < mincount))
108
{
109
110
static const char digits[] = "0123456789ABCDEF";
111
112
switch (format)
113
{
114
case PNG_NUMBER_FORMAT_fixed:
115
/* Needs five digits (the fraction) */
116
mincount = 5;
117
if (output != 0 || number % 10 != 0)
118
{
119
*--end = digits[number % 10];
120
output = 1;
121
}
122
number /= 10;
123
break;
124
125
case PNG_NUMBER_FORMAT_02u:
126
/* Expects at least 2 digits. */
127
mincount = 2;
128
/* FALL THROUGH */
129
130
case PNG_NUMBER_FORMAT_u:
131
*--end = digits[number % 10];
132
number /= 10;
133
break;
134
135
case PNG_NUMBER_FORMAT_02x:
136
/* This format expects at least two digits */
137
mincount = 2;
138
/* FALL THROUGH */
139
140
case PNG_NUMBER_FORMAT_x:
141
*--end = digits[number & 0xf];
142
number >>= 4;
143
break;
144
145
default: /* an error */
146
number = 0;
147
break;
148
}
149
150
/* Keep track of the number of digits added */
151
++count;
152
153
/* Float a fixed number here: */
154
if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
155
{
156
/* End of the fraction, but maybe nothing was output? In that case
157
* drop the decimal point. If the number is a true zero handle that
158
* here.
159
*/
160
if (output != 0)
161
*--end = '.';
162
else if (number == 0) /* and !output */
163
*--end = '0';
164
}
165
}
166
167
return end;
168
}
169
#endif
170
171
#ifdef PNG_WARNINGS_SUPPORTED
172
/* This function is called whenever there is a non-fatal error. This function
173
* should not be changed. If there is a need to handle warnings differently,
174
* you should supply a replacement warning function and use
175
* png_set_error_fn() to replace the warning function at run-time.
176
*/
177
void PNGAPI
178
png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
179
{
180
int offset = 0;
181
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
182
(*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
183
warning_message + offset);
184
else
185
png_default_warning(png_ptr, warning_message + offset);
186
}
187
188
/* These functions support 'formatted' warning messages with up to
189
* PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter
190
* is introduced by @<number>, where 'number' starts at 1. This follows the
191
* standard established by X/Open for internationalizable error messages.
192
*/
193
void
194
png_warning_parameter(png_warning_parameters p, int number,
195
png_const_charp string)
196
{
197
if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
198
(void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
199
}
200
201
void
202
png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
203
png_alloc_size_t value)
204
{
205
char buffer[PNG_NUMBER_BUFFER_SIZE];
206
png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
207
}
208
209
void
210
png_warning_parameter_signed(png_warning_parameters p, int number, int format,
211
png_int_32 value)
212
{
213
png_alloc_size_t u;
214
png_charp str;
215
char buffer[PNG_NUMBER_BUFFER_SIZE];
216
217
/* Avoid overflow by doing the negate in a png_alloc_size_t: */
218
u = (png_alloc_size_t)value;
219
if (value < 0)
220
u = ~u + 1;
221
222
str = PNG_FORMAT_NUMBER(buffer, format, u);
223
224
if (value < 0 && str > buffer)
225
*--str = '-';
226
227
png_warning_parameter(p, number, str);
228
}
229
230
void
231
png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
232
png_const_charp message)
233
{
234
/* The internal buffer is just 192 bytes - enough for all our messages,
235
* overflow doesn't happen because this code checks! If someone figures
236
* out how to send us a message longer than 192 bytes, all that will
237
* happen is that the message will be truncated appropriately.
238
*/
239
size_t i = 0; /* Index in the msg[] buffer: */
240
char msg[192];
241
242
/* Each iteration through the following loop writes at most one character
243
* to msg[i++] then returns here to validate that there is still space for
244
* the trailing '\0'. It may (in the case of a parameter) read more than
245
* one character from message[]; it must check for '\0' and continue to the
246
* test if it finds the end of string.
247
*/
248
while (i<(sizeof msg)-1 && *message != '\0')
249
{
250
/* '@' at end of string is now just printed (previously it was skipped);
251
* it is an error in the calling code to terminate the string with @.
252
*/
253
if (p != NULL && *message == '@' && message[1] != '\0')
254
{
255
int parameter_char = *++message; /* Consume the '@' */
256
static const char valid_parameters[] = "123456789";
257
int parameter = 0;
258
259
/* Search for the parameter digit, the index in the string is the
260
* parameter to use.
261
*/
262
while (valid_parameters[parameter] != parameter_char &&
263
valid_parameters[parameter] != '\0')
264
++parameter;
265
266
/* If the parameter digit is out of range it will just get printed. */
267
if (parameter < PNG_WARNING_PARAMETER_COUNT)
268
{
269
/* Append this parameter */
270
png_const_charp parm = p[parameter];
271
png_const_charp pend = p[parameter] + (sizeof p[parameter]);
272
273
/* No need to copy the trailing '\0' here, but there is no guarantee
274
* that parm[] has been initialized, so there is no guarantee of a
275
* trailing '\0':
276
*/
277
while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
278
msg[i++] = *parm++;
279
280
/* Consume the parameter digit too: */
281
++message;
282
continue;
283
}
284
285
/* else not a parameter and there is a character after the @ sign; just
286
* copy that. This is known not to be '\0' because of the test above.
287
*/
288
}
289
290
/* At this point *message can't be '\0', even in the bad parameter case
291
* above where there is a lone '@' at the end of the message string.
292
*/
293
msg[i++] = *message++;
294
}
295
296
/* i is always less than (sizeof msg), so: */
297
msg[i] = '\0';
298
299
/* And this is the formatted message. It may be larger than
300
* PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
301
* are not (currently) formatted.
302
*/
303
png_warning(png_ptr, msg);
304
}
305
#endif /* WARNINGS */
306
307
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
308
void PNGAPI
309
png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
310
{
311
switch (png_ptr->benign_error_action)
312
{
313
case PNG_ERROR:
314
png_chunk_error(png_ptr, error_message);
315
break;
316
317
case PNG_WARN:
318
png_chunk_warning(png_ptr, error_message);
319
break;
320
321
default: /* PNG_IGNORE */
322
break;
323
}
324
325
# ifndef PNG_ERROR_TEXT_SUPPORTED
326
PNG_UNUSED(error_message)
327
# endif
328
}
329
330
static void
331
app_error(png_const_structrp png_ptr, png_const_charp error_message,
332
unsigned int error_action)
333
{
334
switch (error_action)
335
{
336
case PNG_ERROR:
337
png_error(png_ptr, error_message);
338
break;
339
340
case PNG_WARN:
341
png_warning(png_ptr, error_message);
342
break;
343
344
default: /* PNG_IGNORE */
345
break;
346
}
347
348
# ifndef PNG_ERROR_TEXT_SUPPORTED
349
PNG_UNUSED(error_message)
350
# endif
351
}
352
353
void /* PRIVATE */
354
png_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
355
{
356
app_error(png_ptr, error_message, png_ptr->app_warning_action);
357
}
358
359
void /* PRIVATE */
360
png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
361
{
362
app_error(png_ptr, error_message, png_ptr->app_error_action);
363
}
364
#endif /* BENIGN_ERRORS */
365
366
#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
367
#if defined(PNG_WARNINGS_SUPPORTED) || \
368
(defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
369
/* These utilities are used internally to build an error message that relates
370
* to the current chunk. The chunk name comes from png_ptr->chunk_name unless
371
* png_ptr->zowner is set in which case that is used in preference. This is
372
* used to prefix the message. The message is limited in length to 63 bytes.
373
* The name characters are output as hex digits wrapped in [] if the character
374
* is invalid.
375
*
376
* Using 'zowner' means that IDAT errors at the end of the IDAT stream are still
377
* reported as from the IDAT chunks.
378
*/
379
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
380
static PNG_CONST char png_digit[16] = {
381
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
382
'A', 'B', 'C', 'D', 'E', 'F'
383
};
384
385
static void /* PRIVATE */
386
png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
387
error_message)
388
{
389
png_uint_32 chunk_name = png_ptr->zowner;
390
int iout = 0, ishift = 24;
391
392
if (chunk_name == 0)
393
chunk_name = png_ptr->chunk_name;
394
395
while (ishift >= 0)
396
{
397
int c = (int)(chunk_name >> ishift) & 0xff;
398
399
ishift -= 8;
400
if (isnonalpha(c) != 0)
401
{
402
buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
403
buffer[iout++] = png_digit[(c & 0xf0) >> 4];
404
buffer[iout++] = png_digit[c & 0x0f];
405
buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
406
}
407
408
else
409
{
410
buffer[iout++] = png_check_char(png_ptr, c);
411
}
412
}
413
414
if (error_message == NULL)
415
buffer[iout] = '\0';
416
417
else
418
{
419
int iin = 0;
420
421
buffer[iout++] = ':';
422
buffer[iout++] = ' ';
423
424
while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
425
buffer[iout++] = error_message[iin++];
426
427
/* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
428
buffer[iout] = '\0';
429
}
430
}
431
#endif /* WARNINGS || ERROR_TEXT */
432
433
#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
434
PNG_FUNCTION(void,PNGAPI
435
png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message),
436
PNG_NORETURN)
437
{
438
char msg[18+PNG_MAX_ERROR_TEXT];
439
if (png_ptr == NULL || png_ptr->chunk_name == 0U)
440
png_error(png_ptr, error_message);
441
442
else
443
{
444
png_format_buffer(png_ptr, msg, error_message);
445
png_error(png_ptr, msg);
446
}
447
}
448
#endif /* READ && ERROR_TEXT */
449
450
#ifdef PNG_WARNINGS_SUPPORTED
451
void PNGAPI
452
png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
453
{
454
char msg[18+PNG_MAX_ERROR_TEXT];
455
if (png_ptr == NULL || png_ptr->chunk_name == 0U)
456
png_warning(png_ptr, warning_message);
457
458
else
459
{
460
png_format_buffer(png_ptr, msg, warning_message);
461
png_warning(png_ptr, msg);
462
}
463
}
464
#endif /* WARNINGS */
465
466
#ifdef PNG_READ_SUPPORTED
467
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
468
void PNGAPI
469
png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
470
error_message)
471
{
472
switch (png_ptr->benign_error_action)
473
{
474
case PNG_ERROR:
475
png_chunk_error(png_ptr, error_message);
476
break;
477
478
case PNG_WARN:
479
png_chunk_warning(png_ptr, error_message);
480
break;
481
482
default: /* PNG_IGNORE */
483
break;
484
}
485
486
# ifndef PNG_ERROR_TEXT_SUPPORTED
487
PNG_UNUSED(error_message)
488
# endif
489
}
490
#endif /* BENIGN_ERRORS */
491
#endif /* READ */
492
493
void /* PRIVATE */
494
(png_chunk_report)(png_const_structrp png_ptr, png_const_charp message,
495
int error)
496
{
497
/* This is always supported, but for just read or just write it
498
* unconditionally does the right thing.
499
*/
500
# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
501
if (png_ptr->read_struct)
502
# endif
503
504
# ifdef PNG_READ_SUPPORTED
505
{
506
if (error < PNG_CHUNK_ERROR)
507
png_chunk_warning(png_ptr, message);
508
509
else if (error < PNG_CHUNK_FATAL)
510
png_chunk_benign_error(png_ptr, message);
511
512
else
513
png_chunk_error(png_ptr, message);
514
}
515
# endif
516
517
# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
518
else if (!png_ptr->read_struct)
519
# endif
520
521
# ifdef PNG_WRITE_SUPPORTED
522
{
523
if (error < PNG_CHUNK_WRITE_ERROR)
524
png_app_warning(png_ptr, message);
525
526
else if (error < PNG_CHUNK_FATAL)
527
png_app_error(png_ptr, message);
528
529
else
530
png_error(png_ptr, message);
531
}
532
# endif
533
534
# ifndef PNG_ERROR_TEXT_SUPPORTED
535
PNG_UNUSED(message)
536
# endif
537
}
538
539
#ifdef PNG_ERROR_TEXT_SUPPORTED
540
541
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
542
(defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
543
defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
544
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
545
(defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) &&\
546
defined(PNG_sCAL_SUPPORTED))
547
PNG_FUNCTION(void,
548
png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
549
{
550
# define fixed_message "fixed point overflow in "
551
# define fixed_message_ln ((sizeof fixed_message)-1)
552
int iin;
553
char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
554
memcpy(msg, fixed_message, fixed_message_ln);
555
iin = 0;
556
if (name != NULL)
557
while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
558
{
559
msg[fixed_message_ln + iin] = name[iin];
560
++iin;
561
}
562
msg[fixed_message_ln + iin] = 0;
563
png_error(png_ptr, msg);
564
}
565
#endif
566
#endif
567
568
#ifdef PNG_SETJMP_SUPPORTED
569
/* This API only exists if ANSI-C style error handling is used,
570
* otherwise it is necessary for png_default_error to be overridden.
571
*/
572
jmp_buf* PNGAPI
573
png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
574
size_t jmp_buf_size)
575
{
576
/* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
577
* and it must not change after that. Libpng doesn't care how big the
578
* buffer is, just that it doesn't change.
579
*
580
* If the buffer size is no *larger* than the size of jmp_buf when libpng is
581
* compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
582
* semantics that this call will not fail. If the size is larger, however,
583
* the buffer is allocated and this may fail, causing the function to return
584
* NULL.
585
*/
586
if (png_ptr == NULL)
587
return NULL;
588
589
if (png_ptr->jmp_buf_ptr == NULL)
590
{
591
png_ptr->jmp_buf_size = 0; /* not allocated */
592
593
if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
594
png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
595
596
else
597
{
598
png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
599
png_malloc_warn(png_ptr, jmp_buf_size));
600
601
if (png_ptr->jmp_buf_ptr == NULL)
602
return NULL; /* new NULL return on OOM */
603
604
png_ptr->jmp_buf_size = jmp_buf_size;
605
}
606
}
607
608
else /* Already allocated: check the size */
609
{
610
size_t size = png_ptr->jmp_buf_size;
611
612
if (size == 0)
613
{
614
size = (sizeof png_ptr->jmp_buf_local);
615
if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
616
{
617
/* This is an internal error in libpng: somehow we have been left
618
* with a stack allocated jmp_buf when the application regained
619
* control. It's always possible to fix this up, but for the moment
620
* this is an affirm because that makes it easy to detect.
621
*/
622
impossible("Libpng jmp_buf still allocated");
623
/* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
624
}
625
}
626
627
if (size != jmp_buf_size)
628
{
629
png_warning(png_ptr, "Application jmp_buf size changed");
630
return NULL; /* caller will probably crash: no choice here */
631
}
632
}
633
634
/* Finally fill in the function, now we have a satisfactory buffer. It is
635
* valid to change the function on every call.
636
*/
637
png_ptr->longjmp_fn = longjmp_fn;
638
return png_ptr->jmp_buf_ptr;
639
}
640
641
void /* PRIVATE */
642
png_free_jmpbuf(png_structrp png_ptr)
643
{
644
if (png_ptr != NULL)
645
{
646
jmp_buf *jb = png_ptr->jmp_buf_ptr;
647
648
/* A size of 0 is used to indicate a local, stack, allocation of the
649
* pointer; used here and in png.c
650
*/
651
if (jb != NULL && png_ptr->jmp_buf_size > 0)
652
{
653
654
/* This stuff is so that a failure to free the error control structure
655
* does not leave libpng in a state with no valid error handling: the
656
* free always succeeds, if there is an error it gets ignored.
657
*/
658
if (jb != &png_ptr->jmp_buf_local)
659
{
660
/* Make an internal, libpng, jmp_buf to return here */
661
jmp_buf free_jmp_buf;
662
663
if (!setjmp(free_jmp_buf))
664
{
665
png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
666
png_ptr->jmp_buf_size = 0; /* stack allocation */
667
png_ptr->longjmp_fn = longjmp;
668
png_free(png_ptr, jb); /* Return to setjmp on error */
669
}
670
}
671
}
672
673
/* *Always* cancel everything out: */
674
png_ptr->jmp_buf_size = 0;
675
png_ptr->jmp_buf_ptr = NULL;
676
png_ptr->longjmp_fn = 0;
677
}
678
}
679
#endif
680
681
/* This is the default error handling function. Note that replacements for
682
* this function MUST NOT RETURN, or the program will likely crash. This
683
* function is used by default, or if the program supplies NULL for the
684
* error function pointer in png_set_error_fn().
685
*/
686
static PNG_FUNCTION(void /* PRIVATE */,
687
png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
688
PNG_NORETURN)
689
{
690
#ifdef PNG_CONSOLE_IO_SUPPORTED
691
{
692
fprintf(stderr, "libpng error: %s", error_message ? error_message :
693
"undefined");
694
fprintf(stderr, PNG_STRING_NEWLINE);
695
}
696
#else
697
PNG_UNUSED(error_message) /* Make compiler happy */
698
#endif
699
png_longjmp(png_ptr, 1);
700
}
701
702
PNG_FUNCTION(void,PNGAPI
703
png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
704
{
705
#ifdef PNG_SETJMP_SUPPORTED
706
if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
707
png_ptr->jmp_buf_ptr != NULL)
708
png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
709
#else
710
PNG_UNUSED(png_ptr)
711
PNG_UNUSED(val)
712
#endif
713
714
/* If control reaches this point, png_longjmp() must not return. The only
715
* choice is to terminate the whole process (or maybe the thread); to do
716
* this the ANSI-C abort() function is used unless a different method is
717
* implemented by overriding the default configuration setting for
718
* PNG_ABORT (see scripts/pnglibconf.dfa).
719
*
720
* API change: prior to 1.7.0 PNG_ABORT was invoked as a function type macro
721
* with no arguments 'PNG_ABORT();', in 1.7.0 this is changed to a simple
722
* macro that is defined in the configuration.
723
*/
724
PNG_ABORT
725
}
726
727
#ifdef PNG_WARNINGS_SUPPORTED
728
/* This function is called when there is a warning, but the library thinks
729
* it can continue anyway. Replacement functions don't have to do anything
730
* here if you don't want them to. In the default configuration, png_ptr is
731
* not used, but it is passed in case it may be useful.
732
*/
733
static void /* PRIVATE */
734
png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
735
{
736
#ifdef PNG_CONSOLE_IO_SUPPORTED
737
{
738
fprintf(stderr, "libpng warning: %s", warning_message);
739
fprintf(stderr, PNG_STRING_NEWLINE);
740
}
741
#else
742
PNG_UNUSED(warning_message) /* Make compiler happy */
743
#endif
744
PNG_UNUSED(png_ptr) /* Make compiler happy */
745
}
746
#endif /* WARNINGS */
747
748
/* This function is called when the application wants to use another method
749
* of handling errors and warnings. Note that the error function MUST NOT
750
* return to the calling routine or serious problems will occur. The return
751
* method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
752
*/
753
void PNGAPI
754
png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr,
755
png_error_ptr error_fn, png_error_ptr warning_fn)
756
{
757
if (png_ptr == NULL)
758
return;
759
760
png_ptr->error_ptr = error_ptr;
761
png_ptr->error_fn = error_fn;
762
#ifdef PNG_WARNINGS_SUPPORTED
763
png_ptr->warning_fn = warning_fn;
764
#else
765
PNG_UNUSED(warning_fn)
766
#endif
767
}
768
769
770
/* This function returns a pointer to the error_ptr associated with the user
771
* functions. The application should free any memory associated with this
772
* pointer before png_write_destroy and png_read_destroy are called.
773
*/
774
png_voidp PNGAPI
775
png_get_error_ptr(png_const_structrp png_ptr)
776
{
777
if (png_ptr == NULL)
778
return NULL;
779
780
return ((png_voidp)png_ptr->error_ptr);
781
}
782
783
784
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
785
defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
786
/* Currently the above both depend on SETJMP_SUPPORTED, however it would be
787
* possible to implement without setjmp support just so long as there is some
788
* way to handle the error return here:
789
*/
790
PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
791
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
792
PNG_NORETURN)
793
{
794
const png_const_structrp png_ptr = png_nonconst_ptr;
795
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
796
797
/* An error is always logged here, overwriting anything (typically a warning)
798
* that is already there:
799
*/
800
if (image != NULL)
801
{
802
png_safecat(image->message, (sizeof image->message), 0, error_message);
803
image->warning_or_error |= PNG_IMAGE_ERROR;
804
805
/* Retrieve the jmp_buf from within the png_control, making this work for
806
* C++ compilation too is pretty tricky: C++ wants a pointer to the first
807
* element of a jmp_buf, but C doesn't tell us the type of that.
808
*/
809
if (image->opaque != NULL && image->opaque->error_buf != NULL)
810
longjmp(png_control_jmp_buf(image->opaque), 1);
811
812
/* Missing longjmp buffer, the following is to help debugging: */
813
{
814
size_t pos = png_safecat(image->message, (sizeof image->message), 0,
815
"bad longjmp: ");
816
png_safecat(image->message, (sizeof image->message), pos,
817
error_message);
818
}
819
}
820
821
/* Here on an internal programming error. */
822
abort();
823
}
824
825
#ifdef PNG_WARNINGS_SUPPORTED
826
void /* PRIVATE */ PNGCBAPI
827
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
828
{
829
const png_const_structrp png_ptr = png_nonconst_ptr;
830
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
831
832
/* A warning is only logged if there is no prior warning or error. */
833
if (image->warning_or_error == 0)
834
{
835
png_safecat(image->message, (sizeof image->message), 0, warning_message);
836
image->warning_or_error |= PNG_IMAGE_WARNING;
837
}
838
}
839
#endif
840
841
int /* PRIVATE */
842
png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
843
{
844
volatile png_imagep image = image_in;
845
volatile int result;
846
volatile png_voidp saved_error_buf;
847
jmp_buf safe_jmpbuf;
848
849
/* Safely execute function(arg) with png_error returning to this function. */
850
saved_error_buf = image->opaque->error_buf;
851
result = setjmp(safe_jmpbuf) == 0;
852
853
if (result != 0)
854
{
855
856
image->opaque->error_buf = safe_jmpbuf;
857
result = function(arg);
858
}
859
860
image->opaque->error_buf = saved_error_buf;
861
862
/* And do the cleanup prior to any failure return. */
863
if (result == 0)
864
png_image_free(image);
865
866
return result;
867
}
868
#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
869
870
/* Affirms: minimal code in 'STABLE' builds to return control to the
871
* application via png_error(), more verbose code followed by PNG_ABORT for
872
* all other builds to ensure that internal errors are detected.
873
*
874
* The code always produces a message if it is possible, regardless of the
875
* setting of PNG_ERROR_TEXT_SUPPORTED, except that in stable builds
876
* PNG_ERROR_TEXT_SUPPORTED is honored. See pngpriv.h for the calculation of
877
* the two control macros PNG_RELEASE_BUILD (don't abort; stable build or rc)
878
* and PNG_AFFIRM_TEXT (output text.)
879
*/
880
#if PNG_AFFIRM_TEXT
881
# ifdef PNG_HAVE_FORMAT_NUMBER
882
static size_t
883
png_affirm_number(png_charp buffer, size_t bufsize, size_t pos,
884
unsigned int number, int format)
885
{
886
char numbuf[PNG_NUMBER_BUFFER_SIZE];
887
return png_safecat(buffer, bufsize, pos,
888
png_format_number(numbuf, numbuf + sizeof numbuf, format, number));
889
}
890
# define affirm_number(a,b,c,d,e) png_affirm_number(a,b,c,d,e)
891
# else /* !HAVE_FORMAT_NUMBER */
892
static size_t
893
png_affirm_number(png_charp buffer, size_t bufsize, size_t pos,
894
unsigned int number)
895
{
896
/* binhex it; highly non-portable, assumes the ASCII character set, but
897
* if warnings are turned off then it is unlikely the text will get read
898
* anyway. This binhex variant is (48+val), where 'val' is the next 6
899
* bits of the number, so it starts as '0' (for 0) and ends at 'I' for
900
* 63. The number is wrapped in {}, so 0 comes out as '{}' and 9 comes
901
* out as '{9}' and so on.
902
*/
903
char numbuf[32];
904
int i = sizeof numbuf;
905
906
numbuf[--i] = 0;
907
numbuf[--i] = '}';
908
909
do
910
{
911
if (number > 0)
912
numbuf[--i] = (char)/*SAFE*/((number & 63) + 48), number >>= 6;
913
else
914
{
915
numbuf[--i] = '{';
916
break;
917
}
918
}
919
while (i > 0);
920
921
return png_safecat(buffer, bufsize, pos, numbuf+i);
922
}
923
# define affirm_number(a,b,c,d,e) png_affirm_number(a,b,c,d)
924
#endif /* !HAVE_FORMAT_NUMBER */
925
926
static void
927
affirm_text(png_charp buffer, size_t bufsize,
928
param_deb(png_const_charp condition) unsigned int position)
929
{
930
/* Format the 'position' number and output:
931
*
932
* "<file> <line>: affirm 'condition' failed\n"
933
* " libpng version <version> - <date>\n"
934
* " translated __DATE__ __TIME__"
935
*
936
* In the STABLE versions the output is the same for the last two lines
937
* but the first line becomes:
938
*
939
* "<position>: affirm failed"
940
*
941
* If there is no number formatting the numbers just get replaced by
942
* some binhex (see the utility above).
943
*/
944
size_t pos = 0;
945
946
# if PNG_RELEASE_BUILD /* no 'condition' parameter: minimal text */
947
pos = affirm_number(buffer, bufsize, pos, position, PNG_NUMBER_FORMAT_x);
948
pos = png_safecat(buffer, bufsize, pos, ": affirm failed");
949
# else /* !STABLE */
950
/* Break down 'position' into a file name and a line number: */
951
{
952
# define PNG_apply(f) { #f "\0", PNG_SRC_FILE_ ## f },
953
# define PNG_end { "", PNG_SRC_FILE_LAST }
954
static struct {
955
char filename[28]; /* GCC checks this size */
956
unsigned int base;
957
} fileinfo[] = { PNG_FILES };
958
# undef PNG_apply
959
# undef PNG_end
960
961
unsigned int i;
962
png_const_charp filename;
963
964
/* Do 'nfiles' this way to avoid problems with g++ where it whines
965
* about (size_t) being larger than (int), even though this is a
966
* compile time constant:
967
*/
968
# define nfiles ((sizeof fileinfo)/(sizeof (fileinfo[0])))
969
for (i=0; i < nfiles && position > fileinfo[i].base; ++i) {}
970
971
if (i == 0 || i > nfiles)
972
filename = "UNKNOWN";
973
else
974
{
975
filename = fileinfo[i-1].filename;
976
position -= fileinfo[i-1].base;
977
}
978
# undef nfiles
979
980
pos = png_safecat(buffer, bufsize, pos, filename);
981
pos = png_safecat(buffer, bufsize, pos, ".c ");
982
pos = affirm_number(buffer, bufsize, pos, position,
983
PNG_NUMBER_FORMAT_u);
984
}
985
986
pos = png_safecat(buffer, bufsize, pos, ": affirm '");
987
pos = png_safecat(buffer, bufsize, pos, condition);
988
pos = png_safecat(buffer, bufsize, pos, "' failed\n");
989
# endif /* !STABLE */
990
991
pos = png_safecat(buffer, bufsize, pos, PNG_HEADER_VERSION_STRING);
992
pos = png_safecat(buffer, bufsize, pos,
993
" translated " __DATE__ " " __TIME__);
994
}
995
996
#define affirm_text(b, c, p)\
997
do {\
998
(affirm_text)(b, sizeof b, param_deb(c) (p));\
999
} while (0)
1000
1001
#endif /* AFFIRM_TEXT */
1002
1003
PNG_FUNCTION(void,png_affirm,(png_const_structrp png_ptr,
1004
param_deb(png_const_charp condition) unsigned int position),PNG_NORETURN)
1005
{
1006
# if PNG_AFFIRM_TEXT
1007
char buffer[512];
1008
1009
affirm_text(buffer, condition, position);
1010
# else /* !AFFIRM_TEXT */
1011
PNG_UNUSED(position)
1012
# if !PNG_RELEASE_BUILD
1013
PNG_UNUSED(condition)
1014
# endif
1015
# endif /* AFFIRM_TEXT */
1016
1017
/* Now in STABLE do a png_error, but in other builds output the message
1018
* (if possible) then abort (PNG_ABORT).
1019
*/
1020
# if PNG_RELEASE_BUILD
1021
png_error(png_ptr, buffer/*macro parameter used only if ERROR_TEXT*/);
1022
# else /* !AFFIRM_ERROR */
1023
/* Use console IO if possible; this is because there is no guarantee that
1024
* the app 'warning' will output anything. For certain the simplified
1025
* API implementation just copies the message (truncated) to the image
1026
* message buffer, which makes debugging much more difficult.
1027
*
1028
* Note that it is possible that neither WARNINGS nor CONSOLE_IO are
1029
* supported; in that case no text will be output (and PNG_AFFIRM_TEXT
1030
* will be false.)
1031
*/
1032
# ifdef PNG_CONSOLE_IO_SUPPORTED
1033
fprintf(stderr, "%s\n", buffer);
1034
PNG_UNUSED(png_ptr)
1035
# elif defined PNG_WARNINGS_SUPPORTED
1036
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
1037
png_ptr->warning_fn(png_constcast(png_structrp, png_ptr), buffer);
1038
/* else no way to output the text */
1039
# else
1040
PNG_UNUSED(png_ptr)
1041
# endif
1042
1043
PNG_ABORT
1044
# endif /* AFFIRM_ERROR */
1045
}
1046
1047
#if !PNG_RELEASE_BUILD
1048
void /* PRIVATE */
1049
png_handled_affirm(png_const_structrp png_ptr, png_const_charp message,
1050
unsigned int position)
1051
{
1052
# if PNG_RELEASE_BUILD
1053
/* testing in RC: we want to return control to the caller, so do not
1054
* use png_affirm.
1055
*/
1056
char buffer[512];
1057
1058
affirm_text(buffer, message, position);
1059
1060
# ifdef PNG_CONSOLE_IO_SUPPORTED
1061
fprintf(stderr, "%s\n", buffer);
1062
# elif defined PNG_WARNINGS_SUPPORTED
1063
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
1064
png_ptr->warning_fn(png_constcast(png_structrp, png_ptr), buffer);
1065
/* else no way to output the text */
1066
# else
1067
PNG_UNUSED(png_ptr)
1068
# endif
1069
# else
1070
png_affirm(png_ptr, message, position);
1071
# endif
1072
}
1073
#endif /* !RELEASE_BUILD */
1074
1075
#ifdef PNG_RANGE_CHECK_SUPPORTED
1076
/* The character/byte checking APIs. These do their own calls to png_affirm
1077
* because the caller provides the position.
1078
*/
1079
unsigned int /* PRIVATE */
1080
png_bit_affirm(png_const_structrp png_ptr, unsigned int position,
1081
unsigned int u, unsigned int bits)
1082
{
1083
/* The following avoids overflow errors even if 'bits' is 16 or 32: */
1084
if (u <= (1U << bits)-1U)
1085
return u;
1086
1087
png_affirm(png_ptr, param_deb("(bit field) range") position);
1088
}
1089
1090
char /* PRIVATE */
1091
png_char_affirm(png_const_structrp png_ptr, unsigned int position, int c)
1092
{
1093
if (c >= CHAR_MIN && c <= CHAR_MAX)
1094
return (char)/*SAFE*/c;
1095
1096
png_affirm(png_ptr, param_deb("(char) range") position);
1097
}
1098
1099
png_byte /* PRIVATE */
1100
png_byte_affirm(png_const_structrp png_ptr, unsigned int position, int b)
1101
{
1102
/* For the type png_byte the limits.h values are ignored and we check
1103
* against the values PNG expects to store in a byte:
1104
*/
1105
if (b >= 0 && b <= 255)
1106
return (png_byte)/*SAFE*/b;
1107
1108
png_affirm(png_ptr, param_deb("PNG byte range") position);
1109
}
1110
1111
#if INT_MAX >= 65535
1112
png_uint_16 /* PRIVATE */
1113
png_u16_affirm(png_const_structrp png_ptr, unsigned int position, int b)
1114
{
1115
/* Check against the PNG 16-bit limit, as with png_byte. */
1116
if (b >= 0 && b <= 65535)
1117
return (png_uint_16)/*SAFE*/b;
1118
1119
png_affirm(png_ptr, param_deb("PNG 16-bit range") position);
1120
}
1121
#endif /* INT_MAX >= 65535 */
1122
#endif /* RANGE_CHECK */
1123
#endif /* READ || WRITE */
1124
1125