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