]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngrutil.c
Add EnableHistory support to the OSX WebKit backend.
[wxWidgets.git] / src / png / pngrutil.c
CommitLineData
0272a10d
VZ
1
2/* pngrutil.c - utilities to read a PNG file
3 *
b61cc19c
PC
4 * Last changed in libpng 1.4.4 [August 26, 2010]
5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
0272a10d
VZ
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 *
b61cc19c
PC
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 *
0272a10d
VZ
13 * This file contains routines that are only called from within
14 * libpng itself during the course of reading an image.
15 */
16
b61cc19c 17#define PNG_NO_PEDANTIC_WARNINGS
0272a10d 18#include "png.h"
b61cc19c
PC
19#ifdef PNG_READ_SUPPORTED
20#include "pngpriv.h"
0272a10d 21
0272a10d 22# define png_strtod(p,a,b) strtod(a,b)
0272a10d
VZ
23png_uint_32 PNGAPI
24png_get_uint_31(png_structp png_ptr, png_bytep buf)
25{
26 png_uint_32 i = png_get_uint_32(buf);
27 if (i > PNG_UINT_31_MAX)
b61cc19c 28 png_error(png_ptr, "PNG unsigned integer out of range");
0272a10d
VZ
29 return (i);
30}
b61cc19c 31#ifndef PNG_USE_READ_MACROS
0272a10d 32/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
b61cc19c
PC
33png_uint_32 (PNGAPI
34png_get_uint_32)(png_bytep buf)
0272a10d 35{
b61cc19c
PC
36 png_uint_32 i =
37 ((png_uint_32)(*(buf )) << 24) +
38 ((png_uint_32)(*(buf + 1)) << 16) +
39 ((png_uint_32)(*(buf + 2)) << 8) +
40 ((png_uint_32)(*(buf + 3)) ) ;
0272a10d
VZ
41
42 return (i);
43}
44
45/* Grab a signed 32-bit integer from a buffer in big-endian format. The
b61cc19c
PC
46 * data is stored in the PNG file in two's complement format and there
47 * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore
48 * the following code does a two's complement to native conversion.
49 */
50png_int_32 (PNGAPI
51png_get_int_32)(png_bytep buf)
0272a10d 52{
b61cc19c
PC
53 png_uint_32 u = png_get_uint_32(buf);
54 if ((u & 0x80000000) == 0) /* non-negative */
55 return u;
0272a10d 56
b61cc19c
PC
57 u = (u ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */
58 return -(png_int_32)u;
0272a10d
VZ
59}
60
61/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
b61cc19c
PC
62png_uint_16 (PNGAPI
63png_get_uint_16)(png_bytep buf)
0272a10d 64{
b61cc19c
PC
65 png_uint_16 i =
66 ((png_uint_32)(*buf) << 8) +
67 ((png_uint_32)(*(buf + 1)));
0272a10d
VZ
68
69 return (i);
70}
b61cc19c 71#endif /* PNG_USE_READ_MACROS */
0272a10d 72
970f6abe
VZ
73/* Read the chunk header (length + type name).
74 * Put the type name into png_ptr->chunk_name, and return the length.
75 */
76png_uint_32 /* PRIVATE */
77png_read_chunk_header(png_structp png_ptr)
78{
79 png_byte buf[8];
80 png_uint_32 length;
81
b61cc19c
PC
82#ifdef PNG_IO_STATE_SUPPORTED
83 /* Inform the I/O callback that the chunk header is being read.
84 * PNG_IO_CHUNK_HDR requires a single I/O call.
85 */
86 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
87#endif
88
89 /* Read the length and the chunk name */
970f6abe
VZ
90 png_read_data(png_ptr, buf, 8);
91 length = png_get_uint_31(png_ptr, buf);
92
b61cc19c 93 /* Put the chunk name into png_ptr->chunk_name */
970f6abe
VZ
94 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
95
96 png_debug2(0, "Reading %s chunk, length = %lu",
97 png_ptr->chunk_name, length);
98
b61cc19c 99 /* Reset the crc and run it over the chunk name */
970f6abe
VZ
100 png_reset_crc(png_ptr);
101 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
102
b61cc19c 103 /* Check to see if chunk name is valid */
970f6abe
VZ
104 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
105
b61cc19c
PC
106#ifdef PNG_IO_STATE_SUPPORTED
107 /* Inform the I/O callback that chunk data will (possibly) be read.
108 * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
109 */
110 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
111#endif
112
970f6abe
VZ
113 return length;
114}
115
0272a10d
VZ
116/* Read data, and (optionally) run it through the CRC. */
117void /* PRIVATE */
118png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
119{
b61cc19c
PC
120 if (png_ptr == NULL)
121 return;
0272a10d
VZ
122 png_read_data(png_ptr, buf, length);
123 png_calculate_crc(png_ptr, buf, length);
124}
125
126/* Optionally skip data and then check the CRC. Depending on whether we
b61cc19c
PC
127 * are reading a ancillary or critical chunk, and how the program has set
128 * things up, we may calculate the CRC on the data and print a message.
129 * Returns '1' if there was a CRC error, '0' otherwise.
130 */
0272a10d
VZ
131int /* PRIVATE */
132png_crc_finish(png_structp png_ptr, png_uint_32 skip)
133{
134 png_size_t i;
135 png_size_t istop = png_ptr->zbuf_size;
136
137 for (i = (png_size_t)skip; i > istop; i -= istop)
138 {
139 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
140 }
141 if (i)
142 {
143 png_crc_read(png_ptr, png_ptr->zbuf, i);
144 }
145
146 if (png_crc_error(png_ptr))
147 {
148 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
b61cc19c 149 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
0272a10d
VZ
150 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
151 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
152 {
153 png_chunk_warning(png_ptr, "CRC error");
154 }
155 else
156 {
b61cc19c
PC
157 png_chunk_benign_error(png_ptr, "CRC error");
158 return (0);
0272a10d
VZ
159 }
160 return (1);
161 }
162
163 return (0);
164}
165
166/* Compare the CRC stored in the PNG file with that calculated by libpng from
b61cc19c
PC
167 * the data it has read thus far.
168 */
0272a10d
VZ
169int /* PRIVATE */
170png_crc_error(png_structp png_ptr)
171{
172 png_byte crc_bytes[4];
173 png_uint_32 crc;
174 int need_crc = 1;
175
176 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
177 {
178 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
179 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
180 need_crc = 0;
181 }
182 else /* critical */
183 {
184 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
185 need_crc = 0;
186 }
187
b61cc19c
PC
188#ifdef PNG_IO_STATE_SUPPORTED
189 /* Inform the I/O callback that the chunk CRC is being read */
190 /* PNG_IO_CHUNK_CRC requires the I/O to be done at once */
191 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
192#endif
193
0272a10d
VZ
194 png_read_data(png_ptr, crc_bytes, 4);
195
196 if (need_crc)
197 {
198 crc = png_get_uint_32(crc_bytes);
199 return ((int)(crc != png_ptr->crc));
200 }
201 else
202 return (0);
203}
204
205#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
206 defined(PNG_READ_iCCP_SUPPORTED)
b61cc19c
PC
207static png_size_t
208png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
209 png_bytep output, png_size_t output_size)
0272a10d 210{
b61cc19c
PC
211 png_size_t count = 0;
212
213 png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
214 png_ptr->zstream.avail_in = size;
0272a10d 215
b61cc19c 216 while (1)
0272a10d 217 {
b61cc19c
PC
218 int ret, avail;
219
220 /* Reset the output buffer each time round - we empty it
221 * after every inflate call.
222 */
0272a10d 223 png_ptr->zstream.next_out = png_ptr->zbuf;
b61cc19c 224 png_ptr->zstream.avail_out = png_ptr->zbuf_size;
0272a10d 225
b61cc19c
PC
226 ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
227 avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
0272a10d 228
b61cc19c
PC
229 /* First copy/count any new output - but only if we didn't
230 * get an error code.
231 */
232 if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
0272a10d 233 {
b61cc19c 234 if (output != 0 && output_size > count)
0272a10d 235 {
b61cc19c
PC
236 int copy = output_size - count;
237 if (avail < copy) copy = avail;
238 png_memcpy(output + count, png_ptr->zbuf, copy);
239 }
240 count += avail;
241 }
0272a10d 242
b61cc19c
PC
243 if (ret == Z_OK)
244 continue;
0272a10d 245
b61cc19c
PC
246 /* Termination conditions - always reset the zstream, it
247 * must be left in inflateInit state.
248 */
249 png_ptr->zstream.avail_in = 0;
250 inflateReset(&png_ptr->zstream);
0272a10d 251
b61cc19c
PC
252 if (ret == Z_STREAM_END)
253 return count; /* NOTE: may be zero. */
254
255 /* Now handle the error codes - the API always returns 0
256 * and the error message is dumped into the uncompressed
257 * buffer if available.
258 */
259 {
260 PNG_CONST char *msg;
261 if (png_ptr->zstream.msg != 0)
262 msg = png_ptr->zstream.msg;
263 else
0272a10d 264 {
b61cc19c
PC
265#ifdef PNG_STDIO_SUPPORTED
266 char umsg[52];
0272a10d 267
b61cc19c 268 switch (ret)
0272a10d 269 {
b61cc19c
PC
270 case Z_BUF_ERROR:
271 msg = "Buffer error in compressed datastream in %s chunk";
272 break;
273 case Z_DATA_ERROR:
274 msg = "Data error in compressed datastream in %s chunk";
275 break;
276 default:
277 msg = "Incomplete compressed datastream in %s chunk";
278 break;
0272a10d 279 }
b61cc19c
PC
280
281 png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
282 msg = umsg;
283#else
284 msg = "Damaged compressed datastream in chunk other than IDAT";
285#endif
0272a10d 286 }
b61cc19c
PC
287
288 png_warning(png_ptr, msg);
0272a10d 289 }
b61cc19c
PC
290
291 /* 0 means an error - notice that this code simple ignores
292 * zero length compressed chunks as a result.
293 */
294 return 0;
295 }
296}
297
298/*
299 * Decompress trailing data in a chunk. The assumption is that chunkdata
300 * points at an allocated area holding the contents of a chunk with a
301 * trailing compressed part. What we get back is an allocated area
302 * holding the original prefix part and an uncompressed version of the
303 * trailing part (the malloc area passed in is freed).
304 */
305void /* PRIVATE */
306png_decompress_chunk(png_structp png_ptr, int comp_type,
307 png_size_t chunklength,
308 png_size_t prefix_size, png_size_t *newlength)
309{
310 /* The caller should guarantee this */
311 if (prefix_size > chunklength)
312 {
313 /* The recovery is to delete the chunk. */
314 png_warning(png_ptr, "invalid chunklength");
315 prefix_size = 0; /* To delete everything */
316 }
317
318 else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
319 {
320 png_size_t expanded_size = png_inflate(png_ptr,
321 (png_bytep)(png_ptr->chunkdata + prefix_size),
322 chunklength - prefix_size,
323 0/*output*/, 0/*output size*/);
324
325 /* Now check the limits on this chunk - if the limit fails the
326 * compressed data will be removed, the prefix will remain.
327 */
328#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
329 if (png_ptr->user_chunk_malloc_max &&
330 (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
0272a10d 331#else
b61cc19c
PC
332# ifdef PNG_USER_CHUNK_MALLOC_MAX
333 if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
334 prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
335# endif
336#endif
337 png_warning(png_ptr, "Exceeded size limit while expanding chunk");
338
339 /* If the size is zero either there was an error and a message
340 * has already been output (warning) or the size really is zero
341 * and we have nothing to do - the code will exit through the
342 * error case below.
343 */
344#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
345 defined(PNG_USER_CHUNK_MALLOC_MAX)
346 else
0272a10d 347#endif
b61cc19c
PC
348 if (expanded_size > 0)
349 {
350 /* Success (maybe) - really uncompress the chunk. */
351 png_size_t new_size = 0;
352 png_charp text = png_malloc_warn(png_ptr,
353 prefix_size + expanded_size + 1);
354
355 if (text != NULL)
0272a10d 356 {
970f6abe 357 png_memcpy(text, png_ptr->chunkdata, prefix_size);
b61cc19c
PC
358 new_size = png_inflate(png_ptr,
359 (png_bytep)(png_ptr->chunkdata + prefix_size),
360 chunklength - prefix_size,
361 (png_bytep)(text + prefix_size), expanded_size);
362 text[prefix_size + expanded_size] = 0; /* just in case */
0272a10d 363
b61cc19c
PC
364 if (new_size == expanded_size)
365 {
366 png_free(png_ptr, png_ptr->chunkdata);
367 png_ptr->chunkdata = text;
368 *newlength = prefix_size + expanded_size;
369 return; /* The success return! */
370 }
0272a10d 371
b61cc19c
PC
372 png_warning(png_ptr, "png_inflate logic error");
373 png_free(png_ptr, text);
374 }
375 else
376 png_warning(png_ptr, "Not enough memory to decompress chunk");
377 }
0272a10d 378 }
b61cc19c 379
0272a10d
VZ
380 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
381 {
b61cc19c 382#ifdef PNG_STDIO_SUPPORTED
0272a10d
VZ
383 char umsg[50];
384
b61cc19c
PC
385 png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
386 comp_type);
0272a10d
VZ
387 png_warning(png_ptr, umsg);
388#else
389 png_warning(png_ptr, "Unknown zTXt compression type");
390#endif
391
b61cc19c 392 /* The recovery is to simply drop the data. */
0272a10d 393 }
b61cc19c
PC
394
395 /* Generic error return - leave the prefix, delete the compressed
396 * data, reallocate the chunkdata to remove the potentially large
397 * amount of compressed data.
398 */
399 {
400 png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
401 if (text != NULL)
402 {
403 if (prefix_size > 0)
404 png_memcpy(text, png_ptr->chunkdata, prefix_size);
405 png_free(png_ptr, png_ptr->chunkdata);
406 png_ptr->chunkdata = text;
407
408 /* This is an extra zero in the 'uncompressed' part. */
409 *(png_ptr->chunkdata + prefix_size) = 0x00;
410 }
411 /* Ignore a malloc error here - it is safe. */
412 }
413
414 *newlength = prefix_size;
0272a10d
VZ
415}
416#endif
417
b61cc19c 418/* Read and check the IDHR chunk */
0272a10d
VZ
419void /* PRIVATE */
420png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
421{
422 png_byte buf[13];
423 png_uint_32 width, height;
424 int bit_depth, color_type, compression_type, filter_type;
425 int interlace_type;
426
970f6abe 427 png_debug(1, "in png_handle_IHDR");
0272a10d
VZ
428
429 if (png_ptr->mode & PNG_HAVE_IHDR)
430 png_error(png_ptr, "Out of place IHDR");
431
b61cc19c 432 /* Check the length */
0272a10d
VZ
433 if (length != 13)
434 png_error(png_ptr, "Invalid IHDR chunk");
435
436 png_ptr->mode |= PNG_HAVE_IHDR;
437
438 png_crc_read(png_ptr, buf, 13);
439 png_crc_finish(png_ptr, 0);
440
441 width = png_get_uint_31(png_ptr, buf);
442 height = png_get_uint_31(png_ptr, buf + 4);
443 bit_depth = buf[8];
444 color_type = buf[9];
445 compression_type = buf[10];
446 filter_type = buf[11];
447 interlace_type = buf[12];
448
b61cc19c 449 /* Set internal variables */
0272a10d
VZ
450 png_ptr->width = width;
451 png_ptr->height = height;
452 png_ptr->bit_depth = (png_byte)bit_depth;
453 png_ptr->interlaced = (png_byte)interlace_type;
454 png_ptr->color_type = (png_byte)color_type;
b61cc19c 455#ifdef PNG_MNG_FEATURES_SUPPORTED
0272a10d
VZ
456 png_ptr->filter_type = (png_byte)filter_type;
457#endif
458 png_ptr->compression_type = (png_byte)compression_type;
459
b61cc19c 460 /* Find number of channels */
0272a10d
VZ
461 switch (png_ptr->color_type)
462 {
463 case PNG_COLOR_TYPE_GRAY:
464 case PNG_COLOR_TYPE_PALETTE:
465 png_ptr->channels = 1;
466 break;
b61cc19c 467
0272a10d
VZ
468 case PNG_COLOR_TYPE_RGB:
469 png_ptr->channels = 3;
470 break;
b61cc19c 471
0272a10d
VZ
472 case PNG_COLOR_TYPE_GRAY_ALPHA:
473 png_ptr->channels = 2;
474 break;
b61cc19c 475
0272a10d
VZ
476 case PNG_COLOR_TYPE_RGB_ALPHA:
477 png_ptr->channels = 4;
478 break;
479 }
480
b61cc19c 481 /* Set up other useful info */
0272a10d
VZ
482 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
483 png_ptr->channels);
970f6abe
VZ
484 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
485 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
486 png_debug1(3, "channels = %d", png_ptr->channels);
487 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
0272a10d
VZ
488 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
489 color_type, interlace_type, compression_type, filter_type);
490}
491
b61cc19c 492/* Read and check the palette */
0272a10d
VZ
493void /* PRIVATE */
494png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
495{
496 png_color palette[PNG_MAX_PALETTE_LENGTH];
497 int num, i;
b61cc19c 498#ifdef PNG_POINTER_INDEXING_SUPPORTED
0272a10d
VZ
499 png_colorp pal_ptr;
500#endif
501
970f6abe 502 png_debug(1, "in png_handle_PLTE");
0272a10d
VZ
503
504 if (!(png_ptr->mode & PNG_HAVE_IHDR))
505 png_error(png_ptr, "Missing IHDR before PLTE");
b61cc19c 506
0272a10d
VZ
507 else if (png_ptr->mode & PNG_HAVE_IDAT)
508 {
509 png_warning(png_ptr, "Invalid PLTE after IDAT");
510 png_crc_finish(png_ptr, length);
511 return;
512 }
b61cc19c 513
0272a10d
VZ
514 else if (png_ptr->mode & PNG_HAVE_PLTE)
515 png_error(png_ptr, "Duplicate PLTE chunk");
516
517 png_ptr->mode |= PNG_HAVE_PLTE;
518
519 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
520 {
521 png_warning(png_ptr,
522 "Ignoring PLTE chunk in grayscale PNG");
523 png_crc_finish(png_ptr, length);
524 return;
525 }
b61cc19c 526#ifndef PNG_READ_OPT_PLTE_SUPPORTED
0272a10d
VZ
527 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
528 {
529 png_crc_finish(png_ptr, length);
530 return;
531 }
532#endif
533
534 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
535 {
536 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
537 {
538 png_warning(png_ptr, "Invalid palette chunk");
539 png_crc_finish(png_ptr, length);
540 return;
541 }
b61cc19c 542
0272a10d
VZ
543 else
544 {
545 png_error(png_ptr, "Invalid palette chunk");
546 }
547 }
548
549 num = (int)length / 3;
550
b61cc19c 551#ifdef PNG_POINTER_INDEXING_SUPPORTED
0272a10d
VZ
552 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
553 {
554 png_byte buf[3];
555
556 png_crc_read(png_ptr, buf, 3);
557 pal_ptr->red = buf[0];
558 pal_ptr->green = buf[1];
559 pal_ptr->blue = buf[2];
560 }
561#else
562 for (i = 0; i < num; i++)
563 {
564 png_byte buf[3];
565
566 png_crc_read(png_ptr, buf, 3);
b61cc19c 567 /* Don't depend upon png_color being any order */
0272a10d
VZ
568 palette[i].red = buf[0];
569 palette[i].green = buf[1];
570 palette[i].blue = buf[2];
571 }
572#endif
573
574 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
b61cc19c
PC
575 * whatever the normal CRC configuration tells us. However, if we
576 * have an RGB image, the PLTE can be considered ancillary, so
577 * we will act as though it is.
578 */
579#ifndef PNG_READ_OPT_PLTE_SUPPORTED
0272a10d
VZ
580 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
581#endif
582 {
583 png_crc_finish(png_ptr, 0);
584 }
b61cc19c 585#ifndef PNG_READ_OPT_PLTE_SUPPORTED
0272a10d
VZ
586 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
587 {
588 /* If we don't want to use the data from an ancillary chunk,
589 we have two options: an error abort, or a warning and we
590 ignore the data in this chunk (which should be OK, since
591 it's considered ancillary for a RGB or RGBA image). */
592 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
593 {
594 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
595 {
b61cc19c 596 png_chunk_benign_error(png_ptr, "CRC error");
0272a10d
VZ
597 }
598 else
599 {
600 png_chunk_warning(png_ptr, "CRC error");
601 return;
602 }
603 }
604 /* Otherwise, we (optionally) emit a warning and use the chunk. */
605 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
606 {
607 png_chunk_warning(png_ptr, "CRC error");
608 }
609 }
610#endif
611
612 png_set_PLTE(png_ptr, info_ptr, palette, num);
613
b61cc19c 614#ifdef PNG_READ_tRNS_SUPPORTED
0272a10d
VZ
615 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
616 {
617 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
618 {
619 if (png_ptr->num_trans > (png_uint_16)num)
620 {
621 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
622 png_ptr->num_trans = (png_uint_16)num;
623 }
624 if (info_ptr->num_trans > (png_uint_16)num)
625 {
626 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
627 info_ptr->num_trans = (png_uint_16)num;
628 }
629 }
630 }
631#endif
632
633}
634
635void /* PRIVATE */
636png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
637{
970f6abe 638 png_debug(1, "in png_handle_IEND");
0272a10d
VZ
639
640 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
641 {
642 png_error(png_ptr, "No image in file");
643 }
644
645 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
646
647 if (length != 0)
648 {
649 png_warning(png_ptr, "Incorrect IEND chunk length");
650 }
651 png_crc_finish(png_ptr, length);
652
b61cc19c 653 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
0272a10d
VZ
654}
655
b61cc19c 656#ifdef PNG_READ_gAMA_SUPPORTED
0272a10d
VZ
657void /* PRIVATE */
658png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
659{
660 png_fixed_point igamma;
661#ifdef PNG_FLOATING_POINT_SUPPORTED
662 float file_gamma;
663#endif
664 png_byte buf[4];
665
970f6abe 666 png_debug(1, "in png_handle_gAMA");
0272a10d
VZ
667
668 if (!(png_ptr->mode & PNG_HAVE_IHDR))
669 png_error(png_ptr, "Missing IHDR before gAMA");
670 else if (png_ptr->mode & PNG_HAVE_IDAT)
671 {
672 png_warning(png_ptr, "Invalid gAMA after IDAT");
673 png_crc_finish(png_ptr, length);
674 return;
675 }
676 else if (png_ptr->mode & PNG_HAVE_PLTE)
677 /* Should be an error, but we can cope with it */
678 png_warning(png_ptr, "Out of place gAMA chunk");
679
680 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
b61cc19c 681#ifdef PNG_READ_sRGB_SUPPORTED
0272a10d
VZ
682 && !(info_ptr->valid & PNG_INFO_sRGB)
683#endif
684 )
685 {
686 png_warning(png_ptr, "Duplicate gAMA chunk");
687 png_crc_finish(png_ptr, length);
688 return;
689 }
690
691 if (length != 4)
692 {
693 png_warning(png_ptr, "Incorrect gAMA chunk length");
694 png_crc_finish(png_ptr, length);
695 return;
696 }
697
698 png_crc_read(png_ptr, buf, 4);
699 if (png_crc_finish(png_ptr, 0))
700 return;
701
702 igamma = (png_fixed_point)png_get_uint_32(buf);
b61cc19c 703 /* Check for zero gamma */
0272a10d
VZ
704 if (igamma == 0)
705 {
706 png_warning(png_ptr,
707 "Ignoring gAMA chunk with gamma=0");
708 return;
709 }
710
b61cc19c 711#ifdef PNG_READ_sRGB_SUPPORTED
0272a10d
VZ
712 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
713 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
714 {
715 png_warning(png_ptr,
716 "Ignoring incorrect gAMA value when sRGB is also present");
b61cc19c 717#ifdef PNG_CONSOLE_IO_SUPPORTED
970f6abe 718 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
0272a10d
VZ
719#endif
720 return;
721 }
722#endif /* PNG_READ_sRGB_SUPPORTED */
723
724#ifdef PNG_FLOATING_POINT_SUPPORTED
725 file_gamma = (float)igamma / (float)100000.0;
726# ifdef PNG_READ_GAMMA_SUPPORTED
727 png_ptr->gamma = file_gamma;
728# endif
729 png_set_gAMA(png_ptr, info_ptr, file_gamma);
730#endif
731#ifdef PNG_FIXED_POINT_SUPPORTED
732 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
733#endif
734}
735#endif
736
b61cc19c 737#ifdef PNG_READ_sBIT_SUPPORTED
0272a10d
VZ
738void /* PRIVATE */
739png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
740{
741 png_size_t truelen;
742 png_byte buf[4];
743
970f6abe 744 png_debug(1, "in png_handle_sBIT");
0272a10d
VZ
745
746 buf[0] = buf[1] = buf[2] = buf[3] = 0;
747
748 if (!(png_ptr->mode & PNG_HAVE_IHDR))
749 png_error(png_ptr, "Missing IHDR before sBIT");
750 else if (png_ptr->mode & PNG_HAVE_IDAT)
751 {
752 png_warning(png_ptr, "Invalid sBIT after IDAT");
753 png_crc_finish(png_ptr, length);
754 return;
755 }
756 else if (png_ptr->mode & PNG_HAVE_PLTE)
757 {
758 /* Should be an error, but we can cope with it */
759 png_warning(png_ptr, "Out of place sBIT chunk");
760 }
761 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
762 {
763 png_warning(png_ptr, "Duplicate sBIT chunk");
764 png_crc_finish(png_ptr, length);
765 return;
766 }
767
768 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
769 truelen = 3;
770 else
771 truelen = (png_size_t)png_ptr->channels;
772
773 if (length != truelen || length > 4)
774 {
775 png_warning(png_ptr, "Incorrect sBIT chunk length");
776 png_crc_finish(png_ptr, length);
777 return;
778 }
779
780 png_crc_read(png_ptr, buf, truelen);
781 if (png_crc_finish(png_ptr, 0))
782 return;
783
784 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
785 {
786 png_ptr->sig_bit.red = buf[0];
787 png_ptr->sig_bit.green = buf[1];
788 png_ptr->sig_bit.blue = buf[2];
789 png_ptr->sig_bit.alpha = buf[3];
790 }
791 else
792 {
793 png_ptr->sig_bit.gray = buf[0];
794 png_ptr->sig_bit.red = buf[0];
795 png_ptr->sig_bit.green = buf[0];
796 png_ptr->sig_bit.blue = buf[0];
797 png_ptr->sig_bit.alpha = buf[1];
798 }
799 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
800}
801#endif
802
b61cc19c 803#ifdef PNG_READ_cHRM_SUPPORTED
0272a10d
VZ
804void /* PRIVATE */
805png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
806{
970f6abe 807 png_byte buf[32];
0272a10d
VZ
808#ifdef PNG_FLOATING_POINT_SUPPORTED
809 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
810#endif
811 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
812 int_y_green, int_x_blue, int_y_blue;
813
814 png_uint_32 uint_x, uint_y;
815
970f6abe 816 png_debug(1, "in png_handle_cHRM");
0272a10d
VZ
817
818 if (!(png_ptr->mode & PNG_HAVE_IHDR))
819 png_error(png_ptr, "Missing IHDR before cHRM");
820 else if (png_ptr->mode & PNG_HAVE_IDAT)
821 {
822 png_warning(png_ptr, "Invalid cHRM after IDAT");
823 png_crc_finish(png_ptr, length);
824 return;
825 }
826 else if (png_ptr->mode & PNG_HAVE_PLTE)
827 /* Should be an error, but we can cope with it */
828 png_warning(png_ptr, "Missing PLTE before cHRM");
829
830 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
b61cc19c 831#ifdef PNG_READ_sRGB_SUPPORTED
0272a10d
VZ
832 && !(info_ptr->valid & PNG_INFO_sRGB)
833#endif
834 )
835 {
836 png_warning(png_ptr, "Duplicate cHRM chunk");
837 png_crc_finish(png_ptr, length);
838 return;
839 }
840
841 if (length != 32)
842 {
843 png_warning(png_ptr, "Incorrect cHRM chunk length");
844 png_crc_finish(png_ptr, length);
845 return;
846 }
847
970f6abe
VZ
848 png_crc_read(png_ptr, buf, 32);
849 if (png_crc_finish(png_ptr, 0))
0272a10d 850 return;
0272a10d 851
0272a10d 852 uint_x = png_get_uint_32(buf);
970f6abe
VZ
853 uint_y = png_get_uint_32(buf + 4);
854 int_x_white = (png_fixed_point)uint_x;
855 int_y_white = (png_fixed_point)uint_y;
0272a10d 856
970f6abe
VZ
857 uint_x = png_get_uint_32(buf + 8);
858 uint_y = png_get_uint_32(buf + 12);
0272a10d
VZ
859 int_x_red = (png_fixed_point)uint_x;
860 int_y_red = (png_fixed_point)uint_y;
861
970f6abe
VZ
862 uint_x = png_get_uint_32(buf + 16);
863 uint_y = png_get_uint_32(buf + 20);
0272a10d
VZ
864 int_x_green = (png_fixed_point)uint_x;
865 int_y_green = (png_fixed_point)uint_y;
866
970f6abe
VZ
867 uint_x = png_get_uint_32(buf + 24);
868 uint_y = png_get_uint_32(buf + 28);
0272a10d
VZ
869 int_x_blue = (png_fixed_point)uint_x;
870 int_y_blue = (png_fixed_point)uint_y;
871
872#ifdef PNG_FLOATING_POINT_SUPPORTED
873 white_x = (float)int_x_white / (float)100000.0;
874 white_y = (float)int_y_white / (float)100000.0;
875 red_x = (float)int_x_red / (float)100000.0;
876 red_y = (float)int_y_red / (float)100000.0;
877 green_x = (float)int_x_green / (float)100000.0;
878 green_y = (float)int_y_green / (float)100000.0;
879 blue_x = (float)int_x_blue / (float)100000.0;
880 blue_y = (float)int_y_blue / (float)100000.0;
881#endif
882
b61cc19c 883#ifdef PNG_READ_sRGB_SUPPORTED
0272a10d
VZ
884 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
885 {
886 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
887 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
888 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
889 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
890 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
891 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
892 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
893 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
894 {
895 png_warning(png_ptr,
896 "Ignoring incorrect cHRM value when sRGB is also present");
b61cc19c 897#ifdef PNG_CONSOLE_IO_SUPPORTED
0272a10d 898#ifdef PNG_FLOATING_POINT_SUPPORTED
970f6abe 899 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
0272a10d 900 white_x, white_y, red_x, red_y);
970f6abe 901 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
0272a10d
VZ
902 green_x, green_y, blue_x, blue_y);
903#else
970f6abe 904 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
b61cc19c
PC
905 (long)int_x_white, (long)int_y_white,
906 (long)int_x_red, (long)int_y_red);
970f6abe 907 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
b61cc19c
PC
908 (long)int_x_green, (long)int_y_green,
909 (long)int_x_blue, (long)int_y_blue);
0272a10d 910#endif
b61cc19c 911#endif /* PNG_CONSOLE_IO_SUPPORTED */
0272a10d 912 }
0272a10d
VZ
913 return;
914 }
915#endif /* PNG_READ_sRGB_SUPPORTED */
916
917#ifdef PNG_FLOATING_POINT_SUPPORTED
918 png_set_cHRM(png_ptr, info_ptr,
919 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
920#endif
921#ifdef PNG_FIXED_POINT_SUPPORTED
922 png_set_cHRM_fixed(png_ptr, info_ptr,
923 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
924 int_y_green, int_x_blue, int_y_blue);
925#endif
0272a10d
VZ
926}
927#endif
928
b61cc19c 929#ifdef PNG_READ_sRGB_SUPPORTED
0272a10d
VZ
930void /* PRIVATE */
931png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
932{
933 int intent;
934 png_byte buf[1];
935
970f6abe 936 png_debug(1, "in png_handle_sRGB");
0272a10d
VZ
937
938 if (!(png_ptr->mode & PNG_HAVE_IHDR))
939 png_error(png_ptr, "Missing IHDR before sRGB");
940 else if (png_ptr->mode & PNG_HAVE_IDAT)
941 {
942 png_warning(png_ptr, "Invalid sRGB after IDAT");
943 png_crc_finish(png_ptr, length);
944 return;
945 }
946 else if (png_ptr->mode & PNG_HAVE_PLTE)
947 /* Should be an error, but we can cope with it */
948 png_warning(png_ptr, "Out of place sRGB chunk");
949
950 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
951 {
952 png_warning(png_ptr, "Duplicate sRGB chunk");
953 png_crc_finish(png_ptr, length);
954 return;
955 }
956
957 if (length != 1)
958 {
959 png_warning(png_ptr, "Incorrect sRGB chunk length");
960 png_crc_finish(png_ptr, length);
961 return;
962 }
963
964 png_crc_read(png_ptr, buf, 1);
965 if (png_crc_finish(png_ptr, 0))
966 return;
967
968 intent = buf[0];
b61cc19c 969 /* Check for bad intent */
0272a10d
VZ
970 if (intent >= PNG_sRGB_INTENT_LAST)
971 {
972 png_warning(png_ptr, "Unknown sRGB intent");
973 return;
974 }
975
976#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
977 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
978 {
979 png_fixed_point igamma;
980#ifdef PNG_FIXED_POINT_SUPPORTED
981 igamma=info_ptr->int_gamma;
982#else
983# ifdef PNG_FLOATING_POINT_SUPPORTED
984 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
985# endif
986#endif
987 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
988 {
989 png_warning(png_ptr,
990 "Ignoring incorrect gAMA value when sRGB is also present");
b61cc19c 991#ifdef PNG_CONSOLE_IO_SUPPORTED
0272a10d 992# ifdef PNG_FIXED_POINT_SUPPORTED
970f6abe
VZ
993 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
994 (int)png_ptr->int_gamma);
0272a10d
VZ
995# else
996# ifdef PNG_FLOATING_POINT_SUPPORTED
970f6abe 997 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
0272a10d
VZ
998# endif
999# endif
1000#endif
1001 }
1002 }
1003#endif /* PNG_READ_gAMA_SUPPORTED */
1004
1005#ifdef PNG_READ_cHRM_SUPPORTED
1006#ifdef PNG_FIXED_POINT_SUPPORTED
1007 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
1008 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
1009 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
1010 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
1011 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
1012 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
1013 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
1014 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
1015 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
1016 {
1017 png_warning(png_ptr,
1018 "Ignoring incorrect cHRM value when sRGB is also present");
1019 }
1020#endif /* PNG_FIXED_POINT_SUPPORTED */
1021#endif /* PNG_READ_cHRM_SUPPORTED */
1022
1023 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1024}
1025#endif /* PNG_READ_sRGB_SUPPORTED */
1026
b61cc19c 1027#ifdef PNG_READ_iCCP_SUPPORTED
0272a10d
VZ
1028void /* PRIVATE */
1029png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1030/* Note: this does not properly handle chunks that are > 64K under DOS */
1031{
0272a10d
VZ
1032 png_byte compression_type;
1033 png_bytep pC;
1034 png_charp profile;
1035 png_uint_32 skip = 0;
1036 png_uint_32 profile_size, profile_length;
1037 png_size_t slength, prefix_length, data_length;
1038
970f6abe 1039 png_debug(1, "in png_handle_iCCP");
0272a10d
VZ
1040
1041 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1042 png_error(png_ptr, "Missing IHDR before iCCP");
1043 else if (png_ptr->mode & PNG_HAVE_IDAT)
1044 {
1045 png_warning(png_ptr, "Invalid iCCP after IDAT");
1046 png_crc_finish(png_ptr, length);
1047 return;
1048 }
1049 else if (png_ptr->mode & PNG_HAVE_PLTE)
1050 /* Should be an error, but we can cope with it */
1051 png_warning(png_ptr, "Out of place iCCP chunk");
1052
1053 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1054 {
1055 png_warning(png_ptr, "Duplicate iCCP chunk");
1056 png_crc_finish(png_ptr, length);
1057 return;
1058 }
1059
1060#ifdef PNG_MAX_MALLOC_64K
1061 if (length > (png_uint_32)65535L)
1062 {
1063 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1064 skip = length - (png_uint_32)65535L;
1065 length = (png_uint_32)65535L;
1066 }
1067#endif
1068
970f6abe
VZ
1069 png_free(png_ptr, png_ptr->chunkdata);
1070 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
0272a10d 1071 slength = (png_size_t)length;
970f6abe 1072 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1073
1074 if (png_crc_finish(png_ptr, skip))
1075 {
970f6abe
VZ
1076 png_free(png_ptr, png_ptr->chunkdata);
1077 png_ptr->chunkdata = NULL;
0272a10d
VZ
1078 return;
1079 }
1080
970f6abe 1081 png_ptr->chunkdata[slength] = 0x00;
0272a10d 1082
970f6abe 1083 for (profile = png_ptr->chunkdata; *profile; profile++)
b61cc19c 1084 /* Empty loop to find end of name */ ;
0272a10d
VZ
1085
1086 ++profile;
1087
b61cc19c
PC
1088 /* There should be at least one zero (the compression type byte)
1089 * following the separator, and we should be on it
1090 */
970f6abe 1091 if ( profile >= png_ptr->chunkdata + slength - 1)
0272a10d 1092 {
970f6abe
VZ
1093 png_free(png_ptr, png_ptr->chunkdata);
1094 png_ptr->chunkdata = NULL;
0272a10d
VZ
1095 png_warning(png_ptr, "Malformed iCCP chunk");
1096 return;
1097 }
1098
b61cc19c 1099 /* Compression_type should always be zero */
0272a10d
VZ
1100 compression_type = *profile++;
1101 if (compression_type)
1102 {
1103 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
970f6abe 1104 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
0272a10d
VZ
1105 wrote nonzero) */
1106 }
1107
970f6abe
VZ
1108 prefix_length = profile - png_ptr->chunkdata;
1109 png_decompress_chunk(png_ptr, compression_type,
1110 slength, prefix_length, &data_length);
0272a10d
VZ
1111
1112 profile_length = data_length - prefix_length;
1113
1114 if ( prefix_length > data_length || profile_length < 4)
1115 {
970f6abe
VZ
1116 png_free(png_ptr, png_ptr->chunkdata);
1117 png_ptr->chunkdata = NULL;
0272a10d
VZ
1118 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1119 return;
1120 }
1121
1122 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
970f6abe
VZ
1123 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1124 profile_size = ((*(pC ))<<24) |
1125 ((*(pC + 1))<<16) |
1126 ((*(pC + 2))<< 8) |
1127 ((*(pC + 3)) );
0272a10d 1128
970f6abe 1129 if (profile_size < profile_length)
0272a10d
VZ
1130 profile_length = profile_size;
1131
970f6abe 1132 if (profile_size > profile_length)
0272a10d 1133 {
b61cc19c
PC
1134#ifdef PNG_STDIO_SUPPORTED
1135 char umsg[50];
1136#endif
970f6abe
VZ
1137 png_free(png_ptr, png_ptr->chunkdata);
1138 png_ptr->chunkdata = NULL;
b61cc19c
PC
1139 png_warning(png_ptr, "Ignoring truncated iCCP profile");
1140#ifdef PNG_STDIO_SUPPORTED
1141
1142 png_snprintf(umsg, 50, "declared profile size = %lu",
1143 (unsigned long)profile_size);
1144 png_warning(png_ptr, umsg);
1145 png_snprintf(umsg, 50, "actual profile length = %lu",
1146 (unsigned long)profile_length);
1147 png_warning(png_ptr, umsg);
1148#endif
0272a10d
VZ
1149 return;
1150 }
1151
970f6abe
VZ
1152 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1153 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1154 png_free(png_ptr, png_ptr->chunkdata);
1155 png_ptr->chunkdata = NULL;
0272a10d
VZ
1156}
1157#endif /* PNG_READ_iCCP_SUPPORTED */
1158
b61cc19c 1159#ifdef PNG_READ_sPLT_SUPPORTED
0272a10d
VZ
1160void /* PRIVATE */
1161png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1162/* Note: this does not properly handle chunks that are > 64K under DOS */
1163{
0272a10d
VZ
1164 png_bytep entry_start;
1165 png_sPLT_t new_palette;
b61cc19c 1166#ifdef PNG_POINTER_INDEXING_SUPPORTED
0272a10d
VZ
1167 png_sPLT_entryp pp;
1168#endif
1169 int data_length, entry_size, i;
1170 png_uint_32 skip = 0;
1171 png_size_t slength;
1172
970f6abe 1173 png_debug(1, "in png_handle_sPLT");
0272a10d 1174
b61cc19c
PC
1175#ifdef PNG_USER_LIMITS_SUPPORTED
1176
1177 if (png_ptr->user_chunk_cache_max != 0)
1178 {
1179 if (png_ptr->user_chunk_cache_max == 1)
1180 {
1181 png_crc_finish(png_ptr, length);
1182 return;
1183 }
1184 if (--png_ptr->user_chunk_cache_max == 1)
1185 {
1186 png_warning(png_ptr, "No space in chunk cache for sPLT");
1187 png_crc_finish(png_ptr, length);
1188 return;
1189 }
1190 }
1191#endif
1192
0272a10d
VZ
1193 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1194 png_error(png_ptr, "Missing IHDR before sPLT");
1195 else if (png_ptr->mode & PNG_HAVE_IDAT)
1196 {
1197 png_warning(png_ptr, "Invalid sPLT after IDAT");
1198 png_crc_finish(png_ptr, length);
1199 return;
1200 }
1201
1202#ifdef PNG_MAX_MALLOC_64K
1203 if (length > (png_uint_32)65535L)
1204 {
1205 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1206 skip = length - (png_uint_32)65535L;
1207 length = (png_uint_32)65535L;
1208 }
1209#endif
1210
970f6abe
VZ
1211 png_free(png_ptr, png_ptr->chunkdata);
1212 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
0272a10d 1213 slength = (png_size_t)length;
970f6abe 1214 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1215
1216 if (png_crc_finish(png_ptr, skip))
1217 {
970f6abe
VZ
1218 png_free(png_ptr, png_ptr->chunkdata);
1219 png_ptr->chunkdata = NULL;
0272a10d
VZ
1220 return;
1221 }
1222
970f6abe 1223 png_ptr->chunkdata[slength] = 0x00;
0272a10d 1224
b61cc19c
PC
1225 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1226 entry_start++)
1227 /* Empty loop to find end of name */ ;
0272a10d
VZ
1228 ++entry_start;
1229
b61cc19c 1230 /* A sample depth should follow the separator, and we should be on it */
970f6abe 1231 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
0272a10d 1232 {
970f6abe
VZ
1233 png_free(png_ptr, png_ptr->chunkdata);
1234 png_ptr->chunkdata = NULL;
0272a10d
VZ
1235 png_warning(png_ptr, "malformed sPLT chunk");
1236 return;
1237 }
1238
1239 new_palette.depth = *entry_start++;
1240 entry_size = (new_palette.depth == 8 ? 6 : 10);
970f6abe 1241 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
0272a10d 1242
b61cc19c 1243 /* Integrity-check the data length */
0272a10d
VZ
1244 if (data_length % entry_size)
1245 {
970f6abe
VZ
1246 png_free(png_ptr, png_ptr->chunkdata);
1247 png_ptr->chunkdata = NULL;
0272a10d
VZ
1248 png_warning(png_ptr, "sPLT chunk has bad length");
1249 return;
1250 }
1251
1252 new_palette.nentries = (png_int_32) ( data_length / entry_size);
970f6abe
VZ
1253 if ((png_uint_32) new_palette.nentries >
1254 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
0272a10d
VZ
1255 {
1256 png_warning(png_ptr, "sPLT chunk too long");
1257 return;
1258 }
1259 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1260 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1261 if (new_palette.entries == NULL)
1262 {
1263 png_warning(png_ptr, "sPLT chunk requires too much memory");
1264 return;
1265 }
1266
b61cc19c 1267#ifdef PNG_POINTER_INDEXING_SUPPORTED
0272a10d
VZ
1268 for (i = 0; i < new_palette.nentries; i++)
1269 {
b61cc19c 1270 pp = new_palette.entries + i;
0272a10d
VZ
1271
1272 if (new_palette.depth == 8)
1273 {
1274 pp->red = *entry_start++;
1275 pp->green = *entry_start++;
1276 pp->blue = *entry_start++;
1277 pp->alpha = *entry_start++;
1278 }
1279 else
1280 {
1281 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1282 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1283 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1284 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1285 }
1286 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1287 }
1288#else
1289 pp = new_palette.entries;
1290 for (i = 0; i < new_palette.nentries; i++)
1291 {
1292
1293 if (new_palette.depth == 8)
1294 {
1295 pp[i].red = *entry_start++;
1296 pp[i].green = *entry_start++;
1297 pp[i].blue = *entry_start++;
1298 pp[i].alpha = *entry_start++;
1299 }
1300 else
1301 {
1302 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1303 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1304 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1305 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1306 }
1307 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1308 }
1309#endif
1310
b61cc19c 1311 /* Discard all chunk data except the name and stash that */
970f6abe 1312 new_palette.name = png_ptr->chunkdata;
0272a10d
VZ
1313
1314 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1315
970f6abe
VZ
1316 png_free(png_ptr, png_ptr->chunkdata);
1317 png_ptr->chunkdata = NULL;
0272a10d
VZ
1318 png_free(png_ptr, new_palette.entries);
1319}
1320#endif /* PNG_READ_sPLT_SUPPORTED */
1321
b61cc19c 1322#ifdef PNG_READ_tRNS_SUPPORTED
0272a10d
VZ
1323void /* PRIVATE */
1324png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1325{
1326 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
0272a10d 1327
970f6abe 1328 png_debug(1, "in png_handle_tRNS");
0272a10d
VZ
1329
1330 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1331 png_error(png_ptr, "Missing IHDR before tRNS");
1332 else if (png_ptr->mode & PNG_HAVE_IDAT)
1333 {
1334 png_warning(png_ptr, "Invalid tRNS after IDAT");
1335 png_crc_finish(png_ptr, length);
1336 return;
1337 }
1338 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1339 {
1340 png_warning(png_ptr, "Duplicate tRNS chunk");
1341 png_crc_finish(png_ptr, length);
1342 return;
1343 }
1344
1345 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1346 {
1347 png_byte buf[2];
1348
1349 if (length != 2)
1350 {
1351 png_warning(png_ptr, "Incorrect tRNS chunk length");
1352 png_crc_finish(png_ptr, length);
1353 return;
1354 }
1355
1356 png_crc_read(png_ptr, buf, 2);
1357 png_ptr->num_trans = 1;
b61cc19c 1358 png_ptr->trans_color.gray = png_get_uint_16(buf);
0272a10d
VZ
1359 }
1360 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1361 {
1362 png_byte buf[6];
1363
1364 if (length != 6)
1365 {
1366 png_warning(png_ptr, "Incorrect tRNS chunk length");
1367 png_crc_finish(png_ptr, length);
1368 return;
1369 }
1370 png_crc_read(png_ptr, buf, (png_size_t)length);
1371 png_ptr->num_trans = 1;
b61cc19c
PC
1372 png_ptr->trans_color.red = png_get_uint_16(buf);
1373 png_ptr->trans_color.green = png_get_uint_16(buf + 2);
1374 png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
0272a10d
VZ
1375 }
1376 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1377 {
1378 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1379 {
1380 /* Should be an error, but we can cope with it. */
1381 png_warning(png_ptr, "Missing PLTE before tRNS");
1382 }
1383 if (length > (png_uint_32)png_ptr->num_palette ||
1384 length > PNG_MAX_PALETTE_LENGTH)
1385 {
1386 png_warning(png_ptr, "Incorrect tRNS chunk length");
1387 png_crc_finish(png_ptr, length);
1388 return;
1389 }
1390 if (length == 0)
1391 {
1392 png_warning(png_ptr, "Zero length tRNS chunk");
1393 png_crc_finish(png_ptr, length);
1394 return;
1395 }
1396 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1397 png_ptr->num_trans = (png_uint_16)length;
1398 }
1399 else
1400 {
1401 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1402 png_crc_finish(png_ptr, length);
1403 return;
1404 }
1405
1406 if (png_crc_finish(png_ptr, 0))
1407 {
1408 png_ptr->num_trans = 0;
1409 return;
1410 }
1411
1412 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
b61cc19c 1413 &(png_ptr->trans_color));
0272a10d
VZ
1414}
1415#endif
1416
b61cc19c 1417#ifdef PNG_READ_bKGD_SUPPORTED
0272a10d
VZ
1418void /* PRIVATE */
1419png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1420{
1421 png_size_t truelen;
1422 png_byte buf[6];
1423
970f6abe 1424 png_debug(1, "in png_handle_bKGD");
0272a10d
VZ
1425
1426 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1427 png_error(png_ptr, "Missing IHDR before bKGD");
1428 else if (png_ptr->mode & PNG_HAVE_IDAT)
1429 {
1430 png_warning(png_ptr, "Invalid bKGD after IDAT");
1431 png_crc_finish(png_ptr, length);
1432 return;
1433 }
1434 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1435 !(png_ptr->mode & PNG_HAVE_PLTE))
1436 {
1437 png_warning(png_ptr, "Missing PLTE before bKGD");
1438 png_crc_finish(png_ptr, length);
1439 return;
1440 }
1441 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1442 {
1443 png_warning(png_ptr, "Duplicate bKGD chunk");
1444 png_crc_finish(png_ptr, length);
1445 return;
1446 }
1447
1448 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1449 truelen = 1;
1450 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1451 truelen = 6;
1452 else
1453 truelen = 2;
1454
1455 if (length != truelen)
1456 {
1457 png_warning(png_ptr, "Incorrect bKGD chunk length");
1458 png_crc_finish(png_ptr, length);
1459 return;
1460 }
1461
1462 png_crc_read(png_ptr, buf, truelen);
1463 if (png_crc_finish(png_ptr, 0))
1464 return;
1465
1466 /* We convert the index value into RGB components so that we can allow
1467 * arbitrary RGB values for background when we have transparency, and
1468 * so it is easy to determine the RGB values of the background color
1469 * from the info_ptr struct. */
1470 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1471 {
1472 png_ptr->background.index = buf[0];
970f6abe 1473 if (info_ptr && info_ptr->num_palette)
0272a10d 1474 {
970f6abe 1475 if (buf[0] >= info_ptr->num_palette)
0272a10d
VZ
1476 {
1477 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1478 return;
1479 }
1480 png_ptr->background.red =
1481 (png_uint_16)png_ptr->palette[buf[0]].red;
1482 png_ptr->background.green =
1483 (png_uint_16)png_ptr->palette[buf[0]].green;
1484 png_ptr->background.blue =
1485 (png_uint_16)png_ptr->palette[buf[0]].blue;
1486 }
1487 }
1488 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1489 {
1490 png_ptr->background.red =
1491 png_ptr->background.green =
1492 png_ptr->background.blue =
1493 png_ptr->background.gray = png_get_uint_16(buf);
1494 }
1495 else
1496 {
1497 png_ptr->background.red = png_get_uint_16(buf);
1498 png_ptr->background.green = png_get_uint_16(buf + 2);
1499 png_ptr->background.blue = png_get_uint_16(buf + 4);
1500 }
1501
1502 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1503}
1504#endif
1505
b61cc19c 1506#ifdef PNG_READ_hIST_SUPPORTED
0272a10d
VZ
1507void /* PRIVATE */
1508png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1509{
1510 unsigned int num, i;
1511 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1512
970f6abe 1513 png_debug(1, "in png_handle_hIST");
0272a10d
VZ
1514
1515 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1516 png_error(png_ptr, "Missing IHDR before hIST");
1517 else if (png_ptr->mode & PNG_HAVE_IDAT)
1518 {
1519 png_warning(png_ptr, "Invalid hIST after IDAT");
1520 png_crc_finish(png_ptr, length);
1521 return;
1522 }
1523 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1524 {
1525 png_warning(png_ptr, "Missing PLTE before hIST");
1526 png_crc_finish(png_ptr, length);
1527 return;
1528 }
1529 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1530 {
1531 png_warning(png_ptr, "Duplicate hIST chunk");
1532 png_crc_finish(png_ptr, length);
1533 return;
1534 }
1535
1536 num = length / 2 ;
1537 if (num != (unsigned int) png_ptr->num_palette || num >
1538 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1539 {
1540 png_warning(png_ptr, "Incorrect hIST chunk length");
1541 png_crc_finish(png_ptr, length);
1542 return;
1543 }
1544
1545 for (i = 0; i < num; i++)
1546 {
1547 png_byte buf[2];
1548
1549 png_crc_read(png_ptr, buf, 2);
1550 readbuf[i] = png_get_uint_16(buf);
1551 }
1552
1553 if (png_crc_finish(png_ptr, 0))
1554 return;
1555
1556 png_set_hIST(png_ptr, info_ptr, readbuf);
1557}
1558#endif
1559
b61cc19c 1560#ifdef PNG_READ_pHYs_SUPPORTED
0272a10d
VZ
1561void /* PRIVATE */
1562png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1563{
1564 png_byte buf[9];
1565 png_uint_32 res_x, res_y;
1566 int unit_type;
1567
970f6abe 1568 png_debug(1, "in png_handle_pHYs");
0272a10d
VZ
1569
1570 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1571 png_error(png_ptr, "Missing IHDR before pHYs");
1572 else if (png_ptr->mode & PNG_HAVE_IDAT)
1573 {
1574 png_warning(png_ptr, "Invalid pHYs after IDAT");
1575 png_crc_finish(png_ptr, length);
1576 return;
1577 }
1578 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1579 {
1580 png_warning(png_ptr, "Duplicate pHYs chunk");
1581 png_crc_finish(png_ptr, length);
1582 return;
1583 }
1584
1585 if (length != 9)
1586 {
1587 png_warning(png_ptr, "Incorrect pHYs chunk length");
1588 png_crc_finish(png_ptr, length);
1589 return;
1590 }
1591
1592 png_crc_read(png_ptr, buf, 9);
1593 if (png_crc_finish(png_ptr, 0))
1594 return;
1595
1596 res_x = png_get_uint_32(buf);
1597 res_y = png_get_uint_32(buf + 4);
1598 unit_type = buf[8];
1599 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1600}
1601#endif
1602
b61cc19c 1603#ifdef PNG_READ_oFFs_SUPPORTED
0272a10d
VZ
1604void /* PRIVATE */
1605png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1606{
1607 png_byte buf[9];
1608 png_int_32 offset_x, offset_y;
1609 int unit_type;
1610
970f6abe 1611 png_debug(1, "in png_handle_oFFs");
0272a10d
VZ
1612
1613 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1614 png_error(png_ptr, "Missing IHDR before oFFs");
1615 else if (png_ptr->mode & PNG_HAVE_IDAT)
1616 {
1617 png_warning(png_ptr, "Invalid oFFs after IDAT");
1618 png_crc_finish(png_ptr, length);
1619 return;
1620 }
1621 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1622 {
1623 png_warning(png_ptr, "Duplicate oFFs chunk");
1624 png_crc_finish(png_ptr, length);
1625 return;
1626 }
1627
1628 if (length != 9)
1629 {
1630 png_warning(png_ptr, "Incorrect oFFs chunk length");
1631 png_crc_finish(png_ptr, length);
1632 return;
1633 }
1634
1635 png_crc_read(png_ptr, buf, 9);
1636 if (png_crc_finish(png_ptr, 0))
1637 return;
1638
1639 offset_x = png_get_int_32(buf);
1640 offset_y = png_get_int_32(buf + 4);
1641 unit_type = buf[8];
1642 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1643}
1644#endif
1645
b61cc19c
PC
1646#ifdef PNG_READ_pCAL_SUPPORTED
1647/* Read the pCAL chunk (described in the PNG Extensions document) */
0272a10d
VZ
1648void /* PRIVATE */
1649png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1650{
0272a10d
VZ
1651 png_int_32 X0, X1;
1652 png_byte type, nparams;
1653 png_charp buf, units, endptr;
1654 png_charpp params;
1655 png_size_t slength;
1656 int i;
1657
970f6abe 1658 png_debug(1, "in png_handle_pCAL");
0272a10d
VZ
1659
1660 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1661 png_error(png_ptr, "Missing IHDR before pCAL");
1662 else if (png_ptr->mode & PNG_HAVE_IDAT)
1663 {
1664 png_warning(png_ptr, "Invalid pCAL after IDAT");
1665 png_crc_finish(png_ptr, length);
1666 return;
1667 }
1668 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1669 {
1670 png_warning(png_ptr, "Duplicate pCAL chunk");
1671 png_crc_finish(png_ptr, length);
1672 return;
1673 }
1674
970f6abe 1675 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
0272a10d 1676 length + 1);
970f6abe
VZ
1677 png_free(png_ptr, png_ptr->chunkdata);
1678 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1679 if (png_ptr->chunkdata == NULL)
0272a10d 1680 {
b61cc19c 1681 png_warning(png_ptr, "No memory for pCAL purpose");
0272a10d
VZ
1682 return;
1683 }
1684 slength = (png_size_t)length;
970f6abe 1685 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1686
1687 if (png_crc_finish(png_ptr, 0))
1688 {
970f6abe
VZ
1689 png_free(png_ptr, png_ptr->chunkdata);
1690 png_ptr->chunkdata = NULL;
0272a10d
VZ
1691 return;
1692 }
1693
b61cc19c 1694 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
0272a10d 1695
970f6abe
VZ
1696 png_debug(3, "Finding end of pCAL purpose string");
1697 for (buf = png_ptr->chunkdata; *buf; buf++)
b61cc19c 1698 /* Empty loop */ ;
0272a10d 1699
970f6abe 1700 endptr = png_ptr->chunkdata + slength;
0272a10d
VZ
1701
1702 /* We need to have at least 12 bytes after the purpose string
1703 in order to get the parameter information. */
1704 if (endptr <= buf + 12)
1705 {
1706 png_warning(png_ptr, "Invalid pCAL data");
970f6abe
VZ
1707 png_free(png_ptr, png_ptr->chunkdata);
1708 png_ptr->chunkdata = NULL;
0272a10d
VZ
1709 return;
1710 }
1711
970f6abe 1712 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
0272a10d
VZ
1713 X0 = png_get_int_32((png_bytep)buf+1);
1714 X1 = png_get_int_32((png_bytep)buf+5);
1715 type = buf[9];
1716 nparams = buf[10];
1717 units = buf + 11;
1718
970f6abe 1719 png_debug(3, "Checking pCAL equation type and number of parameters");
0272a10d
VZ
1720 /* Check that we have the right number of parameters for known
1721 equation types. */
1722 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1723 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1724 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1725 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1726 {
1727 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
970f6abe
VZ
1728 png_free(png_ptr, png_ptr->chunkdata);
1729 png_ptr->chunkdata = NULL;
0272a10d
VZ
1730 return;
1731 }
1732 else if (type >= PNG_EQUATION_LAST)
1733 {
1734 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1735 }
1736
1737 for (buf = units; *buf; buf++)
1738 /* Empty loop to move past the units string. */ ;
1739
970f6abe
VZ
1740 png_debug(3, "Allocating pCAL parameters array");
1741 params = (png_charpp)png_malloc_warn(png_ptr,
b61cc19c 1742 (png_size_t)(nparams * png_sizeof(png_charp)));
0272a10d
VZ
1743 if (params == NULL)
1744 {
970f6abe
VZ
1745 png_free(png_ptr, png_ptr->chunkdata);
1746 png_ptr->chunkdata = NULL;
b61cc19c 1747 png_warning(png_ptr, "No memory for pCAL params");
0272a10d
VZ
1748 return;
1749 }
1750
1751 /* Get pointers to the start of each parameter string. */
1752 for (i = 0; i < (int)nparams; i++)
1753 {
1754 buf++; /* Skip the null string terminator from previous parameter. */
1755
970f6abe
VZ
1756 png_debug1(3, "Reading pCAL parameter %d", i);
1757 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
0272a10d
VZ
1758 /* Empty loop to move past each parameter string */ ;
1759
1760 /* Make sure we haven't run out of data yet */
1761 if (buf > endptr)
1762 {
1763 png_warning(png_ptr, "Invalid pCAL data");
970f6abe
VZ
1764 png_free(png_ptr, png_ptr->chunkdata);
1765 png_ptr->chunkdata = NULL;
0272a10d
VZ
1766 png_free(png_ptr, params);
1767 return;
1768 }
1769 }
1770
970f6abe 1771 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
0272a10d
VZ
1772 units, params);
1773
970f6abe
VZ
1774 png_free(png_ptr, png_ptr->chunkdata);
1775 png_ptr->chunkdata = NULL;
0272a10d
VZ
1776 png_free(png_ptr, params);
1777}
1778#endif
1779
b61cc19c
PC
1780#ifdef PNG_READ_sCAL_SUPPORTED
1781/* Read the sCAL chunk */
0272a10d
VZ
1782void /* PRIVATE */
1783png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1784{
970f6abe 1785 png_charp ep;
0272a10d
VZ
1786#ifdef PNG_FLOATING_POINT_SUPPORTED
1787 double width, height;
1788 png_charp vp;
1789#else
1790#ifdef PNG_FIXED_POINT_SUPPORTED
1791 png_charp swidth, sheight;
1792#endif
1793#endif
1794 png_size_t slength;
1795
970f6abe 1796 png_debug(1, "in png_handle_sCAL");
0272a10d
VZ
1797
1798 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1799 png_error(png_ptr, "Missing IHDR before sCAL");
1800 else if (png_ptr->mode & PNG_HAVE_IDAT)
1801 {
1802 png_warning(png_ptr, "Invalid sCAL after IDAT");
1803 png_crc_finish(png_ptr, length);
1804 return;
1805 }
1806 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1807 {
1808 png_warning(png_ptr, "Duplicate sCAL chunk");
1809 png_crc_finish(png_ptr, length);
1810 return;
1811 }
1812
970f6abe 1813 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
0272a10d 1814 length + 1);
970f6abe
VZ
1815 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1816 if (png_ptr->chunkdata == NULL)
1817 {
1818 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
b61cc19c 1819 png_crc_finish(png_ptr, length);
970f6abe
VZ
1820 return;
1821 }
0272a10d 1822 slength = (png_size_t)length;
970f6abe 1823 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1824
1825 if (png_crc_finish(png_ptr, 0))
1826 {
970f6abe
VZ
1827 png_free(png_ptr, png_ptr->chunkdata);
1828 png_ptr->chunkdata = NULL;
0272a10d
VZ
1829 return;
1830 }
1831
b61cc19c 1832 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
0272a10d 1833
b61cc19c 1834 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
0272a10d
VZ
1835
1836#ifdef PNG_FLOATING_POINT_SUPPORTED
1837 width = png_strtod(png_ptr, ep, &vp);
1838 if (*vp)
1839 {
970f6abe 1840 png_warning(png_ptr, "malformed width string in sCAL chunk");
b61cc19c
PC
1841 png_free(png_ptr, png_ptr->chunkdata);
1842 png_ptr->chunkdata = NULL;
970f6abe 1843 return;
0272a10d
VZ
1844 }
1845#else
1846#ifdef PNG_FIXED_POINT_SUPPORTED
1847 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1848 if (swidth == NULL)
970f6abe
VZ
1849 {
1850 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
b61cc19c
PC
1851 png_free(png_ptr, png_ptr->chunkdata);
1852 png_ptr->chunkdata = NULL;
970f6abe
VZ
1853 return;
1854 }
b61cc19c 1855 png_memcpy(swidth, ep, png_strlen(ep));
0272a10d
VZ
1856#endif
1857#endif
1858
970f6abe 1859 for (ep = png_ptr->chunkdata; *ep; ep++)
b61cc19c 1860 /* Empty loop */ ;
0272a10d
VZ
1861 ep++;
1862
970f6abe
VZ
1863 if (png_ptr->chunkdata + slength < ep)
1864 {
1865 png_warning(png_ptr, "Truncated sCAL chunk");
b61cc19c 1866#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
970f6abe
VZ
1867 png_free(png_ptr, swidth);
1868#endif
1869 png_free(png_ptr, png_ptr->chunkdata);
1870 png_ptr->chunkdata = NULL;
1871 return;
1872 }
1873
0272a10d
VZ
1874#ifdef PNG_FLOATING_POINT_SUPPORTED
1875 height = png_strtod(png_ptr, ep, &vp);
1876 if (*vp)
1877 {
970f6abe 1878 png_warning(png_ptr, "malformed height string in sCAL chunk");
b61cc19c
PC
1879 png_free(png_ptr, png_ptr->chunkdata);
1880 png_ptr->chunkdata = NULL;
970f6abe 1881 return;
0272a10d
VZ
1882 }
1883#else
1884#ifdef PNG_FIXED_POINT_SUPPORTED
1885 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
970f6abe
VZ
1886 if (sheight == NULL)
1887 {
1888 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
b61cc19c
PC
1889 png_free(png_ptr, png_ptr->chunkdata);
1890 png_ptr->chunkdata = NULL;
1891 png_free(png_ptr, swidth);
970f6abe
VZ
1892 return;
1893 }
b61cc19c 1894 png_memcpy(sheight, ep, png_strlen(ep));
0272a10d
VZ
1895#endif
1896#endif
1897
970f6abe 1898 if (png_ptr->chunkdata + slength < ep
0272a10d
VZ
1899#ifdef PNG_FLOATING_POINT_SUPPORTED
1900 || width <= 0. || height <= 0.
1901#endif
1902 )
1903 {
1904 png_warning(png_ptr, "Invalid sCAL data");
970f6abe
VZ
1905 png_free(png_ptr, png_ptr->chunkdata);
1906 png_ptr->chunkdata = NULL;
0272a10d
VZ
1907#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1908 png_free(png_ptr, swidth);
1909 png_free(png_ptr, sheight);
1910#endif
1911 return;
1912 }
1913
1914
1915#ifdef PNG_FLOATING_POINT_SUPPORTED
970f6abe 1916 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
0272a10d
VZ
1917#else
1918#ifdef PNG_FIXED_POINT_SUPPORTED
970f6abe 1919 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
0272a10d
VZ
1920#endif
1921#endif
1922
970f6abe
VZ
1923 png_free(png_ptr, png_ptr->chunkdata);
1924 png_ptr->chunkdata = NULL;
0272a10d
VZ
1925#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1926 png_free(png_ptr, swidth);
1927 png_free(png_ptr, sheight);
1928#endif
1929}
1930#endif
1931
b61cc19c 1932#ifdef PNG_READ_tIME_SUPPORTED
0272a10d
VZ
1933void /* PRIVATE */
1934png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1935{
1936 png_byte buf[7];
1937 png_time mod_time;
1938
970f6abe 1939 png_debug(1, "in png_handle_tIME");
0272a10d
VZ
1940
1941 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1942 png_error(png_ptr, "Out of place tIME chunk");
1943 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1944 {
1945 png_warning(png_ptr, "Duplicate tIME chunk");
1946 png_crc_finish(png_ptr, length);
1947 return;
1948 }
1949
1950 if (png_ptr->mode & PNG_HAVE_IDAT)
1951 png_ptr->mode |= PNG_AFTER_IDAT;
1952
1953 if (length != 7)
1954 {
1955 png_warning(png_ptr, "Incorrect tIME chunk length");
1956 png_crc_finish(png_ptr, length);
1957 return;
1958 }
1959
1960 png_crc_read(png_ptr, buf, 7);
1961 if (png_crc_finish(png_ptr, 0))
1962 return;
1963
1964 mod_time.second = buf[6];
1965 mod_time.minute = buf[5];
1966 mod_time.hour = buf[4];
1967 mod_time.day = buf[3];
1968 mod_time.month = buf[2];
1969 mod_time.year = png_get_uint_16(buf);
1970
1971 png_set_tIME(png_ptr, info_ptr, &mod_time);
1972}
1973#endif
1974
b61cc19c 1975#ifdef PNG_READ_tEXt_SUPPORTED
0272a10d
VZ
1976/* Note: this does not properly handle chunks that are > 64K under DOS */
1977void /* PRIVATE */
1978png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1979{
1980 png_textp text_ptr;
1981 png_charp key;
1982 png_charp text;
1983 png_uint_32 skip = 0;
1984 png_size_t slength;
1985 int ret;
1986
970f6abe 1987 png_debug(1, "in png_handle_tEXt");
0272a10d 1988
b61cc19c
PC
1989#ifdef PNG_USER_LIMITS_SUPPORTED
1990 if (png_ptr->user_chunk_cache_max != 0)
1991 {
1992 if (png_ptr->user_chunk_cache_max == 1)
1993 {
1994 png_crc_finish(png_ptr, length);
1995 return;
1996 }
1997 if (--png_ptr->user_chunk_cache_max == 1)
1998 {
1999 png_warning(png_ptr, "No space in chunk cache for tEXt");
2000 png_crc_finish(png_ptr, length);
2001 return;
2002 }
2003 }
2004#endif
2005
0272a10d
VZ
2006 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2007 png_error(png_ptr, "Missing IHDR before tEXt");
2008
2009 if (png_ptr->mode & PNG_HAVE_IDAT)
2010 png_ptr->mode |= PNG_AFTER_IDAT;
2011
2012#ifdef PNG_MAX_MALLOC_64K
2013 if (length > (png_uint_32)65535L)
2014 {
2015 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
2016 skip = length - (png_uint_32)65535L;
2017 length = (png_uint_32)65535L;
2018 }
2019#endif
2020
970f6abe 2021 png_free(png_ptr, png_ptr->chunkdata);
b61cc19c 2022
970f6abe
VZ
2023 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2024 if (png_ptr->chunkdata == NULL)
0272a10d 2025 {
b61cc19c 2026 png_warning(png_ptr, "No memory to process text chunk");
0272a10d
VZ
2027 return;
2028 }
2029 slength = (png_size_t)length;
970f6abe 2030 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
2031
2032 if (png_crc_finish(png_ptr, skip))
2033 {
970f6abe
VZ
2034 png_free(png_ptr, png_ptr->chunkdata);
2035 png_ptr->chunkdata = NULL;
0272a10d
VZ
2036 return;
2037 }
2038
970f6abe 2039 key = png_ptr->chunkdata;
b61cc19c 2040
0272a10d
VZ
2041 key[slength] = 0x00;
2042
2043 for (text = key; *text; text++)
b61cc19c 2044 /* Empty loop to find end of key */ ;
0272a10d
VZ
2045
2046 if (text != key + slength)
2047 text++;
2048
2049 text_ptr = (png_textp)png_malloc_warn(png_ptr,
b61cc19c 2050 png_sizeof(png_text));
0272a10d
VZ
2051 if (text_ptr == NULL)
2052 {
b61cc19c 2053 png_warning(png_ptr, "Not enough memory to process text chunk");
970f6abe
VZ
2054 png_free(png_ptr, png_ptr->chunkdata);
2055 png_ptr->chunkdata = NULL;
0272a10d
VZ
2056 return;
2057 }
2058 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2059 text_ptr->key = key;
2060#ifdef PNG_iTXt_SUPPORTED
2061 text_ptr->lang = NULL;
2062 text_ptr->lang_key = NULL;
2063 text_ptr->itxt_length = 0;
2064#endif
2065 text_ptr->text = text;
2066 text_ptr->text_length = png_strlen(text);
2067
970f6abe 2068 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
0272a10d 2069
970f6abe
VZ
2070 png_free(png_ptr, png_ptr->chunkdata);
2071 png_ptr->chunkdata = NULL;
0272a10d
VZ
2072 png_free(png_ptr, text_ptr);
2073 if (ret)
b61cc19c 2074 png_warning(png_ptr, "Insufficient memory to process text chunk");
0272a10d
VZ
2075}
2076#endif
2077
b61cc19c
PC
2078#ifdef PNG_READ_zTXt_SUPPORTED
2079/* Note: this does not correctly handle chunks that are > 64K under DOS */
0272a10d
VZ
2080void /* PRIVATE */
2081png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2082{
2083 png_textp text_ptr;
0272a10d
VZ
2084 png_charp text;
2085 int comp_type;
2086 int ret;
2087 png_size_t slength, prefix_len, data_len;
2088
970f6abe 2089 png_debug(1, "in png_handle_zTXt");
b61cc19c
PC
2090
2091#ifdef PNG_USER_LIMITS_SUPPORTED
2092 if (png_ptr->user_chunk_cache_max != 0)
2093 {
2094 if (png_ptr->user_chunk_cache_max == 1)
2095 {
2096 png_crc_finish(png_ptr, length);
2097 return;
2098 }
2099 if (--png_ptr->user_chunk_cache_max == 1)
2100 {
2101 png_warning(png_ptr, "No space in chunk cache for zTXt");
2102 png_crc_finish(png_ptr, length);
2103 return;
2104 }
2105 }
2106#endif
2107
0272a10d
VZ
2108 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2109 png_error(png_ptr, "Missing IHDR before zTXt");
2110
2111 if (png_ptr->mode & PNG_HAVE_IDAT)
2112 png_ptr->mode |= PNG_AFTER_IDAT;
2113
2114#ifdef PNG_MAX_MALLOC_64K
2115 /* We will no doubt have problems with chunks even half this size, but
2116 there is no hard and fast rule to tell us where to stop. */
2117 if (length > (png_uint_32)65535L)
2118 {
970f6abe 2119 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
0272a10d
VZ
2120 png_crc_finish(png_ptr, length);
2121 return;
2122 }
2123#endif
2124
970f6abe
VZ
2125 png_free(png_ptr, png_ptr->chunkdata);
2126 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2127 if (png_ptr->chunkdata == NULL)
0272a10d 2128 {
b61cc19c 2129 png_warning(png_ptr, "Out of memory processing zTXt chunk");
0272a10d
VZ
2130 return;
2131 }
2132 slength = (png_size_t)length;
970f6abe 2133 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
2134 if (png_crc_finish(png_ptr, 0))
2135 {
970f6abe
VZ
2136 png_free(png_ptr, png_ptr->chunkdata);
2137 png_ptr->chunkdata = NULL;
0272a10d
VZ
2138 return;
2139 }
2140
970f6abe 2141 png_ptr->chunkdata[slength] = 0x00;
0272a10d 2142
970f6abe 2143 for (text = png_ptr->chunkdata; *text; text++)
b61cc19c 2144 /* Empty loop */ ;
0272a10d
VZ
2145
2146 /* zTXt must have some text after the chunkdataword */
970f6abe 2147 if (text >= png_ptr->chunkdata + slength - 2)
0272a10d
VZ
2148 {
2149 png_warning(png_ptr, "Truncated zTXt chunk");
970f6abe
VZ
2150 png_free(png_ptr, png_ptr->chunkdata);
2151 png_ptr->chunkdata = NULL;
0272a10d
VZ
2152 return;
2153 }
2154 else
2155 {
2156 comp_type = *(++text);
2157 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2158 {
2159 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2160 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2161 }
b61cc19c 2162 text++; /* Skip the compression_method byte */
0272a10d 2163 }
970f6abe 2164 prefix_len = text - png_ptr->chunkdata;
0272a10d 2165
970f6abe
VZ
2166 png_decompress_chunk(png_ptr, comp_type,
2167 (png_size_t)length, prefix_len, &data_len);
0272a10d
VZ
2168
2169 text_ptr = (png_textp)png_malloc_warn(png_ptr,
b61cc19c 2170 png_sizeof(png_text));
0272a10d
VZ
2171 if (text_ptr == NULL)
2172 {
b61cc19c 2173 png_warning(png_ptr, "Not enough memory to process zTXt chunk");
970f6abe
VZ
2174 png_free(png_ptr, png_ptr->chunkdata);
2175 png_ptr->chunkdata = NULL;
0272a10d
VZ
2176 return;
2177 }
2178 text_ptr->compression = comp_type;
970f6abe 2179 text_ptr->key = png_ptr->chunkdata;
0272a10d
VZ
2180#ifdef PNG_iTXt_SUPPORTED
2181 text_ptr->lang = NULL;
2182 text_ptr->lang_key = NULL;
2183 text_ptr->itxt_length = 0;
2184#endif
970f6abe 2185 text_ptr->text = png_ptr->chunkdata + prefix_len;
0272a10d
VZ
2186 text_ptr->text_length = data_len;
2187
970f6abe 2188 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
0272a10d
VZ
2189
2190 png_free(png_ptr, text_ptr);
970f6abe
VZ
2191 png_free(png_ptr, png_ptr->chunkdata);
2192 png_ptr->chunkdata = NULL;
0272a10d 2193 if (ret)
b61cc19c 2194 png_error(png_ptr, "Insufficient memory to store zTXt chunk");
0272a10d
VZ
2195}
2196#endif
2197
b61cc19c
PC
2198#ifdef PNG_READ_iTXt_SUPPORTED
2199/* Note: this does not correctly handle chunks that are > 64K under DOS */
0272a10d
VZ
2200void /* PRIVATE */
2201png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2202{
2203 png_textp text_ptr;
0272a10d
VZ
2204 png_charp key, lang, text, lang_key;
2205 int comp_flag;
2206 int comp_type = 0;
2207 int ret;
2208 png_size_t slength, prefix_len, data_len;
2209
970f6abe 2210 png_debug(1, "in png_handle_iTXt");
0272a10d 2211
b61cc19c
PC
2212#ifdef PNG_USER_LIMITS_SUPPORTED
2213 if (png_ptr->user_chunk_cache_max != 0)
2214 {
2215 if (png_ptr->user_chunk_cache_max == 1)
2216 {
2217 png_crc_finish(png_ptr, length);
2218 return;
2219 }
2220 if (--png_ptr->user_chunk_cache_max == 1)
2221 {
2222 png_warning(png_ptr, "No space in chunk cache for iTXt");
2223 png_crc_finish(png_ptr, length);
2224 return;
2225 }
2226 }
2227#endif
2228
0272a10d
VZ
2229 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2230 png_error(png_ptr, "Missing IHDR before iTXt");
2231
2232 if (png_ptr->mode & PNG_HAVE_IDAT)
2233 png_ptr->mode |= PNG_AFTER_IDAT;
2234
2235#ifdef PNG_MAX_MALLOC_64K
2236 /* We will no doubt have problems with chunks even half this size, but
2237 there is no hard and fast rule to tell us where to stop. */
2238 if (length > (png_uint_32)65535L)
2239 {
970f6abe 2240 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
0272a10d
VZ
2241 png_crc_finish(png_ptr, length);
2242 return;
2243 }
2244#endif
2245
970f6abe
VZ
2246 png_free(png_ptr, png_ptr->chunkdata);
2247 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2248 if (png_ptr->chunkdata == NULL)
0272a10d 2249 {
b61cc19c 2250 png_warning(png_ptr, "No memory to process iTXt chunk");
0272a10d
VZ
2251 return;
2252 }
2253 slength = (png_size_t)length;
970f6abe 2254 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
2255 if (png_crc_finish(png_ptr, 0))
2256 {
970f6abe
VZ
2257 png_free(png_ptr, png_ptr->chunkdata);
2258 png_ptr->chunkdata = NULL;
0272a10d
VZ
2259 return;
2260 }
2261
970f6abe 2262 png_ptr->chunkdata[slength] = 0x00;
0272a10d 2263
970f6abe 2264 for (lang = png_ptr->chunkdata; *lang; lang++)
b61cc19c
PC
2265 /* Empty loop */ ;
2266 lang++; /* Skip NUL separator */
0272a10d
VZ
2267
2268 /* iTXt must have a language tag (possibly empty), two compression bytes,
b61cc19c
PC
2269 * translated keyword (possibly empty), and possibly some text after the
2270 * keyword
2271 */
0272a10d 2272
970f6abe 2273 if (lang >= png_ptr->chunkdata + slength - 3)
0272a10d
VZ
2274 {
2275 png_warning(png_ptr, "Truncated iTXt chunk");
970f6abe
VZ
2276 png_free(png_ptr, png_ptr->chunkdata);
2277 png_ptr->chunkdata = NULL;
0272a10d
VZ
2278 return;
2279 }
2280 else
2281 {
2282 comp_flag = *lang++;
2283 comp_type = *lang++;
2284 }
2285
2286 for (lang_key = lang; *lang_key; lang_key++)
b61cc19c
PC
2287 /* Empty loop */ ;
2288 lang_key++; /* Skip NUL separator */
0272a10d 2289
970f6abe
VZ
2290 if (lang_key >= png_ptr->chunkdata + slength)
2291 {
2292 png_warning(png_ptr, "Truncated iTXt chunk");
2293 png_free(png_ptr, png_ptr->chunkdata);
2294 png_ptr->chunkdata = NULL;
2295 return;
2296 }
2297
0272a10d 2298 for (text = lang_key; *text; text++)
b61cc19c
PC
2299 /* Empty loop */ ;
2300 text++; /* Skip NUL separator */
970f6abe 2301 if (text >= png_ptr->chunkdata + slength)
0272a10d
VZ
2302 {
2303 png_warning(png_ptr, "Malformed iTXt chunk");
970f6abe
VZ
2304 png_free(png_ptr, png_ptr->chunkdata);
2305 png_ptr->chunkdata = NULL;
0272a10d
VZ
2306 return;
2307 }
2308
970f6abe 2309 prefix_len = text - png_ptr->chunkdata;
0272a10d 2310
970f6abe 2311 key=png_ptr->chunkdata;
0272a10d 2312 if (comp_flag)
970f6abe
VZ
2313 png_decompress_chunk(png_ptr, comp_type,
2314 (size_t)length, prefix_len, &data_len);
0272a10d 2315 else
970f6abe 2316 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
0272a10d 2317 text_ptr = (png_textp)png_malloc_warn(png_ptr,
b61cc19c 2318 png_sizeof(png_text));
0272a10d
VZ
2319 if (text_ptr == NULL)
2320 {
b61cc19c 2321 png_warning(png_ptr, "Not enough memory to process iTXt chunk");
970f6abe
VZ
2322 png_free(png_ptr, png_ptr->chunkdata);
2323 png_ptr->chunkdata = NULL;
0272a10d
VZ
2324 return;
2325 }
2326 text_ptr->compression = (int)comp_flag + 1;
970f6abe
VZ
2327 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2328 text_ptr->lang = png_ptr->chunkdata + (lang - key);
0272a10d
VZ
2329 text_ptr->itxt_length = data_len;
2330 text_ptr->text_length = 0;
970f6abe
VZ
2331 text_ptr->key = png_ptr->chunkdata;
2332 text_ptr->text = png_ptr->chunkdata + prefix_len;
0272a10d 2333
970f6abe 2334 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
0272a10d
VZ
2335
2336 png_free(png_ptr, text_ptr);
970f6abe
VZ
2337 png_free(png_ptr, png_ptr->chunkdata);
2338 png_ptr->chunkdata = NULL;
0272a10d 2339 if (ret)
b61cc19c 2340 png_error(png_ptr, "Insufficient memory to store iTXt chunk");
0272a10d
VZ
2341}
2342#endif
2343
2344/* This function is called when we haven't found a handler for a
2345 chunk. If there isn't a problem with the chunk itself (ie bad
2346 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2347 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2348 case it will be saved away to be written out later. */
2349void /* PRIVATE */
2350png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2351{
2352 png_uint_32 skip = 0;
2353
970f6abe 2354 png_debug(1, "in png_handle_unknown");
0272a10d 2355
b61cc19c
PC
2356#ifdef PNG_USER_LIMITS_SUPPORTED
2357 if (png_ptr->user_chunk_cache_max != 0)
0272a10d 2358 {
b61cc19c
PC
2359 if (png_ptr->user_chunk_cache_max == 1)
2360 {
2361 png_crc_finish(png_ptr, length);
2362 return;
2363 }
2364 if (--png_ptr->user_chunk_cache_max == 1)
2365 {
2366 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2367 png_crc_finish(png_ptr, length);
2368 return;
2369 }
2370 }
0272a10d 2371#endif
b61cc19c
PC
2372
2373 if (png_ptr->mode & PNG_HAVE_IDAT)
2374 {
2375 PNG_IDAT;
2376 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
0272a10d
VZ
2377 png_ptr->mode |= PNG_AFTER_IDAT;
2378 }
2379
0272a10d
VZ
2380 if (!(png_ptr->chunk_name[0] & 0x20))
2381 {
b61cc19c 2382#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
970f6abe 2383 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
0272a10d 2384 PNG_HANDLE_CHUNK_ALWAYS
b61cc19c 2385#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
0272a10d
VZ
2386 && png_ptr->read_user_chunk_fn == NULL
2387#endif
2388 )
2389#endif
2390 png_chunk_error(png_ptr, "unknown critical chunk");
2391 }
2392
b61cc19c
PC
2393#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
2394 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2395#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2396 || (png_ptr->read_user_chunk_fn != NULL)
2397#endif
2398 )
0272a10d
VZ
2399 {
2400#ifdef PNG_MAX_MALLOC_64K
2401 if (length > (png_uint_32)65535L)
2402 {
2403 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2404 skip = length - (png_uint_32)65535L;
2405 length = (png_uint_32)65535L;
2406 }
2407#endif
970f6abe 2408 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
b61cc19c 2409 (png_charp)png_ptr->chunk_name,
970f6abe 2410 png_sizeof(png_ptr->unknown_chunk.name));
b61cc19c
PC
2411 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2412 = '\0';
0272a10d 2413 png_ptr->unknown_chunk.size = (png_size_t)length;
970f6abe
VZ
2414 if (length == 0)
2415 png_ptr->unknown_chunk.data = NULL;
2416 else
2417 {
2418 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2419 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2420 }
b61cc19c 2421#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
970f6abe 2422 if (png_ptr->read_user_chunk_fn != NULL)
0272a10d 2423 {
b61cc19c 2424 /* Callback to user unknown chunk handler */
0272a10d
VZ
2425 int ret;
2426 ret = (*(png_ptr->read_user_chunk_fn))
2427 (png_ptr, &png_ptr->unknown_chunk);
2428 if (ret < 0)
2429 png_chunk_error(png_ptr, "error in user chunk");
2430 if (ret == 0)
2431 {
2432 if (!(png_ptr->chunk_name[0] & 0x20))
b61cc19c 2433#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
970f6abe 2434 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
0272a10d 2435 PNG_HANDLE_CHUNK_ALWAYS)
b61cc19c 2436#endif
0272a10d
VZ
2437 png_chunk_error(png_ptr, "unknown critical chunk");
2438 png_set_unknown_chunks(png_ptr, info_ptr,
2439 &png_ptr->unknown_chunk, 1);
2440 }
2441 }
970f6abe 2442 else
0272a10d 2443#endif
970f6abe 2444 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
0272a10d
VZ
2445 png_free(png_ptr, png_ptr->unknown_chunk.data);
2446 png_ptr->unknown_chunk.data = NULL;
2447 }
2448 else
2449#endif
2450 skip = length;
2451
2452 png_crc_finish(png_ptr, skip);
2453
b61cc19c
PC
2454#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
2455 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
0272a10d
VZ
2456#endif
2457}
2458
2459/* This function is called to verify that a chunk name is valid.
2460 This function can't have the "critical chunk check" incorporated
2461 into it, since in the future we will need to be able to call user
2462 functions to handle unknown critical chunks after we check that
2463 the chunk name itself is valid. */
2464
2465#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2466
2467void /* PRIVATE */
2468png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2469{
970f6abe 2470 png_debug(1, "in png_check_chunk_name");
0272a10d
VZ
2471 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2472 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2473 {
2474 png_chunk_error(png_ptr, "invalid chunk type");
2475 }
2476}
2477
2478/* Combines the row recently read in with the existing pixels in the
2479 row. This routine takes care of alpha and transparency if requested.
2480 This routine also handles the two methods of progressive display
2481 of interlaced images, depending on the mask value.
2482 The mask value describes which pixels are to be combined with
2483 the row. The pattern always repeats every 8 pixels, so just 8
2484 bits are needed. A one indicates the pixel is to be combined,
2485 a zero indicates the pixel is to be skipped. This is in addition
2486 to any alpha or transparency value associated with the pixel. If
2487 you want all pixels to be combined, pass 0xff (255) in mask. */
2488
2489void /* PRIVATE */
2490png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2491{
970f6abe 2492 png_debug(1, "in png_combine_row");
0272a10d
VZ
2493 if (mask == 0xff)
2494 {
2495 png_memcpy(row, png_ptr->row_buf + 1,
2496 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2497 }
2498 else
2499 {
2500 switch (png_ptr->row_info.pixel_depth)
2501 {
2502 case 1:
2503 {
2504 png_bytep sp = png_ptr->row_buf + 1;
2505 png_bytep dp = row;
2506 int s_inc, s_start, s_end;
2507 int m = 0x80;
2508 int shift;
2509 png_uint_32 i;
2510 png_uint_32 row_width = png_ptr->width;
2511
b61cc19c 2512#ifdef PNG_READ_PACKSWAP_SUPPORTED
0272a10d
VZ
2513 if (png_ptr->transformations & PNG_PACKSWAP)
2514 {
2515 s_start = 0;
2516 s_end = 7;
2517 s_inc = 1;
2518 }
2519 else
2520#endif
2521 {
2522 s_start = 7;
2523 s_end = 0;
2524 s_inc = -1;
2525 }
2526
2527 shift = s_start;
2528
2529 for (i = 0; i < row_width; i++)
2530 {
2531 if (m & mask)
2532 {
2533 int value;
2534
2535 value = (*sp >> shift) & 0x01;
2536 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2537 *dp |= (png_byte)(value << shift);
2538 }
2539
2540 if (shift == s_end)
2541 {
2542 shift = s_start;
2543 sp++;
2544 dp++;
2545 }
2546 else
2547 shift += s_inc;
2548
2549 if (m == 1)
2550 m = 0x80;
2551 else
2552 m >>= 1;
2553 }
2554 break;
2555 }
2556 case 2:
2557 {
2558 png_bytep sp = png_ptr->row_buf + 1;
2559 png_bytep dp = row;
2560 int s_start, s_end, s_inc;
2561 int m = 0x80;
2562 int shift;
2563 png_uint_32 i;
2564 png_uint_32 row_width = png_ptr->width;
2565 int value;
2566
b61cc19c 2567#ifdef PNG_READ_PACKSWAP_SUPPORTED
0272a10d
VZ
2568 if (png_ptr->transformations & PNG_PACKSWAP)
2569 {
2570 s_start = 0;
2571 s_end = 6;
2572 s_inc = 2;
2573 }
2574 else
2575#endif
2576 {
2577 s_start = 6;
2578 s_end = 0;
2579 s_inc = -2;
2580 }
2581
2582 shift = s_start;
2583
2584 for (i = 0; i < row_width; i++)
2585 {
2586 if (m & mask)
2587 {
2588 value = (*sp >> shift) & 0x03;
2589 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2590 *dp |= (png_byte)(value << shift);
2591 }
2592
2593 if (shift == s_end)
2594 {
2595 shift = s_start;
2596 sp++;
2597 dp++;
2598 }
2599 else
2600 shift += s_inc;
2601 if (m == 1)
2602 m = 0x80;
2603 else
2604 m >>= 1;
2605 }
2606 break;
2607 }
2608 case 4:
2609 {
2610 png_bytep sp = png_ptr->row_buf + 1;
2611 png_bytep dp = row;
2612 int s_start, s_end, s_inc;
2613 int m = 0x80;
2614 int shift;
2615 png_uint_32 i;
2616 png_uint_32 row_width = png_ptr->width;
2617 int value;
2618
b61cc19c 2619#ifdef PNG_READ_PACKSWAP_SUPPORTED
0272a10d
VZ
2620 if (png_ptr->transformations & PNG_PACKSWAP)
2621 {
2622 s_start = 0;
2623 s_end = 4;
2624 s_inc = 4;
2625 }
2626 else
2627#endif
2628 {
2629 s_start = 4;
2630 s_end = 0;
2631 s_inc = -4;
2632 }
2633 shift = s_start;
2634
2635 for (i = 0; i < row_width; i++)
2636 {
2637 if (m & mask)
2638 {
2639 value = (*sp >> shift) & 0xf;
2640 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2641 *dp |= (png_byte)(value << shift);
2642 }
2643
2644 if (shift == s_end)
2645 {
2646 shift = s_start;
2647 sp++;
2648 dp++;
2649 }
2650 else
2651 shift += s_inc;
2652 if (m == 1)
2653 m = 0x80;
2654 else
2655 m >>= 1;
2656 }
2657 break;
2658 }
2659 default:
2660 {
2661 png_bytep sp = png_ptr->row_buf + 1;
2662 png_bytep dp = row;
2663 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2664 png_uint_32 i;
2665 png_uint_32 row_width = png_ptr->width;
2666 png_byte m = 0x80;
2667
2668
2669 for (i = 0; i < row_width; i++)
2670 {
2671 if (m & mask)
2672 {
2673 png_memcpy(dp, sp, pixel_bytes);
2674 }
2675
2676 sp += pixel_bytes;
2677 dp += pixel_bytes;
2678
2679 if (m == 1)
2680 m = 0x80;
2681 else
2682 m >>= 1;
2683 }
2684 break;
2685 }
2686 }
2687 }
2688}
2689
2690#ifdef PNG_READ_INTERLACING_SUPPORTED
2691/* OLD pre-1.0.9 interface:
2692void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2693 png_uint_32 transformations)
2694 */
2695void /* PRIVATE */
2696png_do_read_interlace(png_structp png_ptr)
2697{
2698 png_row_infop row_info = &(png_ptr->row_info);
2699 png_bytep row = png_ptr->row_buf + 1;
2700 int pass = png_ptr->pass;
2701 png_uint_32 transformations = png_ptr->transformations;
b61cc19c
PC
2702 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2703 /* Offset to next interlace block */
0272a10d 2704 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
0272a10d 2705
970f6abe 2706 png_debug(1, "in png_do_read_interlace");
0272a10d
VZ
2707 if (row != NULL && row_info != NULL)
2708 {
2709 png_uint_32 final_width;
2710
2711 final_width = row_info->width * png_pass_inc[pass];
2712
2713 switch (row_info->pixel_depth)
2714 {
2715 case 1:
2716 {
2717 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2718 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2719 int sshift, dshift;
2720 int s_start, s_end, s_inc;
2721 int jstop = png_pass_inc[pass];
2722 png_byte v;
2723 png_uint_32 i;
2724 int j;
2725
b61cc19c 2726#ifdef PNG_READ_PACKSWAP_SUPPORTED
0272a10d
VZ
2727 if (transformations & PNG_PACKSWAP)
2728 {
2729 sshift = (int)((row_info->width + 7) & 0x07);
2730 dshift = (int)((final_width + 7) & 0x07);
2731 s_start = 7;
2732 s_end = 0;
2733 s_inc = -1;
2734 }
2735 else
2736#endif
2737 {
2738 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2739 dshift = 7 - (int)((final_width + 7) & 0x07);
2740 s_start = 0;
2741 s_end = 7;
2742 s_inc = 1;
2743 }
2744
2745 for (i = 0; i < row_info->width; i++)
2746 {
2747 v = (png_byte)((*sp >> sshift) & 0x01);
2748 for (j = 0; j < jstop; j++)
2749 {
2750 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2751 *dp |= (png_byte)(v << dshift);
2752 if (dshift == s_end)
2753 {
2754 dshift = s_start;
2755 dp--;
2756 }
2757 else
2758 dshift += s_inc;
2759 }
2760 if (sshift == s_end)
2761 {
2762 sshift = s_start;
2763 sp--;
2764 }
2765 else
2766 sshift += s_inc;
2767 }
2768 break;
2769 }
2770 case 2:
2771 {
2772 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2773 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2774 int sshift, dshift;
2775 int s_start, s_end, s_inc;
2776 int jstop = png_pass_inc[pass];
2777 png_uint_32 i;
2778
b61cc19c 2779#ifdef PNG_READ_PACKSWAP_SUPPORTED
0272a10d
VZ
2780 if (transformations & PNG_PACKSWAP)
2781 {
2782 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2783 dshift = (int)(((final_width + 3) & 0x03) << 1);
2784 s_start = 6;
2785 s_end = 0;
2786 s_inc = -2;
2787 }
2788 else
2789#endif
2790 {
2791 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2792 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2793 s_start = 0;
2794 s_end = 6;
2795 s_inc = 2;
2796 }
2797
2798 for (i = 0; i < row_info->width; i++)
2799 {
2800 png_byte v;
2801 int j;
2802
2803 v = (png_byte)((*sp >> sshift) & 0x03);
2804 for (j = 0; j < jstop; j++)
2805 {
2806 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2807 *dp |= (png_byte)(v << dshift);
2808 if (dshift == s_end)
2809 {
2810 dshift = s_start;
2811 dp--;
2812 }
2813 else
2814 dshift += s_inc;
2815 }
2816 if (sshift == s_end)
2817 {
2818 sshift = s_start;
2819 sp--;
2820 }
2821 else
2822 sshift += s_inc;
2823 }
2824 break;
2825 }
2826 case 4:
2827 {
2828 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2829 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2830 int sshift, dshift;
2831 int s_start, s_end, s_inc;
2832 png_uint_32 i;
2833 int jstop = png_pass_inc[pass];
2834
b61cc19c 2835#ifdef PNG_READ_PACKSWAP_SUPPORTED
0272a10d
VZ
2836 if (transformations & PNG_PACKSWAP)
2837 {
2838 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2839 dshift = (int)(((final_width + 1) & 0x01) << 2);
2840 s_start = 4;
2841 s_end = 0;
2842 s_inc = -4;
2843 }
2844 else
2845#endif
2846 {
2847 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2848 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2849 s_start = 0;
2850 s_end = 4;
2851 s_inc = 4;
2852 }
2853
2854 for (i = 0; i < row_info->width; i++)
2855 {
2856 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2857 int j;
2858
2859 for (j = 0; j < jstop; j++)
2860 {
2861 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2862 *dp |= (png_byte)(v << dshift);
2863 if (dshift == s_end)
2864 {
2865 dshift = s_start;
2866 dp--;
2867 }
2868 else
2869 dshift += s_inc;
2870 }
2871 if (sshift == s_end)
2872 {
2873 sshift = s_start;
2874 sp--;
2875 }
2876 else
2877 sshift += s_inc;
2878 }
2879 break;
2880 }
2881 default:
2882 {
2883 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
b61cc19c
PC
2884 png_bytep sp = row + (png_size_t)(row_info->width - 1)
2885 * pixel_bytes;
0272a10d
VZ
2886 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2887
2888 int jstop = png_pass_inc[pass];
2889 png_uint_32 i;
2890
2891 for (i = 0; i < row_info->width; i++)
2892 {
2893 png_byte v[8];
2894 int j;
2895
2896 png_memcpy(v, sp, pixel_bytes);
2897 for (j = 0; j < jstop; j++)
2898 {
2899 png_memcpy(dp, v, pixel_bytes);
2900 dp -= pixel_bytes;
2901 }
2902 sp -= pixel_bytes;
2903 }
2904 break;
2905 }
2906 }
2907 row_info->width = final_width;
970f6abe 2908 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
0272a10d 2909 }
b61cc19c
PC
2910#ifndef PNG_READ_PACKSWAP_SUPPORTED
2911 transformations = transformations; /* Silence compiler warning */
0272a10d
VZ
2912#endif
2913}
2914#endif /* PNG_READ_INTERLACING_SUPPORTED */
2915
2916void /* PRIVATE */
2917png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2918 png_bytep prev_row, int filter)
2919{
970f6abe
VZ
2920 png_debug(1, "in png_read_filter_row");
2921 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
0272a10d
VZ
2922 switch (filter)
2923 {
2924 case PNG_FILTER_VALUE_NONE:
2925 break;
2926 case PNG_FILTER_VALUE_SUB:
2927 {
2928 png_uint_32 i;
2929 png_uint_32 istop = row_info->rowbytes;
2930 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2931 png_bytep rp = row + bpp;
2932 png_bytep lp = row;
2933
2934 for (i = bpp; i < istop; i++)
2935 {
2936 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2937 rp++;
2938 }
2939 break;
2940 }
2941 case PNG_FILTER_VALUE_UP:
2942 {
2943 png_uint_32 i;
2944 png_uint_32 istop = row_info->rowbytes;
2945 png_bytep rp = row;
2946 png_bytep pp = prev_row;
2947
2948 for (i = 0; i < istop; i++)
2949 {
2950 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2951 rp++;
2952 }
2953 break;
2954 }
2955 case PNG_FILTER_VALUE_AVG:
2956 {
2957 png_uint_32 i;
2958 png_bytep rp = row;
2959 png_bytep pp = prev_row;
2960 png_bytep lp = row;
2961 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2962 png_uint_32 istop = row_info->rowbytes - bpp;
2963
2964 for (i = 0; i < bpp; i++)
2965 {
2966 *rp = (png_byte)(((int)(*rp) +
2967 ((int)(*pp++) / 2 )) & 0xff);
2968 rp++;
2969 }
2970
2971 for (i = 0; i < istop; i++)
2972 {
2973 *rp = (png_byte)(((int)(*rp) +
2974 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2975 rp++;
2976 }
2977 break;
2978 }
2979 case PNG_FILTER_VALUE_PAETH:
2980 {
2981 png_uint_32 i;
2982 png_bytep rp = row;
2983 png_bytep pp = prev_row;
2984 png_bytep lp = row;
2985 png_bytep cp = prev_row;
2986 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2987 png_uint_32 istop=row_info->rowbytes - bpp;
2988
2989 for (i = 0; i < bpp; i++)
2990 {
2991 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2992 rp++;
2993 }
2994
b61cc19c 2995 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
0272a10d
VZ
2996 {
2997 int a, b, c, pa, pb, pc, p;
2998
2999 a = *lp++;
3000 b = *pp++;
3001 c = *cp++;
3002
3003 p = b - c;
3004 pc = a - c;
3005
3006#ifdef PNG_USE_ABS
3007 pa = abs(p);
3008 pb = abs(pc);
3009 pc = abs(p + pc);
3010#else
3011 pa = p < 0 ? -p : p;
3012 pb = pc < 0 ? -pc : pc;
3013 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3014#endif
3015
3016 /*
3017 if (pa <= pb && pa <= pc)
3018 p = a;
3019 else if (pb <= pc)
3020 p = b;
3021 else
3022 p = c;
3023 */
3024
970f6abe 3025 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
0272a10d
VZ
3026
3027 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3028 rp++;
3029 }
3030 break;
3031 }
3032 default:
3033 png_warning(png_ptr, "Ignoring bad adaptive filter type");
970f6abe 3034 *row = 0;
0272a10d
VZ
3035 break;
3036 }
3037}
3038
b61cc19c 3039#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
0272a10d
VZ
3040void /* PRIVATE */
3041png_read_finish_row(png_structp png_ptr)
3042{
970f6abe 3043#ifdef PNG_READ_INTERLACING_SUPPORTED
b61cc19c 3044 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
0272a10d 3045
b61cc19c 3046 /* Start of interlace block */
0272a10d
VZ
3047 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3048
b61cc19c 3049 /* Offset to next interlace block */
0272a10d
VZ
3050 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3051
b61cc19c 3052 /* Start of interlace block in the y direction */
0272a10d
VZ
3053 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3054
b61cc19c 3055 /* Offset to next interlace block in the y direction */
0272a10d 3056 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
970f6abe 3057#endif /* PNG_READ_INTERLACING_SUPPORTED */
0272a10d 3058
970f6abe 3059 png_debug(1, "in png_read_finish_row");
0272a10d
VZ
3060 png_ptr->row_number++;
3061 if (png_ptr->row_number < png_ptr->num_rows)
3062 return;
3063
970f6abe 3064#ifdef PNG_READ_INTERLACING_SUPPORTED
0272a10d
VZ
3065 if (png_ptr->interlaced)
3066 {
3067 png_ptr->row_number = 0;
b61cc19c 3068 png_memset(png_ptr->prev_row, 0,
0272a10d
VZ
3069 png_ptr->rowbytes + 1);
3070 do
3071 {
3072 png_ptr->pass++;
3073 if (png_ptr->pass >= 7)
3074 break;
3075 png_ptr->iwidth = (png_ptr->width +
3076 png_pass_inc[png_ptr->pass] - 1 -
3077 png_pass_start[png_ptr->pass]) /
3078 png_pass_inc[png_ptr->pass];
3079
0272a10d
VZ
3080 if (!(png_ptr->transformations & PNG_INTERLACE))
3081 {
3082 png_ptr->num_rows = (png_ptr->height +
3083 png_pass_yinc[png_ptr->pass] - 1 -
3084 png_pass_ystart[png_ptr->pass]) /
3085 png_pass_yinc[png_ptr->pass];
3086 if (!(png_ptr->num_rows))
3087 continue;
3088 }
3089 else /* if (png_ptr->transformations & PNG_INTERLACE) */
3090 break;
3091 } while (png_ptr->iwidth == 0);
3092
3093 if (png_ptr->pass < 7)
3094 return;
3095 }
970f6abe 3096#endif /* PNG_READ_INTERLACING_SUPPORTED */
0272a10d
VZ
3097
3098 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
3099 {
b61cc19c 3100 PNG_IDAT;
0272a10d
VZ
3101 char extra;
3102 int ret;
3103
3104 png_ptr->zstream.next_out = (Byte *)&extra;
3105 png_ptr->zstream.avail_out = (uInt)1;
970f6abe 3106 for (;;)
0272a10d
VZ
3107 {
3108 if (!(png_ptr->zstream.avail_in))
3109 {
3110 while (!png_ptr->idat_size)
3111 {
3112 png_byte chunk_length[4];
3113
3114 png_crc_finish(png_ptr, 0);
3115
3116 png_read_data(png_ptr, chunk_length, 4);
3117 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
3118 png_reset_crc(png_ptr);
3119 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
970f6abe 3120 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
0272a10d
VZ
3121 png_error(png_ptr, "Not enough image data");
3122
3123 }
3124 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3125 png_ptr->zstream.next_in = png_ptr->zbuf;
3126 if (png_ptr->zbuf_size > png_ptr->idat_size)
3127 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3128 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3129 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3130 }
3131 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3132 if (ret == Z_STREAM_END)
3133 {
3134 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3135 png_ptr->idat_size)
3136 png_warning(png_ptr, "Extra compressed data");
3137 png_ptr->mode |= PNG_AFTER_IDAT;
3138 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3139 break;
3140 }
3141 if (ret != Z_OK)
3142 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3143 "Decompression Error");
3144
3145 if (!(png_ptr->zstream.avail_out))
3146 {
b61cc19c 3147 png_warning(png_ptr, "Extra compressed data");
0272a10d
VZ
3148 png_ptr->mode |= PNG_AFTER_IDAT;
3149 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3150 break;
3151 }
3152
3153 }
3154 png_ptr->zstream.avail_out = 0;
3155 }
3156
3157 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3158 png_warning(png_ptr, "Extra compression data");
3159
3160 inflateReset(&png_ptr->zstream);
3161
3162 png_ptr->mode |= PNG_AFTER_IDAT;
3163}
b61cc19c 3164#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
0272a10d
VZ
3165
3166void /* PRIVATE */
3167png_read_start_row(png_structp png_ptr)
3168{
970f6abe 3169#ifdef PNG_READ_INTERLACING_SUPPORTED
b61cc19c 3170 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
0272a10d 3171
b61cc19c 3172 /* Start of interlace block */
0272a10d
VZ
3173 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3174
b61cc19c 3175 /* Offset to next interlace block */
0272a10d
VZ
3176 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3177
b61cc19c 3178 /* Start of interlace block in the y direction */
0272a10d
VZ
3179 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3180
b61cc19c 3181 /* Offset to next interlace block in the y direction */
0272a10d
VZ
3182 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3183#endif
3184
3185 int max_pixel_depth;
970f6abe 3186 png_size_t row_bytes;
0272a10d 3187
970f6abe 3188 png_debug(1, "in png_read_start_row");
0272a10d
VZ
3189 png_ptr->zstream.avail_in = 0;
3190 png_init_read_transformations(png_ptr);
970f6abe 3191#ifdef PNG_READ_INTERLACING_SUPPORTED
0272a10d
VZ
3192 if (png_ptr->interlaced)
3193 {
3194 if (!(png_ptr->transformations & PNG_INTERLACE))
3195 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3196 png_pass_ystart[0]) / png_pass_yinc[0];
3197 else
3198 png_ptr->num_rows = png_ptr->height;
3199
3200 png_ptr->iwidth = (png_ptr->width +
3201 png_pass_inc[png_ptr->pass] - 1 -
3202 png_pass_start[png_ptr->pass]) /
3203 png_pass_inc[png_ptr->pass];
0272a10d
VZ
3204 }
3205 else
970f6abe 3206#endif /* PNG_READ_INTERLACING_SUPPORTED */
0272a10d
VZ
3207 {
3208 png_ptr->num_rows = png_ptr->height;
3209 png_ptr->iwidth = png_ptr->width;
0272a10d
VZ
3210 }
3211 max_pixel_depth = png_ptr->pixel_depth;
3212
b61cc19c 3213#ifdef PNG_READ_PACK_SUPPORTED
0272a10d
VZ
3214 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3215 max_pixel_depth = 8;
3216#endif
3217
b61cc19c 3218#ifdef PNG_READ_EXPAND_SUPPORTED
0272a10d
VZ
3219 if (png_ptr->transformations & PNG_EXPAND)
3220 {
3221 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3222 {
3223 if (png_ptr->num_trans)
3224 max_pixel_depth = 32;
3225 else
3226 max_pixel_depth = 24;
3227 }
3228 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3229 {
3230 if (max_pixel_depth < 8)
3231 max_pixel_depth = 8;
3232 if (png_ptr->num_trans)
3233 max_pixel_depth *= 2;
3234 }
3235 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3236 {
3237 if (png_ptr->num_trans)
3238 {
3239 max_pixel_depth *= 4;
3240 max_pixel_depth /= 3;
3241 }
3242 }
3243 }
3244#endif
3245
b61cc19c 3246#ifdef PNG_READ_FILLER_SUPPORTED
0272a10d
VZ
3247 if (png_ptr->transformations & (PNG_FILLER))
3248 {
3249 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3250 max_pixel_depth = 32;
3251 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3252 {
3253 if (max_pixel_depth <= 8)
3254 max_pixel_depth = 16;
3255 else
3256 max_pixel_depth = 32;
3257 }
3258 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3259 {
3260 if (max_pixel_depth <= 32)
3261 max_pixel_depth = 32;
3262 else
3263 max_pixel_depth = 64;
3264 }
3265 }
3266#endif
3267
b61cc19c 3268#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
0272a10d
VZ
3269 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3270 {
3271 if (
b61cc19c 3272#ifdef PNG_READ_EXPAND_SUPPORTED
0272a10d
VZ
3273 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3274#endif
b61cc19c 3275#ifdef PNG_READ_FILLER_SUPPORTED
0272a10d
VZ
3276 (png_ptr->transformations & (PNG_FILLER)) ||
3277#endif
3278 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3279 {
3280 if (max_pixel_depth <= 16)
3281 max_pixel_depth = 32;
3282 else
3283 max_pixel_depth = 64;
3284 }
3285 else
3286 {
3287 if (max_pixel_depth <= 8)
3288 {
3289 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3290 max_pixel_depth = 32;
3291 else
3292 max_pixel_depth = 24;
3293 }
3294 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3295 max_pixel_depth = 64;
3296 else
3297 max_pixel_depth = 48;
3298 }
3299 }
3300#endif
3301
3302#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3303defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
970f6abe 3304 if (png_ptr->transformations & PNG_USER_TRANSFORM)
0272a10d 3305 {
970f6abe 3306 int user_pixel_depth = png_ptr->user_transform_depth*
0272a10d 3307 png_ptr->user_transform_channels;
970f6abe 3308 if (user_pixel_depth > max_pixel_depth)
0272a10d
VZ
3309 max_pixel_depth=user_pixel_depth;
3310 }
3311#endif
3312
b61cc19c
PC
3313 /* Align the width on the next larger 8 pixels. Mainly used
3314 * for interlacing
3315 */
0272a10d 3316 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
b61cc19c
PC
3317 /* Calculate the maximum bytes needed, adding a byte and a pixel
3318 * for safety's sake
3319 */
970f6abe 3320 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
0272a10d
VZ
3321 1 + ((max_pixel_depth + 7) >> 3);
3322#ifdef PNG_MAX_MALLOC_64K
3323 if (row_bytes > (png_uint_32)65536L)
3324 png_error(png_ptr, "This image requires a row greater than 64KB");
3325#endif
970f6abe 3326
b61cc19c 3327 if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
970f6abe
VZ
3328 {
3329 png_free(png_ptr, png_ptr->big_row_buf);
b61cc19c
PC
3330 if (png_ptr->interlaced)
3331 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3332 row_bytes + 48);
3333 else
3334 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3335 row_bytes + 48);
3336 png_ptr->old_big_row_buf_size = row_bytes + 48;
3337
3338#ifdef PNG_ALIGNED_MEMORY_SUPPORTED
3339 /* Use 16-byte aligned memory for row_buf with at least 16 bytes
3340 * of padding before and after row_buf.
3341 */
3342 png_ptr->row_buf = png_ptr->big_row_buf + 32
3343 - (((png_alloc_size_t)&(png_ptr->big_row_buf[0]) + 15) % 16);
3344 png_ptr->old_big_row_buf_size = row_bytes + 48;
3345#else
3346 /* Use 32 bytes of padding before and 16 bytes after row_buf. */
3347 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3348#endif
3349 png_ptr->old_big_row_buf_size = row_bytes + 48;
970f6abe 3350 }
0272a10d
VZ
3351
3352#ifdef PNG_MAX_MALLOC_64K
3353 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3354 png_error(png_ptr, "This image requires a row greater than 64KB");
3355#endif
3356 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
b61cc19c 3357 png_error(png_ptr, "Row has too many bytes to allocate in memory");
970f6abe 3358
b61cc19c 3359 if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size)
970f6abe 3360 {
b61cc19c
PC
3361 png_free(png_ptr, png_ptr->prev_row);
3362 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
970f6abe 3363 png_ptr->rowbytes + 1));
b61cc19c 3364 png_ptr->old_prev_row_size = png_ptr->rowbytes + 1;
970f6abe 3365 }
0272a10d 3366
b61cc19c 3367 png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
0272a10d 3368
970f6abe
VZ
3369 png_debug1(3, "width = %lu,", png_ptr->width);
3370 png_debug1(3, "height = %lu,", png_ptr->height);
3371 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
b61cc19c 3372 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
970f6abe 3373 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
b61cc19c
PC
3374 png_debug1(3, "irowbytes = %lu",
3375 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
0272a10d
VZ
3376
3377 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3378}
3379#endif /* PNG_READ_SUPPORTED */