Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / core / src / fxcodec / fx_lpng / lpng_v163 / fx_pngrutil.c
1 #if (!defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) || defined(_PNG_DECODER_)) && !defined(_USE_ADDIN_) && !defined(_FX_EMB_NOUSE_DECODER_)\r
2 /* pngrutil.c - utilities to read a PNG file\r
3  *\r
4  * Last changed in libpng 1.6.3 [July 18, 2013]\r
5  * Copyright (c) 1998-2013 Glenn Randers-Pehrson\r
6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)\r
7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)\r
8  *\r
9  * This code is released under the libpng license.\r
10  * For conditions of distribution and use, see the disclaimer\r
11  * and license in png.h\r
12  *\r
13  * This file contains routines that are only called from within\r
14  * libpng itself during the course of reading an image.\r
15  */\r
16 \r
17 #include "pngpriv.h"\r
18 \r
19 #ifdef PNG_READ_SUPPORTED\r
20 \r
21 png_uint_32 PNGAPI\r
22 png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)\r
23 {\r
24    png_uint_32 uval = png_get_uint_32(buf);\r
25 \r
26    if (uval > PNG_UINT_31_MAX)\r
27       png_error(png_ptr, "PNG unsigned integer out of range");\r
28 \r
29    return (uval);\r
30 }\r
31 \r
32 #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)\r
33 /* The following is a variation on the above for use with the fixed\r
34  * point values used for gAMA and cHRM.  Instead of png_error it\r
35  * issues a warning and returns (-1) - an invalid value because both\r
36  * gAMA and cHRM use *unsigned* integers for fixed point values.\r
37  */\r
38 #define PNG_FIXED_ERROR (-1)\r
39 \r
40 static png_fixed_point /* PRIVATE */\r
41 png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)\r
42 {\r
43    png_uint_32 uval = png_get_uint_32(buf);\r
44 \r
45    if (uval <= PNG_UINT_31_MAX)\r
46       return (png_fixed_point)uval; /* known to be in range */\r
47 \r
48    /* The caller can turn off the warning by passing NULL. */\r
49    if (png_ptr != NULL)\r
50       png_warning(png_ptr, "PNG fixed point integer out of range");\r
51 \r
52    return PNG_FIXED_ERROR;\r
53 }\r
54 #endif\r
55 \r
56 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED\r
57 /* NOTE: the read macros will obscure these definitions, so that if\r
58  * PNG_USE_READ_MACROS is set the library will not use them internally,\r
59  * but the APIs will still be available externally.\r
60  *\r
61  * The parentheses around "PNGAPI function_name" in the following three\r
62  * functions are necessary because they allow the macros to co-exist with\r
63  * these (unused but exported) functions.\r
64  */\r
65 \r
66 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */\r
67 png_uint_32 (PNGAPI\r
68 png_get_uint_32)(png_const_bytep buf)\r
69 {\r
70    png_uint_32 uval =\r
71        ((png_uint_32)(*(buf    )) << 24) +\r
72        ((png_uint_32)(*(buf + 1)) << 16) +\r
73        ((png_uint_32)(*(buf + 2)) <<  8) +\r
74        ((png_uint_32)(*(buf + 3))      ) ;\r
75 \r
76    return uval;\r
77 }\r
78 \r
79 /* Grab a signed 32-bit integer from a buffer in big-endian format.  The\r
80  * data is stored in the PNG file in two's complement format and there\r
81  * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore\r
82  * the following code does a two's complement to native conversion.\r
83  */\r
84 png_int_32 (PNGAPI\r
85 png_get_int_32)(png_const_bytep buf)\r
86 {\r
87    png_uint_32 uval = png_get_uint_32(buf);\r
88    if ((uval & 0x80000000) == 0) /* non-negative */\r
89       return uval;\r
90 \r
91    uval = (uval ^ 0xffffffff) + 1;  /* 2's complement: -x = ~x+1 */\r
92    return -(png_int_32)uval;\r
93 }\r
94 \r
95 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */\r
96 png_uint_16 (PNGAPI\r
97 png_get_uint_16)(png_const_bytep buf)\r
98 {\r
99    /* ANSI-C requires an int value to accomodate at least 16 bits so this\r
100     * works and allows the compiler not to worry about possible narrowing\r
101     * on 32 bit systems.  (Pre-ANSI systems did not make integers smaller\r
102     * than 16 bits either.)\r
103     */\r
104    unsigned int val =\r
105        ((unsigned int)(*buf) << 8) +\r
106        ((unsigned int)(*(buf + 1)));\r
107 \r
108    return (png_uint_16)val;\r
109 }\r
110 \r
111 #endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */\r
112 \r
113 /* Read and check the PNG file signature */\r
114 void /* PRIVATE */\r
115 png_read_sig(png_structrp png_ptr, png_inforp info_ptr)\r
116 {\r
117    png_size_t num_checked, num_to_check;\r
118 \r
119    /* Exit if the user application does not expect a signature. */\r
120    if (png_ptr->sig_bytes >= 8)\r
121       return;\r
122 \r
123    num_checked = png_ptr->sig_bytes;\r
124    num_to_check = 8 - num_checked;\r
125 \r
126 #ifdef PNG_IO_STATE_SUPPORTED\r
127    png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE;\r
128 #endif\r
129 \r
130    /* The signature must be serialized in a single I/O call. */\r
131    png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);\r
132    png_ptr->sig_bytes = 8;\r
133 \r
134    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))\r
135    {\r
136       if (num_checked < 4 &&\r
137           png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))\r
138          png_error(png_ptr, "Not a PNG file");\r
139       else\r
140          png_error(png_ptr, "PNG file corrupted by ASCII conversion");\r
141    }\r
142    if (num_checked < 3)\r
143       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;\r
144 }\r
145 \r
146 /* Read the chunk header (length + type name).\r
147  * Put the type name into png_ptr->chunk_name, and return the length.\r
148  */\r
149 png_uint_32 /* PRIVATE */\r
150 png_read_chunk_header(png_structrp png_ptr)\r
151 {\r
152    png_byte buf[8];\r
153    png_uint_32 length;\r
154 \r
155 #ifdef PNG_IO_STATE_SUPPORTED\r
156    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;\r
157 #endif\r
158 \r
159    /* Read the length and the chunk name.\r
160     * This must be performed in a single I/O call.\r
161     */\r
162    png_read_data(png_ptr, buf, 8);\r
163    length = png_get_uint_31(png_ptr, buf);\r
164 \r
165    /* Put the chunk name into png_ptr->chunk_name. */\r
166    png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);\r
167 \r
168    png_debug2(0, "Reading %lx chunk, length = %lu",\r
169        (unsigned long)png_ptr->chunk_name, (unsigned long)length);\r
170 \r
171    /* Reset the crc and run it over the chunk name. */\r
172    png_reset_crc(png_ptr);\r
173    png_calculate_crc(png_ptr, buf + 4, 4);\r
174 \r
175    /* Check to see if chunk name is valid. */\r
176    png_check_chunk_name(png_ptr, png_ptr->chunk_name);\r
177 \r
178 #ifdef PNG_IO_STATE_SUPPORTED\r
179    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;\r
180 #endif\r
181 \r
182    return length;\r
183 }\r
184 \r
185 /* Read data, and (optionally) run it through the CRC. */\r
186 void /* PRIVATE */\r
187 png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)\r
188 {\r
189    if (png_ptr == NULL)\r
190       return;\r
191 \r
192    png_read_data(png_ptr, buf, length);\r
193    png_calculate_crc(png_ptr, buf, length);\r
194 }\r
195 \r
196 /* Optionally skip data and then check the CRC.  Depending on whether we\r
197  * are reading an ancillary or critical chunk, and how the program has set\r
198  * things up, we may calculate the CRC on the data and print a message.\r
199  * Returns '1' if there was a CRC error, '0' otherwise.\r
200  */\r
201 int /* PRIVATE */\r
202 png_crc_finish(png_structrp png_ptr, png_uint_32 skip)\r
203 {\r
204    /* The size of the local buffer for inflate is a good guess as to a\r
205     * reasonable size to use for buffering reads from the application.\r
206     */\r
207    while (skip > 0)\r
208    {\r
209       png_uint_32 len;\r
210       png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];\r
211 \r
212       len = (sizeof tmpbuf);\r
213       if (len > skip)\r
214          len = skip;\r
215       skip -= len;\r
216 \r
217       png_crc_read(png_ptr, tmpbuf, len);\r
218    }\r
219 \r
220    if (png_crc_error(png_ptr))\r
221    {\r
222       if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) ?\r
223           !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) :\r
224           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))\r
225       {\r
226          png_chunk_warning(png_ptr, "CRC error");\r
227       }\r
228 \r
229       else\r
230       {\r
231          png_chunk_benign_error(png_ptr, "CRC error");\r
232          return (0);\r
233       }\r
234 \r
235       return (1);\r
236    }\r
237 \r
238    return (0);\r
239 }\r
240 \r
241 /* Compare the CRC stored in the PNG file with that calculated by libpng from\r
242  * the data it has read thus far.\r
243  */\r
244 int /* PRIVATE */\r
245 png_crc_error(png_structrp png_ptr)\r
246 {\r
247    png_byte crc_bytes[4];\r
248    png_uint_32 crc;\r
249    int need_crc = 1;\r
250 \r
251    if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))\r
252    {\r
253       if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==\r
254           (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))\r
255          need_crc = 0;\r
256    }\r
257 \r
258    else /* critical */\r
259    {\r
260       if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)\r
261          need_crc = 0;\r
262    }\r
263 \r
264 #ifdef PNG_IO_STATE_SUPPORTED\r
265    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;\r
266 #endif\r
267 \r
268    /* The chunk CRC must be serialized in a single I/O call. */\r
269    png_read_data(png_ptr, crc_bytes, 4);\r
270 \r
271    if (need_crc)\r
272    {\r
273       crc = png_get_uint_32(crc_bytes);\r
274       return ((int)(crc != png_ptr->crc));\r
275    }\r
276 \r
277    else\r
278       return (0);\r
279 }\r
280 \r
281 /* Manage the read buffer; this simply reallocates the buffer if it is not small\r
282  * enough (or if it is not allocated).  The routine returns a pointer to the\r
283  * buffer; if an error occurs and 'warn' is set the routine returns NULL, else\r
284  * it will call png_error (via png_malloc) on failure.  (warn == 2 means\r
285  * 'silent').\r
286  */\r
287 static png_bytep\r
288 png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)\r
289 {\r
290    png_bytep buffer = png_ptr->read_buffer;\r
291 \r
292    if (buffer != NULL && new_size > png_ptr->read_buffer_size)\r
293    {\r
294       png_ptr->read_buffer = NULL;\r
295       png_ptr->read_buffer = NULL;\r
296       png_ptr->read_buffer_size = 0;\r
297       png_free(png_ptr, buffer);\r
298       buffer = NULL;\r
299    }\r
300 \r
301    if (buffer == NULL)\r
302    {\r
303       buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size));\r
304 \r
305       if (buffer != NULL)\r
306       {\r
307          png_ptr->read_buffer = buffer;\r
308          png_ptr->read_buffer_size = new_size;\r
309       }\r
310 \r
311       else if (warn < 2) /* else silent */\r
312       {\r
313 #ifdef PNG_WARNINGS_SUPPORTED\r
314          if (warn)\r
315              png_chunk_warning(png_ptr, "insufficient memory to read chunk");\r
316          else\r
317 #endif\r
318          {\r
319 #ifdef PNG_ERROR_TEXT_SUPPORTED\r
320              png_chunk_error(png_ptr, "insufficient memory to read chunk");\r
321 #endif\r
322          }\r
323       }\r
324    }\r
325 \r
326    return buffer;\r
327 }\r
328 \r
329 /* png_inflate_claim: claim the zstream for some nefarious purpose that involves\r
330  * decompression.  Returns Z_OK on success, else a zlib error code.  It checks\r
331  * the owner but, in final release builds, just issues a warning if some other\r
332  * chunk apparently owns the stream.  Prior to release it does a png_error.\r
333  */\r
334 static int\r
335 png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)\r
336 {\r
337    if (png_ptr->zowner != 0)\r
338    {\r
339       char msg[64];\r
340 \r
341       PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner);\r
342       /* So the message that results is "<chunk> using zstream"; this is an\r
343        * internal error, but is very useful for debugging.  i18n requirements\r
344        * are minimal.\r
345        */\r
346       (void)png_safecat(msg, (sizeof msg), 4, " using zstream");\r
347 #     if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC\r
348          png_chunk_warning(png_ptr, msg);\r
349          png_ptr->zowner = 0;\r
350 #     else\r
351          png_chunk_error(png_ptr, msg);\r
352 #     endif\r
353    }\r
354 \r
355    /* Implementation note: unlike 'png_deflate_claim' this internal function\r
356     * does not take the size of the data as an argument.  Some efficiency could\r
357     * be gained by using this when it is known *if* the zlib stream itself does\r
358     * not record the number; however, this is an illusion: the original writer\r
359     * of the PNG may have selected a lower window size, and we really must\r
360     * follow that because, for systems with with limited capabilities, we\r
361     * would otherwise reject the application's attempts to use a smaller window\r
362     * size (zlib doesn't have an interface to say "this or lower"!).\r
363     *\r
364     * inflateReset2 was added to zlib 1.2.4; before this the window could not be\r
365     * reset, therefore it is necessary to always allocate the maximum window\r
366     * size with earlier zlibs just in case later compressed chunks need it.\r
367     */\r
368    {\r
369       int ret; /* zlib return code */\r
370 #     if PNG_ZLIB_VERNUM >= 0x1240\r
371 \r
372 #        if defined(PNG_SET_OPTION_SUPPORTED) && \\r
373             defined(PNG_MAXIMUM_INFLATE_WINDOW)\r
374             int window_bits;\r
375 \r
376             if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) ==\r
377                PNG_OPTION_ON)\r
378                window_bits = 15;\r
379 \r
380             else\r
381                window_bits = 0;\r
382 #        else\r
383 #           define window_bits 0\r
384 #        endif\r
385 #     endif\r
386 \r
387       /* Set this for safety, just in case the previous owner left pointers to\r
388        * memory allocations.\r
389        */\r
390       png_ptr->zstream.next_in = NULL;\r
391       png_ptr->zstream.avail_in = 0;\r
392       png_ptr->zstream.next_out = NULL;\r
393       png_ptr->zstream.avail_out = 0;\r
394 \r
395       if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED)\r
396       {\r
397 #        if PNG_ZLIB_VERNUM < 0x1240\r
398             ret = inflateReset(&png_ptr->zstream);\r
399 #        else\r
400             ret = inflateReset2(&png_ptr->zstream, window_bits);\r
401 #        endif\r
402       }\r
403 \r
404       else\r
405       {\r
406 #        if PNG_ZLIB_VERNUM < 0x1240\r
407             ret = inflateInit(&png_ptr->zstream);\r
408 #        else\r
409             ret = inflateInit2(&png_ptr->zstream, window_bits);\r
410 #        endif\r
411 \r
412          if (ret == Z_OK)\r
413             png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;\r
414       }\r
415 \r
416       if (ret == Z_OK)\r
417          png_ptr->zowner = owner;\r
418 \r
419       else\r
420          png_zstream_error(png_ptr, ret);\r
421 \r
422       return ret;\r
423    }\r
424 \r
425 #  ifdef window_bits\r
426 #     undef window_bits\r
427 #  endif\r
428 }\r
429 \r
430 #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED\r
431 /* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to\r
432  * allow the caller to do multiple calls if required.  If the 'finish' flag is\r
433  * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must\r
434  * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and\r
435  * Z_OK or Z_STREAM_END will be returned on success.\r
436  *\r
437  * The input and output sizes are updated to the actual amounts of data consumed\r
438  * or written, not the amount available (as in a z_stream).  The data pointers\r
439  * are not changed, so the next input is (data+input_size) and the next\r
440  * available output is (output+output_size).\r
441  */\r
442 static int\r
443 png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,\r
444     /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr,\r
445     /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr)\r
446 {\r
447    if (png_ptr->zowner == owner) /* Else not claimed */\r
448    {\r
449       int ret;\r
450       png_alloc_size_t avail_out = *output_size_ptr;\r
451       png_uint_32 avail_in = *input_size_ptr;\r
452 \r
453       /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it\r
454        * can't even necessarily handle 65536 bytes) because the type uInt is\r
455        * "16 bits or more".  Consequently it is necessary to chunk the input to\r
456        * zlib.  This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the\r
457        * maximum value that can be stored in a uInt.)  It is possible to set\r
458        * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have\r
459        * a performance advantage, because it reduces the amount of data accessed\r
460        * at each step and that may give the OS more time to page it in.\r
461        */\r
462       png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);\r
463       /* avail_in and avail_out are set below from 'size' */\r
464       png_ptr->zstream.avail_in = 0;\r
465       png_ptr->zstream.avail_out = 0;\r
466 \r
467       /* Read directly into the output if it is available (this is set to\r
468        * a local buffer below if output is NULL).\r
469        */\r
470       if (output != NULL)\r
471          png_ptr->zstream.next_out = output;\r
472 \r
473       do\r
474       {\r
475          uInt avail;\r
476          Byte local_buffer[PNG_INFLATE_BUF_SIZE];\r
477 \r
478          /* zlib INPUT BUFFER */\r
479          /* The setting of 'avail_in' used to be outside the loop; by setting it\r
480           * inside it is possible to chunk the input to zlib and simply rely on\r
481           * zlib to advance the 'next_in' pointer.  This allows arbitrary\r
482           * amounts of data to be passed through zlib at the unavoidable cost of\r
483           * requiring a window save (memcpy of up to 32768 output bytes)\r
484           * every ZLIB_IO_MAX input bytes.\r
485           */\r
486          avail_in += png_ptr->zstream.avail_in; /* not consumed last time */\r
487 \r
488          avail = ZLIB_IO_MAX;\r
489 \r
490          if (avail_in < avail)\r
491             avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */\r
492 \r
493          avail_in -= avail;\r
494          png_ptr->zstream.avail_in = avail;\r
495 \r
496          /* zlib OUTPUT BUFFER */\r
497          avail_out += png_ptr->zstream.avail_out; /* not written last time */\r
498 \r
499          avail = ZLIB_IO_MAX; /* maximum zlib can process */\r
500 \r
501          if (output == NULL)\r
502          {\r
503             /* Reset the output buffer each time round if output is NULL and\r
504              * make available the full buffer, up to 'remaining_space'\r
505              */\r
506             png_ptr->zstream.next_out = local_buffer;\r
507             if ((sizeof local_buffer) < avail)\r
508                avail = (sizeof local_buffer);\r
509          }\r
510 \r
511          if (avail_out < avail)\r
512             avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */\r
513 \r
514          png_ptr->zstream.avail_out = avail;\r
515          avail_out -= avail;\r
516 \r
517          /* zlib inflate call */\r
518          /* In fact 'avail_out' may be 0 at this point, that happens at the end\r
519           * of the read when the final LZ end code was not passed at the end of\r
520           * the previous chunk of input data.  Tell zlib if we have reached the\r
521           * end of the output buffer.\r
522           */\r
523          ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH :\r
524             (finish ? Z_FINISH : Z_SYNC_FLUSH));\r
525       } while (ret == Z_OK);\r
526 \r
527       /* For safety kill the local buffer pointer now */\r
528       if (output == NULL)\r
529          png_ptr->zstream.next_out = NULL;\r
530 \r
531       /* Claw back the 'size' and 'remaining_space' byte counts. */\r
532       avail_in += png_ptr->zstream.avail_in;\r
533       avail_out += png_ptr->zstream.avail_out;\r
534 \r
535       /* Update the input and output sizes; the updated values are the amount\r
536        * consumed or written, effectively the inverse of what zlib uses.\r
537        */\r
538       if (avail_out > 0)\r
539          *output_size_ptr -= avail_out;\r
540 \r
541       if (avail_in > 0)\r
542          *input_size_ptr -= avail_in;\r
543 \r
544       /* Ensure png_ptr->zstream.msg is set (even in the success case!) */\r
545       png_zstream_error(png_ptr, ret);\r
546       return ret;\r
547    }\r
548 \r
549    else\r
550    {\r
551       /* This is a bad internal error.  The recovery assigns to the zstream msg\r
552        * pointer, which is not owned by the caller, but this is safe; it's only\r
553        * used on errors!\r
554        */\r
555       png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");\r
556       return Z_STREAM_ERROR;\r
557    }\r
558 }\r
559 \r
560 /*\r
561  * Decompress trailing data in a chunk.  The assumption is that read_buffer\r
562  * points at an allocated area holding the contents of a chunk with a\r
563  * trailing compressed part.  What we get back is an allocated area\r
564  * holding the original prefix part and an uncompressed version of the\r
565  * trailing part (the malloc area passed in is freed).\r
566  */\r
567 static int\r
568 png_decompress_chunk(png_structrp png_ptr,\r
569    png_uint_32 chunklength, png_uint_32 prefix_size,\r
570    png_alloc_size_t *newlength /* must be initialized to the maximum! */,\r
571    int terminate /*add a '\0' to the end of the uncompressed data*/)\r
572 {\r
573    /* TODO: implement different limits for different types of chunk.\r
574     *\r
575     * The caller supplies *newlength set to the maximum length of the\r
576     * uncompressed data, but this routine allocates space for the prefix and\r
577     * maybe a '\0' terminator too.  We have to assume that 'prefix_size' is\r
578     * limited only by the maximum chunk size.\r
579     */\r
580    png_alloc_size_t limit = PNG_SIZE_MAX;\r
581 \r
582 #  ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED\r
583       if (png_ptr->user_chunk_malloc_max > 0 &&\r
584          png_ptr->user_chunk_malloc_max < limit)\r
585          limit = png_ptr->user_chunk_malloc_max;\r
586 #  elif PNG_USER_CHUNK_MALLOC_MAX > 0\r
587       if (PNG_USER_CHUNK_MALLOC_MAX < limit)\r
588          limit = PNG_USER_CHUNK_MALLOC_MAX;\r
589 #  endif\r
590 \r
591    if (limit >= prefix_size + (terminate != 0))\r
592    {\r
593       int ret;\r
594 \r
595       limit -= prefix_size + (terminate != 0);\r
596 \r
597       if (limit < *newlength)\r
598          *newlength = limit;\r
599 \r
600       /* Now try to claim the stream. */\r
601       ret = png_inflate_claim(png_ptr, png_ptr->chunk_name);\r
602 \r
603       if (ret == Z_OK)\r
604       {\r
605          png_uint_32 lzsize = chunklength - prefix_size;\r
606 \r
607          ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,\r
608             /* input: */ png_ptr->read_buffer + prefix_size, &lzsize,\r
609             /* output: */ NULL, newlength);\r
610 \r
611          if (ret == Z_STREAM_END)\r
612          {\r
613             /* Use 'inflateReset' here, not 'inflateReset2' because this\r
614              * preserves the previously decided window size (otherwise it would\r
615              * be necessary to store the previous window size.)  In practice\r
616              * this doesn't matter anyway, because png_inflate will call inflate\r
617              * with Z_FINISH in almost all cases, so the window will not be\r
618              * maintained.\r
619              */\r
620             if (inflateReset(&png_ptr->zstream) == Z_OK)\r
621             {\r
622                /* Because of the limit checks above we know that the new,\r
623                 * expanded, size will fit in a size_t (let alone an\r
624                 * png_alloc_size_t).  Use png_malloc_base here to avoid an\r
625                 * extra OOM message.\r
626                 */\r
627                png_alloc_size_t new_size = *newlength;\r
628                png_alloc_size_t buffer_size = prefix_size + new_size +\r
629                   (terminate != 0);\r
630                png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr,\r
631                   buffer_size));\r
632 \r
633                if (text != NULL)\r
634                {\r
635                   ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,\r
636                      png_ptr->read_buffer + prefix_size, &lzsize,\r
637                      text + prefix_size, newlength);\r
638 \r
639                   if (ret == Z_STREAM_END)\r
640                   {\r
641                      if (new_size == *newlength)\r
642                      {\r
643                         if (terminate)\r
644                            text[prefix_size + *newlength] = 0;\r
645 \r
646                         if (prefix_size > 0)\r
647                            memcpy(text, png_ptr->read_buffer, prefix_size);\r
648 \r
649                         {\r
650                            png_bytep old_ptr = png_ptr->read_buffer;\r
651 \r
652                            png_ptr->read_buffer = text;\r
653                            png_ptr->read_buffer_size = buffer_size;\r
654                            text = old_ptr; /* freed below */\r
655                         }\r
656                      }\r
657 \r
658                      else\r
659                      {\r
660                         /* The size changed on the second read, there can be no\r
661                          * guarantee that anything is correct at this point.\r
662                          * The 'msg' pointer has been set to "unexpected end of\r
663                          * LZ stream", which is fine, but return an error code\r
664                          * that the caller won't accept.\r
665                          */\r
666                         ret = PNG_UNEXPECTED_ZLIB_RETURN;\r
667                      }\r
668                   }\r
669 \r
670                   else if (ret == Z_OK)\r
671                      ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */\r
672 \r
673                   /* Free the text pointer (this is the old read_buffer on\r
674                    * success)\r
675                    */\r
676                   png_free(png_ptr, text);\r
677 \r
678                   /* This really is very benign, but it's still an error because\r
679                    * the extra space may otherwise be used as a Trojan Horse.\r
680                    */\r
681                   if (ret == Z_STREAM_END &&\r
682                      chunklength - prefix_size != lzsize)\r
683                      png_chunk_benign_error(png_ptr, "extra compressed data");\r
684                }\r
685 \r
686                else\r
687                {\r
688                   /* Out of memory allocating the buffer */\r
689                   ret = Z_MEM_ERROR;\r
690                   png_zstream_error(png_ptr, Z_MEM_ERROR);\r
691                }\r
692             }\r
693 \r
694             else\r
695             {\r
696                /* inflateReset failed, store the error message */\r
697                png_zstream_error(png_ptr, ret);\r
698 \r
699                if (ret == Z_STREAM_END)\r
700                   ret = PNG_UNEXPECTED_ZLIB_RETURN;\r
701             }\r
702          }\r
703 \r
704          else if (ret == Z_OK)\r
705             ret = PNG_UNEXPECTED_ZLIB_RETURN;\r
706 \r
707          /* Release the claimed stream */\r
708          png_ptr->zowner = 0;\r
709       }\r
710 \r
711       else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */\r
712          ret = PNG_UNEXPECTED_ZLIB_RETURN;\r
713 \r
714       return ret;\r
715    }\r
716 \r
717    else\r
718    {\r
719       /* Application/configuration limits exceeded */\r
720       png_zstream_error(png_ptr, Z_MEM_ERROR);\r
721       return Z_MEM_ERROR;\r
722    }\r
723 }\r
724 #endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */\r
725 \r
726 #ifdef PNG_READ_iCCP_SUPPORTED\r
727 /* Perform a partial read and decompress, producing 'avail_out' bytes and\r
728  * reading from the current chunk as required.\r
729  */\r
730 static int\r
731 png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,\r
732    png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size,\r
733    int finish)\r
734 {\r
735    if (png_ptr->zowner == png_ptr->chunk_name)\r
736    {\r
737       int ret;\r
738 \r
739       /* next_in and avail_in must have been initialized by the caller. */\r
740       png_ptr->zstream.next_out = next_out;\r
741       png_ptr->zstream.avail_out = 0; /* set in the loop */\r
742 \r
743       do\r
744       {\r
745          if (png_ptr->zstream.avail_in == 0)\r
746          {\r
747             if (read_size > *chunk_bytes)\r
748                read_size = (uInt)*chunk_bytes;\r
749             *chunk_bytes -= read_size;\r
750 \r
751             if (read_size > 0)\r
752                png_crc_read(png_ptr, read_buffer, read_size);\r
753 \r
754             png_ptr->zstream.next_in = read_buffer;\r
755             png_ptr->zstream.avail_in = read_size;\r
756          }\r
757 \r
758          if (png_ptr->zstream.avail_out == 0)\r
759          {\r
760             uInt avail = ZLIB_IO_MAX;\r
761             if (avail > *out_size)\r
762                avail = (uInt)*out_size;\r
763             *out_size -= avail;\r
764 \r
765             png_ptr->zstream.avail_out = avail;\r
766          }\r
767 \r
768          /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all\r
769           * the available output is produced; this allows reading of truncated\r
770           * streams.\r
771           */\r
772          ret = inflate(&png_ptr->zstream,\r
773             *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH));\r
774       }\r
775       while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0));\r
776 \r
777       *out_size += png_ptr->zstream.avail_out;\r
778       png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */\r
779 \r
780       /* Ensure the error message pointer is always set: */\r
781       png_zstream_error(png_ptr, ret);\r
782       return ret;\r
783    }\r
784 \r
785    else\r
786    {\r
787       png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");\r
788       return Z_STREAM_ERROR;\r
789    }\r
790 }\r
791 #endif\r
792 \r
793 /* Read and check the IDHR chunk */\r
794 void /* PRIVATE */\r
795 png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
796 {\r
797    png_byte buf[13];\r
798    png_uint_32 width, height;\r
799    int bit_depth, color_type, compression_type, filter_type;\r
800    int interlace_type;\r
801 \r
802    png_debug(1, "in png_handle_IHDR");\r
803 \r
804    if (png_ptr->mode & PNG_HAVE_IHDR)\r
805       png_chunk_error(png_ptr, "out of place");\r
806 \r
807    /* Check the length */\r
808    if (length != 13)\r
809       png_chunk_error(png_ptr, "invalid");\r
810 \r
811    png_ptr->mode |= PNG_HAVE_IHDR;\r
812 \r
813    png_crc_read(png_ptr, buf, 13);\r
814    png_crc_finish(png_ptr, 0);\r
815 \r
816    width = png_get_uint_31(png_ptr, buf);\r
817    height = png_get_uint_31(png_ptr, buf + 4);\r
818    bit_depth = buf[8];\r
819    color_type = buf[9];\r
820    compression_type = buf[10];\r
821    filter_type = buf[11];\r
822    interlace_type = buf[12];\r
823 \r
824    /* Set internal variables */\r
825    png_ptr->width = width;\r
826    png_ptr->height = height;\r
827    png_ptr->bit_depth = (png_byte)bit_depth;\r
828    png_ptr->interlaced = (png_byte)interlace_type;\r
829    png_ptr->color_type = (png_byte)color_type;\r
830 #ifdef PNG_MNG_FEATURES_SUPPORTED\r
831    png_ptr->filter_type = (png_byte)filter_type;\r
832 #endif\r
833    png_ptr->compression_type = (png_byte)compression_type;\r
834 \r
835    /* Find number of channels */\r
836    switch (png_ptr->color_type)\r
837    {\r
838       default: /* invalid, png_set_IHDR calls png_error */\r
839       case PNG_COLOR_TYPE_GRAY:\r
840       case PNG_COLOR_TYPE_PALETTE:\r
841          png_ptr->channels = 1;\r
842          break;\r
843 \r
844       case PNG_COLOR_TYPE_RGB:\r
845          png_ptr->channels = 3;\r
846          break;\r
847 \r
848       case PNG_COLOR_TYPE_GRAY_ALPHA:\r
849          png_ptr->channels = 2;\r
850          break;\r
851 \r
852       case PNG_COLOR_TYPE_RGB_ALPHA:\r
853          png_ptr->channels = 4;\r
854          break;\r
855    }\r
856 \r
857    /* Set up other useful info */\r
858    png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *\r
859    png_ptr->channels);\r
860    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);\r
861    png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);\r
862    png_debug1(3, "channels = %d", png_ptr->channels);\r
863    png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes);\r
864    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,\r
865        color_type, interlace_type, compression_type, filter_type);\r
866 }\r
867 \r
868 /* Read and check the palette */\r
869 void /* PRIVATE */\r
870 png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
871 {\r
872    png_color palette[PNG_MAX_PALETTE_LENGTH];\r
873    int num, i;\r
874 #ifdef PNG_POINTER_INDEXING_SUPPORTED\r
875    png_colorp pal_ptr;\r
876 #endif\r
877 \r
878    png_debug(1, "in png_handle_PLTE");\r
879 \r
880    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
881       png_chunk_error(png_ptr, "missing IHDR");\r
882 \r
883    /* Moved to before the 'after IDAT' check below because otherwise duplicate\r
884     * PLTE chunks are potentially ignored (the spec says there shall not be more\r
885     * than one PLTE, the error is not treated as benign, so this check trumps\r
886     * the requirement that PLTE appears before IDAT.)\r
887     */\r
888    else if (png_ptr->mode & PNG_HAVE_PLTE)\r
889       png_chunk_error(png_ptr, "duplicate");\r
890 \r
891    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
892    {\r
893       /* This is benign because the non-benign error happened before, when an\r
894        * IDAT was encountered in a color-mapped image with no PLTE.\r
895        */\r
896       png_crc_finish(png_ptr, length);\r
897       png_chunk_benign_error(png_ptr, "out of place");\r
898       return;\r
899    }\r
900 \r
901    png_ptr->mode |= PNG_HAVE_PLTE;\r
902 \r
903    if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))\r
904    {\r
905       png_crc_finish(png_ptr, length);\r
906       png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");\r
907       return;\r
908    }\r
909 \r
910 #ifndef PNG_READ_OPT_PLTE_SUPPORTED\r
911    if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)\r
912    {\r
913       png_crc_finish(png_ptr, length);\r
914       return;\r
915    }\r
916 #endif\r
917 \r
918    if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)\r
919    {\r
920       png_crc_finish(png_ptr, length);\r
921 \r
922       if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)\r
923          png_chunk_benign_error(png_ptr, "invalid");\r
924 \r
925       else\r
926          png_chunk_error(png_ptr, "invalid");\r
927 \r
928       return;\r
929    }\r
930 \r
931    /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */\r
932    num = (int)length / 3;\r
933 \r
934 #ifdef PNG_POINTER_INDEXING_SUPPORTED\r
935    for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)\r
936    {\r
937       png_byte buf[3];\r
938 \r
939       png_crc_read(png_ptr, buf, 3);\r
940       pal_ptr->red = buf[0];\r
941       pal_ptr->green = buf[1];\r
942       pal_ptr->blue = buf[2];\r
943    }\r
944 #else\r
945    for (i = 0; i < num; i++)\r
946    {\r
947       png_byte buf[3];\r
948 \r
949       png_crc_read(png_ptr, buf, 3);\r
950       /* Don't depend upon png_color being any order */\r
951       palette[i].red = buf[0];\r
952       palette[i].green = buf[1];\r
953       palette[i].blue = buf[2];\r
954    }\r
955 #endif\r
956 \r
957    /* If we actually need the PLTE chunk (ie for a paletted image), we do\r
958     * whatever the normal CRC configuration tells us.  However, if we\r
959     * have an RGB image, the PLTE can be considered ancillary, so\r
960     * we will act as though it is.\r
961     */\r
962 #ifndef PNG_READ_OPT_PLTE_SUPPORTED\r
963    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
964 #endif\r
965    {\r
966       png_crc_finish(png_ptr, 0);\r
967    }\r
968 \r
969 #ifndef PNG_READ_OPT_PLTE_SUPPORTED\r
970    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */\r
971    {\r
972       /* If we don't want to use the data from an ancillary chunk,\r
973        * we have two options: an error abort, or a warning and we\r
974        * ignore the data in this chunk (which should be OK, since\r
975        * it's considered ancillary for a RGB or RGBA image).\r
976        *\r
977        * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the\r
978        * chunk type to determine whether to check the ancillary or the critical\r
979        * flags.\r
980        */\r
981       if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))\r
982       {\r
983          if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)\r
984          {\r
985             png_chunk_benign_error(png_ptr, "CRC error");\r
986          }\r
987 \r
988          else\r
989          {\r
990             png_chunk_warning(png_ptr, "CRC error");\r
991             return;\r
992          }\r
993       }\r
994 \r
995       /* Otherwise, we (optionally) emit a warning and use the chunk. */\r
996       else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))\r
997       {\r
998          png_chunk_warning(png_ptr, "CRC error");\r
999       }\r
1000    }\r
1001 #endif\r
1002 \r
1003    /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its\r
1004     * own copy of the palette.  This has the side effect that when png_start_row\r
1005     * is called (this happens after any call to png_read_update_info) the\r
1006     * info_ptr palette gets changed.  This is extremely unexpected and\r
1007     * confusing.\r
1008     *\r
1009     * Fix this by not sharing the palette in this way.\r
1010     */\r
1011    png_set_PLTE(png_ptr, info_ptr, palette, num);\r
1012 \r
1013    /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before\r
1014     * IDAT.  Prior to 1.6.0 this was not checked; instead the code merely\r
1015     * checked the apparent validity of a tRNS chunk inserted before PLTE on a\r
1016     * palette PNG.  1.6.0 attempts to rigorously follow the standard and\r
1017     * therefore does a benign error if the erroneous condition is detected *and*\r
1018     * cancels the tRNS if the benign error returns.  The alternative is to\r
1019     * amend the standard since it would be rather hypocritical of the standards\r
1020     * maintainers to ignore it.\r
1021     */\r
1022 #ifdef PNG_READ_tRNS_SUPPORTED\r
1023    if (png_ptr->num_trans > 0 ||\r
1024       (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))\r
1025    {\r
1026       /* Cancel this because otherwise it would be used if the transforms\r
1027        * require it.  Don't cancel the 'valid' flag because this would prevent\r
1028        * detection of duplicate chunks.\r
1029        */\r
1030       png_ptr->num_trans = 0;\r
1031 \r
1032       if (info_ptr != NULL)\r
1033          info_ptr->num_trans = 0;\r
1034 \r
1035       png_chunk_benign_error(png_ptr, "tRNS must be after");\r
1036    }\r
1037 #endif\r
1038 \r
1039 #ifdef PNG_READ_hIST_SUPPORTED\r
1040    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)\r
1041       png_chunk_benign_error(png_ptr, "hIST must be after");\r
1042 #endif\r
1043 \r
1044 #ifdef PNG_READ_bKGD_SUPPORTED\r
1045    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)\r
1046       png_chunk_benign_error(png_ptr, "bKGD must be after");\r
1047 #endif\r
1048 }\r
1049 \r
1050 void /* PRIVATE */\r
1051 png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1052 {\r
1053    png_debug(1, "in png_handle_IEND");\r
1054 \r
1055    if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))\r
1056       png_chunk_error(png_ptr, "out of place");\r
1057 \r
1058    png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);\r
1059 \r
1060    png_crc_finish(png_ptr, length);\r
1061 \r
1062    if (length != 0)\r
1063       png_chunk_benign_error(png_ptr, "invalid");\r
1064 \r
1065    PNG_UNUSED(info_ptr)\r
1066 }\r
1067 \r
1068 #ifdef PNG_READ_gAMA_SUPPORTED\r
1069 void /* PRIVATE */\r
1070 png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1071 {\r
1072    png_fixed_point igamma;\r
1073    png_byte buf[4];\r
1074 \r
1075    png_debug(1, "in png_handle_gAMA");\r
1076 \r
1077    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1078       png_chunk_error(png_ptr, "missing IHDR");\r
1079 \r
1080    else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE))\r
1081    {\r
1082       png_crc_finish(png_ptr, length);\r
1083       png_chunk_benign_error(png_ptr, "out of place");\r
1084       return;\r
1085    }\r
1086 \r
1087    if (length != 4)\r
1088    {\r
1089       png_crc_finish(png_ptr, length);\r
1090       png_chunk_benign_error(png_ptr, "invalid");\r
1091       return;\r
1092    }\r
1093 \r
1094    png_crc_read(png_ptr, buf, 4);\r
1095 \r
1096    if (png_crc_finish(png_ptr, 0))\r
1097       return;\r
1098 \r
1099    igamma = png_get_fixed_point(NULL, buf);\r
1100 \r
1101    png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);\r
1102    png_colorspace_sync(png_ptr, info_ptr);\r
1103 }\r
1104 #endif\r
1105 \r
1106 #ifdef PNG_READ_sBIT_SUPPORTED\r
1107 void /* PRIVATE */\r
1108 png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1109 {\r
1110    unsigned int truelen;\r
1111    png_byte buf[4];\r
1112 \r
1113    png_debug(1, "in png_handle_sBIT");\r
1114 \r
1115    buf[0] = buf[1] = buf[2] = buf[3] = 0;\r
1116 \r
1117    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1118       png_chunk_error(png_ptr, "missing IHDR");\r
1119 \r
1120    else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE))\r
1121    {\r
1122       png_crc_finish(png_ptr, length);\r
1123       png_chunk_benign_error(png_ptr, "out of place");\r
1124       return;\r
1125    }\r
1126 \r
1127    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))\r
1128    {\r
1129       png_crc_finish(png_ptr, length);\r
1130       png_chunk_benign_error(png_ptr, "duplicate");\r
1131       return;\r
1132    }\r
1133 \r
1134    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1135       truelen = 3;\r
1136 \r
1137    else\r
1138       truelen = png_ptr->channels;\r
1139 \r
1140    if (length != truelen || length > 4)\r
1141    {\r
1142       png_chunk_benign_error(png_ptr, "invalid");\r
1143       png_crc_finish(png_ptr, length);\r
1144       return;\r
1145    }\r
1146 \r
1147    png_crc_read(png_ptr, buf, truelen);\r
1148 \r
1149    if (png_crc_finish(png_ptr, 0))\r
1150       return;\r
1151 \r
1152    if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)\r
1153    {\r
1154       png_ptr->sig_bit.red = buf[0];\r
1155       png_ptr->sig_bit.green = buf[1];\r
1156       png_ptr->sig_bit.blue = buf[2];\r
1157       png_ptr->sig_bit.alpha = buf[3];\r
1158    }\r
1159 \r
1160    else\r
1161    {\r
1162       png_ptr->sig_bit.gray = buf[0];\r
1163       png_ptr->sig_bit.red = buf[0];\r
1164       png_ptr->sig_bit.green = buf[0];\r
1165       png_ptr->sig_bit.blue = buf[0];\r
1166       png_ptr->sig_bit.alpha = buf[1];\r
1167    }\r
1168 \r
1169    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));\r
1170 }\r
1171 #endif\r
1172 \r
1173 #ifdef PNG_READ_cHRM_SUPPORTED\r
1174 void /* PRIVATE */\r
1175 png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1176 {\r
1177    png_byte buf[32];\r
1178    png_xy xy;\r
1179 \r
1180    png_debug(1, "in png_handle_cHRM");\r
1181 \r
1182    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1183       png_chunk_error(png_ptr, "missing IHDR");\r
1184 \r
1185    else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE))\r
1186    {\r
1187       png_crc_finish(png_ptr, length);\r
1188       png_chunk_benign_error(png_ptr, "out of place");\r
1189       return;\r
1190    }\r
1191 \r
1192    if (length != 32)\r
1193    {\r
1194       png_crc_finish(png_ptr, length);\r
1195       png_chunk_benign_error(png_ptr, "invalid");\r
1196       return;\r
1197    }\r
1198 \r
1199    png_crc_read(png_ptr, buf, 32);\r
1200 \r
1201    if (png_crc_finish(png_ptr, 0))\r
1202       return;\r
1203 \r
1204    xy.whitex = png_get_fixed_point(NULL, buf);\r
1205    xy.whitey = png_get_fixed_point(NULL, buf + 4);\r
1206    xy.redx   = png_get_fixed_point(NULL, buf + 8);\r
1207    xy.redy   = png_get_fixed_point(NULL, buf + 12);\r
1208    xy.greenx = png_get_fixed_point(NULL, buf + 16);\r
1209    xy.greeny = png_get_fixed_point(NULL, buf + 20);\r
1210    xy.bluex  = png_get_fixed_point(NULL, buf + 24);\r
1211    xy.bluey  = png_get_fixed_point(NULL, buf + 28);\r
1212 \r
1213    if (xy.whitex == PNG_FIXED_ERROR ||\r
1214        xy.whitey == PNG_FIXED_ERROR ||\r
1215        xy.redx   == PNG_FIXED_ERROR ||\r
1216        xy.redy   == PNG_FIXED_ERROR ||\r
1217        xy.greenx == PNG_FIXED_ERROR ||\r
1218        xy.greeny == PNG_FIXED_ERROR ||\r
1219        xy.bluex  == PNG_FIXED_ERROR ||\r
1220        xy.bluey  == PNG_FIXED_ERROR)\r
1221    {\r
1222       png_chunk_benign_error(png_ptr, "invalid values");\r
1223       return;\r
1224    }\r
1225 \r
1226    /* If a colorspace error has already been output skip this chunk */\r
1227    if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID)\r
1228       return;\r
1229 \r
1230    if (png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM)\r
1231    {\r
1232       png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;\r
1233       png_colorspace_sync(png_ptr, info_ptr);\r
1234       png_chunk_benign_error(png_ptr, "duplicate");\r
1235       return;\r
1236    }\r
1237 \r
1238    png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;\r
1239    (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,\r
1240       1/*prefer cHRM values*/);\r
1241    png_colorspace_sync(png_ptr, info_ptr);\r
1242 }\r
1243 #endif\r
1244 \r
1245 #ifdef PNG_READ_sRGB_SUPPORTED\r
1246 void /* PRIVATE */\r
1247 png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1248 {\r
1249    png_byte intent;\r
1250 \r
1251    png_debug(1, "in png_handle_sRGB");\r
1252 \r
1253    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1254       png_chunk_error(png_ptr, "missing IHDR");\r
1255 \r
1256    else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE))\r
1257    {\r
1258       png_crc_finish(png_ptr, length);\r
1259       png_chunk_benign_error(png_ptr, "out of place");\r
1260       return;\r
1261    }\r
1262 \r
1263    if (length != 1)\r
1264    {\r
1265       png_crc_finish(png_ptr, length);\r
1266       png_chunk_benign_error(png_ptr, "invalid");\r
1267       return;\r
1268    }\r
1269 \r
1270    png_crc_read(png_ptr, &intent, 1);\r
1271 \r
1272    if (png_crc_finish(png_ptr, 0))\r
1273       return;\r
1274 \r
1275    /* If a colorspace error has already been output skip this chunk */\r
1276    if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID)\r
1277       return;\r
1278 \r
1279    /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect\r
1280     * this.\r
1281     */\r
1282    if (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT)\r
1283    {\r
1284       png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;\r
1285       png_colorspace_sync(png_ptr, info_ptr);\r
1286       png_chunk_benign_error(png_ptr, "too many profiles");\r
1287       return;\r
1288    }\r
1289 \r
1290    (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);\r
1291    png_colorspace_sync(png_ptr, info_ptr);\r
1292 }\r
1293 #endif /* PNG_READ_sRGB_SUPPORTED */\r
1294 \r
1295 #ifdef PNG_READ_iCCP_SUPPORTED\r
1296 void /* PRIVATE */\r
1297 png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1298 /* Note: this does not properly handle profiles that are > 64K under DOS */\r
1299 {\r
1300    png_const_charp errmsg = NULL; /* error message output, or no error */\r
1301    int finished = 0; /* crc checked */\r
1302 \r
1303    png_debug(1, "in png_handle_iCCP");\r
1304 \r
1305    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1306       png_chunk_error(png_ptr, "missing IHDR");\r
1307 \r
1308    else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE))\r
1309    {\r
1310       png_crc_finish(png_ptr, length);\r
1311       png_chunk_benign_error(png_ptr, "out of place");\r
1312       return;\r
1313    }\r
1314 \r
1315    /* Consistent with all the above colorspace handling an obviously *invalid*\r
1316     * chunk is just ignored, so does not invalidate the color space.  An\r
1317     * alternative is to set the 'invalid' flags at the start of this routine\r
1318     * and only clear them in they were not set before and all the tests pass.\r
1319     * The minimum 'deflate' stream is assumed to be just the 2 byte header and 4\r
1320     * byte checksum.  The keyword must be one character and there is a\r
1321     * terminator (0) byte and the compression method.\r
1322     */\r
1323    if (length < 9)\r
1324    {\r
1325       png_crc_finish(png_ptr, length);\r
1326       png_chunk_benign_error(png_ptr, "too short");\r
1327       return;\r
1328    }\r
1329 \r
1330    /* If a colorspace error has already been output skip this chunk */\r
1331    if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID)\r
1332    {\r
1333       png_crc_finish(png_ptr, length);\r
1334       return;\r
1335    }\r
1336 \r
1337    /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect\r
1338     * this.\r
1339     */\r
1340    if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)\r
1341    {\r
1342       uInt read_length, keyword_length;\r
1343       char keyword[81];\r
1344 \r
1345       /* Find the keyword; the keyword plus separator and compression method\r
1346        * bytes can be at most 81 characters long.\r
1347        */\r
1348       read_length = 81; /* maximum */\r
1349       if (read_length > length)\r
1350          read_length = (uInt)length;\r
1351 \r
1352       png_crc_read(png_ptr, (png_bytep)keyword, read_length);\r
1353       length -= read_length;\r
1354 \r
1355       keyword_length = 0;\r
1356       while (keyword_length < 80 && keyword_length < read_length &&\r
1357          keyword[keyword_length] != 0)\r
1358          ++keyword_length;\r
1359 \r
1360       /* TODO: make the keyword checking common */\r
1361       if (keyword_length >= 1 && keyword_length <= 79)\r
1362       {\r
1363          /* We only understand '0' compression - deflate - so if we get a\r
1364           * different value we can't safely decode the chunk.\r
1365           */\r
1366          if (keyword_length+1 < read_length &&\r
1367             keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE)\r
1368          {\r
1369             read_length -= keyword_length+2;\r
1370 \r
1371             if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK)\r
1372             {\r
1373                Byte profile_header[132];\r
1374                Byte local_buffer[PNG_INFLATE_BUF_SIZE];\r
1375                png_alloc_size_t size = (sizeof profile_header);\r
1376 \r
1377                png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2);\r
1378                png_ptr->zstream.avail_in = read_length;\r
1379                (void)png_inflate_read(png_ptr, local_buffer,\r
1380                   (sizeof local_buffer), &length, profile_header, &size,\r
1381                   0/*finish: don't, because the output is too small*/);\r
1382 \r
1383                if (size == 0)\r
1384                {\r
1385                   /* We have the ICC profile header; do the basic header checks.\r
1386                    */\r
1387                   const png_uint_32 profile_length =\r
1388                      png_get_uint_32(profile_header);\r
1389 \r
1390                   if (png_icc_check_length(png_ptr, &png_ptr->colorspace,\r
1391                      keyword, profile_length))\r
1392                   {\r
1393                      /* The length is apparently ok, so we can check the 132\r
1394                       * byte header.\r
1395                       */\r
1396                      if (png_icc_check_header(png_ptr, &png_ptr->colorspace,\r
1397                         keyword, profile_length, profile_header,\r
1398                         png_ptr->color_type))\r
1399                      {\r
1400                         /* Now read the tag table; a variable size buffer is\r
1401                          * needed at this point, allocate one for the whole\r
1402                          * profile.  The header check has already validated\r
1403                          * that none of these stuff will overflow.\r
1404                          */\r
1405                         const png_uint_32 tag_count = png_get_uint_32(\r
1406                            profile_header+128);\r
1407                         png_bytep profile = png_read_buffer(png_ptr,\r
1408                            profile_length, 2/*silent*/);\r
1409 \r
1410                         if (profile != NULL)\r
1411                         {\r
1412                            memcpy(profile, profile_header,\r
1413                               (sizeof profile_header));\r
1414 \r
1415                            size = 12 * tag_count;\r
1416 \r
1417                            (void)png_inflate_read(png_ptr, local_buffer,\r
1418                               (sizeof local_buffer), &length,\r
1419                               profile + (sizeof profile_header), &size, 0);\r
1420 \r
1421                            /* Still expect a a buffer error because we expect\r
1422                             * there to be some tag data!\r
1423                             */\r
1424                            if (size == 0)\r
1425                            {\r
1426                               if (png_icc_check_tag_table(png_ptr,\r
1427                                  &png_ptr->colorspace, keyword, profile_length,\r
1428                                  profile))\r
1429                               {\r
1430                                  /* The profile has been validated for basic\r
1431                                   * security issues, so read the whole thing in.\r
1432                                   */\r
1433                                  size = profile_length - (sizeof profile_header)\r
1434                                     - 12 * tag_count;\r
1435 \r
1436                                  (void)png_inflate_read(png_ptr, local_buffer,\r
1437                                     (sizeof local_buffer), &length,\r
1438                                     profile + (sizeof profile_header) +\r
1439                                     12 * tag_count, &size, 1/*finish*/);\r
1440 \r
1441                                  if (length > 0 && !(png_ptr->flags &\r
1442                                        PNG_FLAG_BENIGN_ERRORS_WARN))\r
1443                                     errmsg = "extra compressed data";\r
1444 \r
1445                                  /* But otherwise allow extra data: */\r
1446                                  else if (size == 0)\r
1447                                  {\r
1448                                     if (length > 0)\r
1449                                     {\r
1450                                        /* This can be handled completely, so\r
1451                                         * keep going.\r
1452                                         */\r
1453                                        png_chunk_warning(png_ptr,\r
1454                                           "extra compressed data");\r
1455                                     }\r
1456 \r
1457                                     png_crc_finish(png_ptr, length);\r
1458                                     finished = 1;\r
1459 \r
1460 #                                   ifdef PNG_sRGB_SUPPORTED\r
1461                                        /* Check for a match against sRGB */\r
1462                                        png_icc_set_sRGB(png_ptr,\r
1463                                           &png_ptr->colorspace, profile,\r
1464                                           png_ptr->zstream.adler);\r
1465 #                                   endif\r
1466 \r
1467                                     /* Steal the profile for info_ptr. */\r
1468                                     if (info_ptr != NULL)\r
1469                                     {\r
1470                                        png_free_data(png_ptr, info_ptr,\r
1471                                           PNG_FREE_ICCP, 0);\r
1472 \r
1473                                        info_ptr->iccp_name = png_voidcast(char*,\r
1474                                           png_malloc_base(png_ptr,\r
1475                                           keyword_length+1));\r
1476                                        if (info_ptr->iccp_name != NULL)\r
1477                                        {\r
1478                                           memcpy(info_ptr->iccp_name, keyword,\r
1479                                              keyword_length+1);\r
1480                                           info_ptr->iccp_proflen =\r
1481                                              profile_length;\r
1482                                           info_ptr->iccp_profile = profile;\r
1483                                           png_ptr->read_buffer = NULL; /*steal*/\r
1484                                           info_ptr->free_me |= PNG_FREE_ICCP;\r
1485                                           info_ptr->valid |= PNG_INFO_iCCP;\r
1486                                        }\r
1487 \r
1488                                        else\r
1489                                        {\r
1490                                           png_ptr->colorspace.flags |=\r
1491                                              PNG_COLORSPACE_INVALID;\r
1492                                           errmsg = "out of memory";\r
1493                                        }\r
1494                                     }\r
1495 \r
1496                                     /* else the profile remains in the read\r
1497                                      * buffer which gets reused for subsequent\r
1498                                      * chunks.\r
1499                                      */\r
1500 \r
1501                                     if (info_ptr != NULL)\r
1502                                        png_colorspace_sync(png_ptr, info_ptr);\r
1503 \r
1504                                     if (errmsg == NULL)\r
1505                                     {\r
1506                                        png_ptr->zowner = 0;\r
1507                                        return;\r
1508                                     }\r
1509                                  }\r
1510 \r
1511                                  else if (size > 0)\r
1512                                     errmsg = "truncated";\r
1513 \r
1514                                  else\r
1515                                     errmsg = png_ptr->zstream.msg;\r
1516                               }\r
1517 \r
1518                               /* else png_icc_check_tag_table output an error */\r
1519                            }\r
1520 \r
1521                            else /* profile truncated */\r
1522                               errmsg = png_ptr->zstream.msg;\r
1523                         }\r
1524 \r
1525                         else\r
1526                            errmsg = "out of memory";\r
1527                      }\r
1528 \r
1529                      /* else png_icc_check_header output an error */\r
1530                   }\r
1531 \r
1532                   /* else png_icc_check_length output an error */\r
1533                }\r
1534 \r
1535                else /* profile truncated */\r
1536                   errmsg = png_ptr->zstream.msg;\r
1537 \r
1538                /* Release the stream */\r
1539                png_ptr->zowner = 0;\r
1540             }\r
1541 \r
1542             else /* png_inflate_claim failed */\r
1543                errmsg = png_ptr->zstream.msg;\r
1544          }\r
1545 \r
1546          else\r
1547             errmsg = "bad compression method"; /* or missing */\r
1548       }\r
1549 \r
1550       else\r
1551          errmsg = "bad keyword";\r
1552    }\r
1553 \r
1554    else\r
1555       errmsg = "too many profiles";\r
1556 \r
1557    /* Failure: the reason is in 'errmsg' */\r
1558    if (!finished)\r
1559       png_crc_finish(png_ptr, length);\r
1560 \r
1561    png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;\r
1562    png_colorspace_sync(png_ptr, info_ptr);\r
1563    if (errmsg != NULL) /* else already output */\r
1564       png_chunk_benign_error(png_ptr, errmsg);\r
1565 }\r
1566 #endif /* PNG_READ_iCCP_SUPPORTED */\r
1567 \r
1568 #ifdef PNG_READ_sPLT_SUPPORTED\r
1569 void /* PRIVATE */\r
1570 png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1571 /* Note: this does not properly handle chunks that are > 64K under DOS */\r
1572 {\r
1573    png_bytep entry_start, buffer;\r
1574    png_sPLT_t new_palette;\r
1575    png_sPLT_entryp pp;\r
1576    png_uint_32 data_length;\r
1577    int entry_size, i;\r
1578    png_uint_32 skip = 0;\r
1579    png_uint_32 dl;\r
1580    png_size_t max_dl;\r
1581 \r
1582    png_debug(1, "in png_handle_sPLT");\r
1583 \r
1584 #ifdef PNG_USER_LIMITS_SUPPORTED\r
1585    if (png_ptr->user_chunk_cache_max != 0)\r
1586    {\r
1587       if (png_ptr->user_chunk_cache_max == 1)\r
1588       {\r
1589          png_crc_finish(png_ptr, length);\r
1590          return;\r
1591       }\r
1592 \r
1593       if (--png_ptr->user_chunk_cache_max == 1)\r
1594       {\r
1595          png_warning(png_ptr, "No space in chunk cache for sPLT");\r
1596          png_crc_finish(png_ptr, length);\r
1597          return;\r
1598       }\r
1599    }\r
1600 #endif\r
1601 \r
1602    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1603       png_chunk_error(png_ptr, "missing IHDR");\r
1604 \r
1605    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
1606    {\r
1607       png_crc_finish(png_ptr, length);\r
1608       png_chunk_benign_error(png_ptr, "out of place");\r
1609       return;\r
1610    }\r
1611 \r
1612 #ifdef PNG_MAX_MALLOC_64K\r
1613    if (length > 65535U)\r
1614    {\r
1615       png_crc_finish(png_ptr, length);\r
1616       png_chunk_benign_error(png_ptr, "too large to fit in memory");\r
1617       return;\r
1618    }\r
1619 #endif\r
1620 \r
1621    buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);\r
1622    if (buffer == NULL)\r
1623    {\r
1624       png_crc_finish(png_ptr, length);\r
1625       png_chunk_benign_error(png_ptr, "out of memory");\r
1626       return;\r
1627    }\r
1628 \r
1629 \r
1630    /* WARNING: this may break if size_t is less than 32 bits; it is assumed\r
1631     * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a\r
1632     * potential breakage point if the types in pngconf.h aren't exactly right.\r
1633     */\r
1634    png_crc_read(png_ptr, buffer, length);\r
1635 \r
1636    if (png_crc_finish(png_ptr, skip))\r
1637       return;\r
1638 \r
1639    buffer[length] = 0;\r
1640 \r
1641    for (entry_start = buffer; *entry_start; entry_start++)\r
1642       /* Empty loop to find end of name */ ;\r
1643 \r
1644    ++entry_start;\r
1645 \r
1646    /* A sample depth should follow the separator, and we should be on it  */\r
1647    if (entry_start > buffer + length - 2)\r
1648    {\r
1649       png_warning(png_ptr, "malformed sPLT chunk");\r
1650       return;\r
1651    }\r
1652 \r
1653    new_palette.depth = *entry_start++;\r
1654    entry_size = (new_palette.depth == 8 ? 6 : 10);\r
1655    /* This must fit in a png_uint_32 because it is derived from the original\r
1656     * chunk data length.\r
1657     */\r
1658    data_length = length - (png_uint_32)(entry_start - buffer);\r
1659 \r
1660    /* Integrity-check the data length */\r
1661    if (data_length % entry_size)\r
1662    {\r
1663       png_warning(png_ptr, "sPLT chunk has bad length");\r
1664       return;\r
1665    }\r
1666 \r
1667    dl = (png_int_32)(data_length / entry_size);\r
1668    max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry));\r
1669 \r
1670    if (dl > max_dl)\r
1671    {\r
1672        png_warning(png_ptr, "sPLT chunk too long");\r
1673        return;\r
1674    }\r
1675 \r
1676    new_palette.nentries = (png_int_32)(data_length / entry_size);\r
1677 \r
1678    new_palette.entries = (png_sPLT_entryp)png_malloc_warn(\r
1679        png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry)));\r
1680 \r
1681    if (new_palette.entries == NULL)\r
1682    {\r
1683        png_warning(png_ptr, "sPLT chunk requires too much memory");\r
1684        return;\r
1685    }\r
1686 \r
1687 #ifdef PNG_POINTER_INDEXING_SUPPORTED\r
1688    for (i = 0; i < new_palette.nentries; i++)\r
1689    {\r
1690       pp = new_palette.entries + i;\r
1691 \r
1692       if (new_palette.depth == 8)\r
1693       {\r
1694          pp->red = *entry_start++;\r
1695          pp->green = *entry_start++;\r
1696          pp->blue = *entry_start++;\r
1697          pp->alpha = *entry_start++;\r
1698       }\r
1699 \r
1700       else\r
1701       {\r
1702          pp->red   = png_get_uint_16(entry_start); entry_start += 2;\r
1703          pp->green = png_get_uint_16(entry_start); entry_start += 2;\r
1704          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;\r
1705          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;\r
1706       }\r
1707 \r
1708       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;\r
1709    }\r
1710 #else\r
1711    pp = new_palette.entries;\r
1712 \r
1713    for (i = 0; i < new_palette.nentries; i++)\r
1714    {\r
1715 \r
1716       if (new_palette.depth == 8)\r
1717       {\r
1718          pp[i].red   = *entry_start++;\r
1719          pp[i].green = *entry_start++;\r
1720          pp[i].blue  = *entry_start++;\r
1721          pp[i].alpha = *entry_start++;\r
1722       }\r
1723 \r
1724       else\r
1725       {\r
1726          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;\r
1727          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;\r
1728          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;\r
1729          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;\r
1730       }\r
1731 \r
1732       pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;\r
1733    }\r
1734 #endif\r
1735 \r
1736    /* Discard all chunk data except the name and stash that */\r
1737    new_palette.name = (png_charp)buffer;\r
1738 \r
1739    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);\r
1740 \r
1741    png_free(png_ptr, new_palette.entries);\r
1742 }\r
1743 #endif /* PNG_READ_sPLT_SUPPORTED */\r
1744 \r
1745 #ifdef PNG_READ_tRNS_SUPPORTED\r
1746 void /* PRIVATE */\r
1747 png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1748 {\r
1749    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];\r
1750 \r
1751    png_debug(1, "in png_handle_tRNS");\r
1752 \r
1753    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1754       png_chunk_error(png_ptr, "missing IHDR");\r
1755 \r
1756    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
1757    {\r
1758       png_crc_finish(png_ptr, length);\r
1759       png_chunk_benign_error(png_ptr, "out of place");\r
1760       return;\r
1761    }\r
1762 \r
1763    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))\r
1764    {\r
1765       png_crc_finish(png_ptr, length);\r
1766       png_chunk_benign_error(png_ptr, "duplicate");\r
1767       return;\r
1768    }\r
1769 \r
1770    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)\r
1771    {\r
1772       png_byte buf[2];\r
1773 \r
1774       if (length != 2)\r
1775       {\r
1776          png_crc_finish(png_ptr, length);\r
1777          png_chunk_benign_error(png_ptr, "invalid");\r
1778          return;\r
1779       }\r
1780 \r
1781       png_crc_read(png_ptr, buf, 2);\r
1782       png_ptr->num_trans = 1;\r
1783       png_ptr->trans_color.gray = png_get_uint_16(buf);\r
1784    }\r
1785 \r
1786    else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)\r
1787    {\r
1788       png_byte buf[6];\r
1789 \r
1790       if (length != 6)\r
1791       {\r
1792          png_crc_finish(png_ptr, length);\r
1793          png_chunk_benign_error(png_ptr, "invalid");\r
1794          return;\r
1795       }\r
1796 \r
1797       png_crc_read(png_ptr, buf, length);\r
1798       png_ptr->num_trans = 1;\r
1799       png_ptr->trans_color.red = png_get_uint_16(buf);\r
1800       png_ptr->trans_color.green = png_get_uint_16(buf + 2);\r
1801       png_ptr->trans_color.blue = png_get_uint_16(buf + 4);\r
1802    }\r
1803 \r
1804    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1805    {\r
1806       if (!(png_ptr->mode & PNG_HAVE_PLTE))\r
1807       {\r
1808          /* TODO: is this actually an error in the ISO spec? */\r
1809          png_crc_finish(png_ptr, length);\r
1810          png_chunk_benign_error(png_ptr, "out of place");\r
1811          return;\r
1812       }\r
1813 \r
1814       if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH ||\r
1815          length == 0)\r
1816       {\r
1817          png_crc_finish(png_ptr, length);\r
1818          png_chunk_benign_error(png_ptr, "invalid");\r
1819          return;\r
1820       }\r
1821 \r
1822       png_crc_read(png_ptr, readbuf, length);\r
1823       png_ptr->num_trans = (png_uint_16)length;\r
1824    }\r
1825 \r
1826    else\r
1827    {\r
1828       png_crc_finish(png_ptr, length);\r
1829       png_chunk_benign_error(png_ptr, "invalid with alpha channel");\r
1830       return;\r
1831    }\r
1832 \r
1833    if (png_crc_finish(png_ptr, 0))\r
1834    {\r
1835       png_ptr->num_trans = 0;\r
1836       return;\r
1837    }\r
1838 \r
1839    /* TODO: this is a horrible side effect in the palette case because the\r
1840     * png_struct ends up with a pointer to the tRNS buffer owned by the\r
1841     * png_info.  Fix this.\r
1842     */\r
1843    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,\r
1844        &(png_ptr->trans_color));\r
1845 }\r
1846 #endif\r
1847 \r
1848 #ifdef PNG_READ_bKGD_SUPPORTED\r
1849 void /* PRIVATE */\r
1850 png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1851 {\r
1852    unsigned int truelen;\r
1853    png_byte buf[6];\r
1854    png_color_16 background;\r
1855 \r
1856    png_debug(1, "in png_handle_bKGD");\r
1857 \r
1858    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1859       png_chunk_error(png_ptr, "missing IHDR");\r
1860 \r
1861    else if ((png_ptr->mode & PNG_HAVE_IDAT) ||\r
1862       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&\r
1863        !(png_ptr->mode & PNG_HAVE_PLTE)))\r
1864    {\r
1865       png_crc_finish(png_ptr, length);\r
1866       png_chunk_benign_error(png_ptr, "out of place");\r
1867       return;\r
1868    }\r
1869 \r
1870    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))\r
1871    {\r
1872       png_crc_finish(png_ptr, length);\r
1873       png_chunk_benign_error(png_ptr, "duplicate");\r
1874       return;\r
1875    }\r
1876 \r
1877    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1878       truelen = 1;\r
1879 \r
1880    else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)\r
1881       truelen = 6;\r
1882 \r
1883    else\r
1884       truelen = 2;\r
1885 \r
1886    if (length != truelen)\r
1887    {\r
1888       png_crc_finish(png_ptr, length);\r
1889       png_chunk_benign_error(png_ptr, "invalid");\r
1890       return;\r
1891    }\r
1892 \r
1893    png_crc_read(png_ptr, buf, truelen);\r
1894 \r
1895    if (png_crc_finish(png_ptr, 0))\r
1896       return;\r
1897 \r
1898    /* We convert the index value into RGB components so that we can allow\r
1899     * arbitrary RGB values for background when we have transparency, and\r
1900     * so it is easy to determine the RGB values of the background color\r
1901     * from the info_ptr struct.\r
1902     */\r
1903    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
1904    {\r
1905       background.index = buf[0];\r
1906 \r
1907       if (info_ptr && info_ptr->num_palette)\r
1908       {\r
1909          if (buf[0] >= info_ptr->num_palette)\r
1910          {\r
1911             png_chunk_benign_error(png_ptr, "invalid index");\r
1912             return;\r
1913          }\r
1914 \r
1915          background.red = (png_uint_16)png_ptr->palette[buf[0]].red;\r
1916          background.green = (png_uint_16)png_ptr->palette[buf[0]].green;\r
1917          background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;\r
1918       }\r
1919 \r
1920       else\r
1921          background.red = background.green = background.blue = 0;\r
1922 \r
1923       background.gray = 0;\r
1924    }\r
1925 \r
1926    else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */\r
1927    {\r
1928       background.index = 0;\r
1929       background.red =\r
1930       background.green =\r
1931       background.blue =\r
1932       background.gray = png_get_uint_16(buf);\r
1933    }\r
1934 \r
1935    else\r
1936    {\r
1937       background.index = 0;\r
1938       background.red = png_get_uint_16(buf);\r
1939       background.green = png_get_uint_16(buf + 2);\r
1940       background.blue = png_get_uint_16(buf + 4);\r
1941       background.gray = 0;\r
1942    }\r
1943 \r
1944    png_set_bKGD(png_ptr, info_ptr, &background);\r
1945 }\r
1946 #endif\r
1947 \r
1948 #ifdef PNG_READ_hIST_SUPPORTED\r
1949 void /* PRIVATE */\r
1950 png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
1951 {\r
1952    unsigned int num, i;\r
1953    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];\r
1954 \r
1955    png_debug(1, "in png_handle_hIST");\r
1956 \r
1957    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
1958       png_chunk_error(png_ptr, "missing IHDR");\r
1959 \r
1960    else if ((png_ptr->mode & PNG_HAVE_IDAT) || !(png_ptr->mode & PNG_HAVE_PLTE))\r
1961    {\r
1962       png_crc_finish(png_ptr, length);\r
1963       png_chunk_benign_error(png_ptr, "out of place");\r
1964       return;\r
1965    }\r
1966 \r
1967    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))\r
1968    {\r
1969       png_crc_finish(png_ptr, length);\r
1970       png_chunk_benign_error(png_ptr, "duplicate");\r
1971       return;\r
1972    }\r
1973 \r
1974    num = length / 2 ;\r
1975 \r
1976    if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH)\r
1977    {\r
1978       png_crc_finish(png_ptr, length);\r
1979       png_chunk_benign_error(png_ptr, "invalid");\r
1980       return;\r
1981    }\r
1982 \r
1983    for (i = 0; i < num; i++)\r
1984    {\r
1985       png_byte buf[2];\r
1986 \r
1987       png_crc_read(png_ptr, buf, 2);\r
1988       readbuf[i] = png_get_uint_16(buf);\r
1989    }\r
1990 \r
1991    if (png_crc_finish(png_ptr, 0))\r
1992       return;\r
1993 \r
1994    png_set_hIST(png_ptr, info_ptr, readbuf);\r
1995 }\r
1996 #endif\r
1997 \r
1998 #ifdef PNG_READ_pHYs_SUPPORTED\r
1999 void /* PRIVATE */\r
2000 png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2001 {\r
2002    png_byte buf[9];\r
2003    png_uint_32 res_x, res_y;\r
2004    int unit_type;\r
2005 \r
2006    png_debug(1, "in png_handle_pHYs");\r
2007 \r
2008    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2009       png_chunk_error(png_ptr, "missing IHDR");\r
2010 \r
2011    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
2012    {\r
2013       png_crc_finish(png_ptr, length);\r
2014       png_chunk_benign_error(png_ptr, "out of place");\r
2015       return;\r
2016    }\r
2017 \r
2018    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))\r
2019    {\r
2020       png_crc_finish(png_ptr, length);\r
2021       png_chunk_benign_error(png_ptr, "duplicate");\r
2022       return;\r
2023    }\r
2024 \r
2025    if (length != 9)\r
2026    {\r
2027       png_crc_finish(png_ptr, length);\r
2028       png_chunk_benign_error(png_ptr, "invalid");\r
2029       return;\r
2030    }\r
2031 \r
2032    png_crc_read(png_ptr, buf, 9);\r
2033 \r
2034    if (png_crc_finish(png_ptr, 0))\r
2035       return;\r
2036 \r
2037    res_x = png_get_uint_32(buf);\r
2038    res_y = png_get_uint_32(buf + 4);\r
2039    unit_type = buf[8];\r
2040    png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);\r
2041 }\r
2042 #endif\r
2043 \r
2044 #ifdef PNG_READ_oFFs_SUPPORTED\r
2045 void /* PRIVATE */\r
2046 png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2047 {\r
2048    png_byte buf[9];\r
2049    png_int_32 offset_x, offset_y;\r
2050    int unit_type;\r
2051 \r
2052    png_debug(1, "in png_handle_oFFs");\r
2053 \r
2054    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2055       png_chunk_error(png_ptr, "missing IHDR");\r
2056 \r
2057    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
2058    {\r
2059       png_crc_finish(png_ptr, length);\r
2060       png_chunk_benign_error(png_ptr, "out of place");\r
2061       return;\r
2062    }\r
2063 \r
2064    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))\r
2065    {\r
2066       png_crc_finish(png_ptr, length);\r
2067       png_chunk_benign_error(png_ptr, "duplicate");\r
2068       return;\r
2069    }\r
2070 \r
2071    if (length != 9)\r
2072    {\r
2073       png_crc_finish(png_ptr, length);\r
2074       png_chunk_benign_error(png_ptr, "invalid");\r
2075       return;\r
2076    }\r
2077 \r
2078    png_crc_read(png_ptr, buf, 9);\r
2079 \r
2080    if (png_crc_finish(png_ptr, 0))\r
2081       return;\r
2082 \r
2083    offset_x = png_get_int_32(buf);\r
2084    offset_y = png_get_int_32(buf + 4);\r
2085    unit_type = buf[8];\r
2086    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);\r
2087 }\r
2088 #endif\r
2089 \r
2090 #ifdef PNG_READ_pCAL_SUPPORTED\r
2091 /* Read the pCAL chunk (described in the PNG Extensions document) */\r
2092 void /* PRIVATE */\r
2093 png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2094 {\r
2095    png_int_32 X0, X1;\r
2096    png_byte type, nparams;\r
2097    png_bytep buffer, buf, units, endptr;\r
2098    png_charpp params;\r
2099    int i;\r
2100 \r
2101    png_debug(1, "in png_handle_pCAL");\r
2102 \r
2103    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2104       png_chunk_error(png_ptr, "missing IHDR");\r
2105 \r
2106    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
2107    {\r
2108       png_crc_finish(png_ptr, length);\r
2109       png_chunk_benign_error(png_ptr, "out of place");\r
2110       return;\r
2111    }\r
2112 \r
2113    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))\r
2114    {\r
2115       png_crc_finish(png_ptr, length);\r
2116       png_chunk_benign_error(png_ptr, "duplicate");\r
2117       return;\r
2118    }\r
2119 \r
2120    png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",\r
2121        length + 1);\r
2122 \r
2123    buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);\r
2124 \r
2125    if (buffer == NULL)\r
2126    {\r
2127       png_crc_finish(png_ptr, length);\r
2128       png_chunk_benign_error(png_ptr, "out of memory");\r
2129       return;\r
2130    }\r
2131 \r
2132    png_crc_read(png_ptr, buffer, length);\r
2133 \r
2134    if (png_crc_finish(png_ptr, 0))\r
2135       return;\r
2136 \r
2137    buffer[length] = 0; /* Null terminate the last string */\r
2138 \r
2139    png_debug(3, "Finding end of pCAL purpose string");\r
2140    for (buf = buffer; *buf; buf++)\r
2141       /* Empty loop */ ;\r
2142 \r
2143    endptr = buffer + length;\r
2144 \r
2145    /* We need to have at least 12 bytes after the purpose string\r
2146     * in order to get the parameter information.\r
2147     */\r
2148    if (endptr <= buf + 12)\r
2149    {\r
2150       png_chunk_benign_error(png_ptr, "invalid");\r
2151       return;\r
2152    }\r
2153 \r
2154    png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");\r
2155    X0 = png_get_int_32((png_bytep)buf+1);\r
2156    X1 = png_get_int_32((png_bytep)buf+5);\r
2157    type = buf[9];\r
2158    nparams = buf[10];\r
2159    units = buf + 11;\r
2160 \r
2161    png_debug(3, "Checking pCAL equation type and number of parameters");\r
2162    /* Check that we have the right number of parameters for known\r
2163     * equation types.\r
2164     */\r
2165    if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||\r
2166        (type == PNG_EQUATION_BASE_E && nparams != 3) ||\r
2167        (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||\r
2168        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))\r
2169    {\r
2170       png_chunk_benign_error(png_ptr, "invalid parameter count");\r
2171       return;\r
2172    }\r
2173 \r
2174    else if (type >= PNG_EQUATION_LAST)\r
2175    {\r
2176       png_chunk_benign_error(png_ptr, "unrecognized equation type");\r
2177    }\r
2178 \r
2179    for (buf = units; *buf; buf++)\r
2180       /* Empty loop to move past the units string. */ ;\r
2181 \r
2182    png_debug(3, "Allocating pCAL parameters array");\r
2183 \r
2184    params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,\r
2185        nparams * (sizeof (png_charp))));\r
2186 \r
2187    if (params == NULL)\r
2188    {\r
2189       png_chunk_benign_error(png_ptr, "out of memory");\r
2190       return;\r
2191    }\r
2192 \r
2193    /* Get pointers to the start of each parameter string. */\r
2194    for (i = 0; i < nparams; i++)\r
2195    {\r
2196       buf++; /* Skip the null string terminator from previous parameter. */\r
2197 \r
2198       png_debug1(3, "Reading pCAL parameter %d", i);\r
2199 \r
2200       for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++)\r
2201          /* Empty loop to move past each parameter string */ ;\r
2202 \r
2203       /* Make sure we haven't run out of data yet */\r
2204       if (buf > endptr)\r
2205       {\r
2206          png_free(png_ptr, params);\r
2207          png_chunk_benign_error(png_ptr, "invalid data");\r
2208          return;\r
2209       }\r
2210    }\r
2211 \r
2212    png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,\r
2213       (png_charp)units, params);\r
2214 \r
2215    png_free(png_ptr, params);\r
2216 }\r
2217 #endif\r
2218 \r
2219 #ifdef PNG_READ_sCAL_SUPPORTED\r
2220 /* Read the sCAL chunk */\r
2221 void /* PRIVATE */\r
2222 png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2223 {\r
2224    png_bytep buffer;\r
2225    png_size_t i;\r
2226    int state;\r
2227 \r
2228    png_debug(1, "in png_handle_sCAL");\r
2229 \r
2230    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2231       png_chunk_error(png_ptr, "missing IHDR");\r
2232 \r
2233    else if (png_ptr->mode & PNG_HAVE_IDAT)\r
2234    {\r
2235       png_crc_finish(png_ptr, length);\r
2236       png_chunk_benign_error(png_ptr, "out of place");\r
2237       return;\r
2238    }\r
2239 \r
2240    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))\r
2241    {\r
2242       png_crc_finish(png_ptr, length);\r
2243       png_chunk_benign_error(png_ptr, "duplicate");\r
2244       return;\r
2245    }\r
2246 \r
2247    /* Need unit type, width, \0, height: minimum 4 bytes */\r
2248    else if (length < 4)\r
2249    {\r
2250       png_crc_finish(png_ptr, length);\r
2251       png_chunk_benign_error(png_ptr, "invalid");\r
2252       return;\r
2253    }\r
2254 \r
2255    png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",\r
2256       length + 1);\r
2257 \r
2258    buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);\r
2259 \r
2260    if (buffer == NULL)\r
2261    {\r
2262       png_chunk_benign_error(png_ptr, "out of memory");\r
2263       png_crc_finish(png_ptr, length);\r
2264       return;\r
2265    }\r
2266 \r
2267    png_crc_read(png_ptr, buffer, length);\r
2268    buffer[length] = 0; /* Null terminate the last string */\r
2269 \r
2270    if (png_crc_finish(png_ptr, 0))\r
2271       return;\r
2272 \r
2273    /* Validate the unit. */\r
2274    if (buffer[0] != 1 && buffer[0] != 2)\r
2275    {\r
2276       png_chunk_benign_error(png_ptr, "invalid unit");\r
2277       return;\r
2278    }\r
2279 \r
2280    /* Validate the ASCII numbers, need two ASCII numbers separated by\r
2281     * a '\0' and they need to fit exactly in the chunk data.\r
2282     */\r
2283    i = 1;\r
2284    state = 0;\r
2285 \r
2286    if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) ||\r
2287        i >= length || buffer[i++] != 0)\r
2288       png_chunk_benign_error(png_ptr, "bad width format");\r
2289 \r
2290    else if (!PNG_FP_IS_POSITIVE(state))\r
2291       png_chunk_benign_error(png_ptr, "non-positive width");\r
2292 \r
2293    else\r
2294    {\r
2295       png_size_t heighti = i;\r
2296 \r
2297       state = 0;\r
2298       if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) ||\r
2299          i != length)\r
2300          png_chunk_benign_error(png_ptr, "bad height format");\r
2301 \r
2302       else if (!PNG_FP_IS_POSITIVE(state))\r
2303          png_chunk_benign_error(png_ptr, "non-positive height");\r
2304 \r
2305       else\r
2306          /* This is the (only) success case. */\r
2307          png_set_sCAL_s(png_ptr, info_ptr, buffer[0],\r
2308             (png_charp)buffer+1, (png_charp)buffer+heighti);\r
2309    }\r
2310 }\r
2311 #endif\r
2312 \r
2313 #ifdef PNG_READ_tIME_SUPPORTED\r
2314 void /* PRIVATE */\r
2315 png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2316 {\r
2317    png_byte buf[7];\r
2318    png_time mod_time;\r
2319 \r
2320    png_debug(1, "in png_handle_tIME");\r
2321 \r
2322    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2323       png_chunk_error(png_ptr, "missing IHDR");\r
2324 \r
2325    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))\r
2326    {\r
2327       png_crc_finish(png_ptr, length);\r
2328       png_chunk_benign_error(png_ptr, "duplicate");\r
2329       return;\r
2330    }\r
2331 \r
2332    if (png_ptr->mode & PNG_HAVE_IDAT)\r
2333       png_ptr->mode |= PNG_AFTER_IDAT;\r
2334 \r
2335    if (length != 7)\r
2336    {\r
2337       png_crc_finish(png_ptr, length);\r
2338       png_chunk_benign_error(png_ptr, "invalid");\r
2339       return;\r
2340    }\r
2341 \r
2342    png_crc_read(png_ptr, buf, 7);\r
2343 \r
2344    if (png_crc_finish(png_ptr, 0))\r
2345       return;\r
2346 \r
2347    mod_time.second = buf[6];\r
2348    mod_time.minute = buf[5];\r
2349    mod_time.hour = buf[4];\r
2350    mod_time.day = buf[3];\r
2351    mod_time.month = buf[2];\r
2352    mod_time.year = png_get_uint_16(buf);\r
2353 \r
2354    png_set_tIME(png_ptr, info_ptr, &mod_time);\r
2355 }\r
2356 #endif\r
2357 \r
2358 #ifdef PNG_READ_tEXt_SUPPORTED\r
2359 /* Note: this does not properly handle chunks that are > 64K under DOS */\r
2360 void /* PRIVATE */\r
2361 png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2362 {\r
2363    png_text  text_info;\r
2364    png_bytep buffer;\r
2365    png_charp key;\r
2366    png_charp text;\r
2367    png_uint_32 skip = 0;\r
2368 \r
2369    png_debug(1, "in png_handle_tEXt");\r
2370 \r
2371 #ifdef PNG_USER_LIMITS_SUPPORTED\r
2372    if (png_ptr->user_chunk_cache_max != 0)\r
2373    {\r
2374       if (png_ptr->user_chunk_cache_max == 1)\r
2375       {\r
2376          png_crc_finish(png_ptr, length);\r
2377          return;\r
2378       }\r
2379 \r
2380       if (--png_ptr->user_chunk_cache_max == 1)\r
2381       {\r
2382          png_crc_finish(png_ptr, length);\r
2383          png_chunk_benign_error(png_ptr, "no space in chunk cache");\r
2384          return;\r
2385       }\r
2386    }\r
2387 #endif\r
2388 \r
2389    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2390       png_chunk_error(png_ptr, "missing IHDR");\r
2391 \r
2392    if (png_ptr->mode & PNG_HAVE_IDAT)\r
2393       png_ptr->mode |= PNG_AFTER_IDAT;\r
2394 \r
2395 #ifdef PNG_MAX_MALLOC_64K\r
2396    if (length > 65535U)\r
2397    {\r
2398       png_crc_finish(png_ptr, length);\r
2399       png_chunk_benign_error(png_ptr, "too large to fit in memory");\r
2400       return;\r
2401    }\r
2402 #endif\r
2403 \r
2404    buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);\r
2405 \r
2406    if (buffer == NULL)\r
2407    {\r
2408      png_chunk_benign_error(png_ptr, "out of memory");\r
2409      return;\r
2410    }\r
2411 \r
2412    png_crc_read(png_ptr, buffer, length);\r
2413 \r
2414    if (png_crc_finish(png_ptr, skip))\r
2415       return;\r
2416 \r
2417    key = (png_charp)buffer;\r
2418    key[length] = 0;\r
2419 \r
2420    for (text = key; *text; text++)\r
2421       /* Empty loop to find end of key */ ;\r
2422 \r
2423    if (text != key + length)\r
2424       text++;\r
2425 \r
2426    text_info.compression = PNG_TEXT_COMPRESSION_NONE;\r
2427    text_info.key = key;\r
2428    text_info.lang = NULL;\r
2429    text_info.lang_key = NULL;\r
2430    text_info.itxt_length = 0;\r
2431    text_info.text = text;\r
2432    text_info.text_length = strlen(text);\r
2433 \r
2434    if (png_set_text_2(png_ptr, info_ptr, &text_info, 1))\r
2435       png_warning(png_ptr, "Insufficient memory to process text chunk");\r
2436 }\r
2437 #endif\r
2438 \r
2439 #ifdef PNG_READ_zTXt_SUPPORTED\r
2440 /* Note: this does not correctly handle chunks that are > 64K under DOS */\r
2441 void /* PRIVATE */\r
2442 png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2443 {\r
2444    png_const_charp errmsg = NULL;\r
2445    png_bytep       buffer;\r
2446    png_uint_32     keyword_length;\r
2447 \r
2448    png_debug(1, "in png_handle_zTXt");\r
2449 \r
2450 #ifdef PNG_USER_LIMITS_SUPPORTED\r
2451    if (png_ptr->user_chunk_cache_max != 0)\r
2452    {\r
2453       if (png_ptr->user_chunk_cache_max == 1)\r
2454       {\r
2455          png_crc_finish(png_ptr, length);\r
2456          return;\r
2457       }\r
2458 \r
2459       if (--png_ptr->user_chunk_cache_max == 1)\r
2460       {\r
2461          png_crc_finish(png_ptr, length);\r
2462          png_chunk_benign_error(png_ptr, "no space in chunk cache");\r
2463          return;\r
2464       }\r
2465    }\r
2466 #endif\r
2467 \r
2468    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2469       png_chunk_error(png_ptr, "missing IHDR");\r
2470 \r
2471    if (png_ptr->mode & PNG_HAVE_IDAT)\r
2472       png_ptr->mode |= PNG_AFTER_IDAT;\r
2473 \r
2474    buffer = png_read_buffer(png_ptr, length, 2/*silent*/);\r
2475 \r
2476    if (buffer == NULL)\r
2477    {\r
2478       png_crc_finish(png_ptr, length);\r
2479       png_chunk_benign_error(png_ptr, "out of memory");\r
2480       return;\r
2481    }\r
2482 \r
2483    png_crc_read(png_ptr, buffer, length);\r
2484 \r
2485    if (png_crc_finish(png_ptr, 0))\r
2486       return;\r
2487 \r
2488    /* TODO: also check that the keyword contents match the spec! */\r
2489    for (keyword_length = 0;\r
2490       keyword_length < length && buffer[keyword_length] != 0;\r
2491       ++keyword_length)\r
2492       /* Empty loop to find end of name */ ;\r
2493 \r
2494    if (keyword_length > 79 || keyword_length < 1)\r
2495       errmsg = "bad keyword";\r
2496 \r
2497    /* zTXt must have some LZ data after the keyword, although it may expand to\r
2498     * zero bytes; we need a '\0' at the end of the keyword, the compression type\r
2499     * then the LZ data:\r
2500     */\r
2501    else if (keyword_length + 3 > length)\r
2502       errmsg = "truncated";\r
2503 \r
2504    else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE)\r
2505       errmsg = "unknown compression type";\r
2506 \r
2507    else\r
2508    {\r
2509       png_alloc_size_t uncompressed_length = PNG_SIZE_MAX;\r
2510 \r
2511       /* TODO: at present png_decompress_chunk imposes a single application\r
2512        * level memory limit, this should be split to different values for iCCP\r
2513        * and text chunks.\r
2514        */\r
2515       if (png_decompress_chunk(png_ptr, length, keyword_length+2,\r
2516          &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)\r
2517       {\r
2518          png_text text;\r
2519 \r
2520          /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except\r
2521           * for the extra compression type byte and the fact that it isn't\r
2522           * necessarily '\0' terminated.\r
2523           */\r
2524          buffer = png_ptr->read_buffer;\r
2525          buffer[uncompressed_length+(keyword_length+2)] = 0;\r
2526 \r
2527          text.compression = PNG_TEXT_COMPRESSION_zTXt;\r
2528          text.key = (png_charp)buffer;\r
2529          text.text = (png_charp)(buffer + keyword_length+2);\r
2530          text.text_length = uncompressed_length;\r
2531          text.itxt_length = 0;\r
2532          text.lang = NULL;\r
2533          text.lang_key = NULL;\r
2534 \r
2535          if (png_set_text_2(png_ptr, info_ptr, &text, 1))\r
2536             errmsg = "insufficient memory";\r
2537       }\r
2538 \r
2539       else\r
2540          errmsg = png_ptr->zstream.msg;\r
2541    }\r
2542 \r
2543    if (errmsg != NULL)\r
2544       png_chunk_benign_error(png_ptr, errmsg);\r
2545 }\r
2546 #endif\r
2547 \r
2548 #ifdef PNG_READ_iTXt_SUPPORTED\r
2549 /* Note: this does not correctly handle chunks that are > 64K under DOS */\r
2550 void /* PRIVATE */\r
2551 png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)\r
2552 {\r
2553    png_const_charp errmsg = NULL;\r
2554    png_bytep buffer;\r
2555    png_uint_32 prefix_length;\r
2556 \r
2557    png_debug(1, "in png_handle_iTXt");\r
2558 \r
2559 #ifdef PNG_USER_LIMITS_SUPPORTED\r
2560    if (png_ptr->user_chunk_cache_max != 0)\r
2561    {\r
2562       if (png_ptr->user_chunk_cache_max == 1)\r
2563       {\r
2564          png_crc_finish(png_ptr, length);\r
2565          return;\r
2566       }\r
2567 \r
2568       if (--png_ptr->user_chunk_cache_max == 1)\r
2569       {\r
2570          png_crc_finish(png_ptr, length);\r
2571          png_chunk_benign_error(png_ptr, "no space in chunk cache");\r
2572          return;\r
2573       }\r
2574    }\r
2575 #endif\r
2576 \r
2577    if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
2578       png_chunk_error(png_ptr, "missing IHDR");\r
2579 \r
2580    if (png_ptr->mode & PNG_HAVE_IDAT)\r
2581       png_ptr->mode |= PNG_AFTER_IDAT;\r
2582 \r
2583    buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);\r
2584 \r
2585    if (buffer == NULL)\r
2586    {\r
2587       png_crc_finish(png_ptr, length);\r
2588       png_chunk_benign_error(png_ptr, "out of memory");\r
2589       return;\r
2590    }\r
2591 \r
2592    png_crc_read(png_ptr, buffer, length);\r
2593 \r
2594    if (png_crc_finish(png_ptr, 0))\r
2595       return;\r
2596 \r
2597    /* First the keyword. */\r
2598    for (prefix_length=0;\r
2599       prefix_length < length && buffer[prefix_length] != 0;\r
2600       ++prefix_length)\r
2601       /* Empty loop */ ;\r
2602 \r
2603    /* Perform a basic check on the keyword length here. */\r
2604    if (prefix_length > 79 || prefix_length < 1)\r
2605       errmsg = "bad keyword";\r
2606 \r
2607    /* Expect keyword, compression flag, compression type, language, translated\r
2608     * keyword (both may be empty but are 0 terminated) then the text, which may\r
2609     * be empty.\r
2610     */\r
2611    else if (prefix_length + 5 > length)\r
2612       errmsg = "truncated";\r
2613 \r
2614    else if (buffer[prefix_length+1] == 0 ||\r
2615       (buffer[prefix_length+1] == 1 &&\r
2616       buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE))\r
2617    {\r
2618       int compressed = buffer[prefix_length+1] != 0;\r
2619       png_uint_32 language_offset, translated_keyword_offset;\r
2620       png_alloc_size_t uncompressed_length = 0;\r
2621 \r
2622       /* Now the language tag */\r
2623       prefix_length += 3;\r
2624       language_offset = prefix_length;\r
2625 \r
2626       for (; prefix_length < length && buffer[prefix_length] != 0;\r
2627          ++prefix_length)\r
2628          /* Empty loop */ ;\r
2629 \r
2630       /* WARNING: the length may be invalid here, this is checked below. */\r
2631       translated_keyword_offset = ++prefix_length;\r
2632 \r
2633       for (; prefix_length < length && buffer[prefix_length] != 0;\r
2634          ++prefix_length)\r
2635          /* Empty loop */ ;\r
2636 \r
2637       /* prefix_length should now be at the trailing '\0' of the translated\r
2638        * keyword, but it may already be over the end.  None of this arithmetic\r
2639        * can overflow because chunks are at most 2^31 bytes long, but on 16-bit\r
2640        * systems the available allocaton may overflow.\r
2641        */\r
2642       ++prefix_length;\r
2643 \r
2644       if (!compressed && prefix_length <= length)\r
2645          uncompressed_length = length - prefix_length;\r
2646 \r
2647       else if (compressed && prefix_length < length)\r
2648       {\r
2649          uncompressed_length = PNG_SIZE_MAX;\r
2650 \r
2651          /* TODO: at present png_decompress_chunk imposes a single application\r
2652           * level memory limit, this should be split to different values for\r
2653           * iCCP and text chunks.\r
2654           */\r
2655          if (png_decompress_chunk(png_ptr, length, prefix_length,\r
2656             &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)\r
2657             buffer = png_ptr->read_buffer;\r
2658 \r
2659          else\r
2660             errmsg = png_ptr->zstream.msg;\r
2661       }\r
2662 \r
2663       else\r
2664          errmsg = "truncated";\r
2665 \r
2666       if (errmsg == NULL)\r
2667       {\r
2668          png_text text;\r
2669 \r
2670          buffer[uncompressed_length+prefix_length] = 0;\r
2671 \r
2672          if (compressed)\r
2673             text.compression = PNG_ITXT_COMPRESSION_NONE;\r
2674 \r
2675          else\r
2676             text.compression = PNG_ITXT_COMPRESSION_zTXt;\r
2677 \r
2678          text.key = (png_charp)buffer;\r
2679          text.lang = (png_charp)buffer + language_offset;\r
2680          text.lang_key = (png_charp)buffer + translated_keyword_offset;\r
2681          text.text = (png_charp)buffer + prefix_length;\r
2682          text.text_length = 0;\r
2683          text.itxt_length = uncompressed_length;\r
2684 \r
2685          if (png_set_text_2(png_ptr, info_ptr, &text, 1))\r
2686             errmsg = "insufficient memory";\r
2687       }\r
2688    }\r
2689 \r
2690    else\r
2691       errmsg = "bad compression info";\r
2692 \r
2693    if (errmsg != NULL)\r
2694       png_chunk_benign_error(png_ptr, errmsg);\r
2695 }\r
2696 #endif\r
2697 \r
2698 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED\r
2699 /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */\r
2700 static int\r
2701 png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)\r
2702 {\r
2703    png_alloc_size_t limit = PNG_SIZE_MAX;\r
2704 \r
2705    if (png_ptr->unknown_chunk.data != NULL)\r
2706    {\r
2707       png_free(png_ptr, png_ptr->unknown_chunk.data);\r
2708       png_ptr->unknown_chunk.data = NULL;\r
2709    }\r
2710 \r
2711 #  ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED\r
2712       if (png_ptr->user_chunk_malloc_max > 0 &&\r
2713          png_ptr->user_chunk_malloc_max < limit)\r
2714          limit = png_ptr->user_chunk_malloc_max;\r
2715 \r
2716 #  elif PNG_USER_CHUNK_MALLOC_MAX > 0\r
2717       if (PNG_USER_CHUNK_MALLOC_MAX < limit)\r
2718          limit = PNG_USER_CHUNK_MALLOC_MAX;\r
2719 #  endif\r
2720 \r
2721    if (length <= limit)\r
2722    {\r
2723       PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);\r
2724       /* The following is safe because of the PNG_SIZE_MAX init above */\r
2725       png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/;\r
2726       /* 'mode' is a flag array, only the bottom four bits matter here */\r
2727       png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/;\r
2728 \r
2729       if (length == 0)\r
2730          png_ptr->unknown_chunk.data = NULL;\r
2731 \r
2732       else\r
2733       {\r
2734          /* Do a 'warn' here - it is handled below. */\r
2735          png_ptr->unknown_chunk.data = png_voidcast(png_bytep,\r
2736             png_malloc_warn(png_ptr, length));\r
2737       }\r
2738    }\r
2739 \r
2740    if (png_ptr->unknown_chunk.data == NULL && length > 0)\r
2741    {\r
2742       /* This is benign because we clean up correctly */\r
2743       png_crc_finish(png_ptr, length);\r
2744       png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits");\r
2745       return 0;\r
2746    }\r
2747 \r
2748    else\r
2749    {\r
2750       if (length > 0)\r
2751          png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);\r
2752       png_crc_finish(png_ptr, 0);\r
2753       return 1;\r
2754    }\r
2755 }\r
2756 #endif /* PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */\r
2757 \r
2758 /* Handle an unknown, or known but disabled, chunk */\r
2759 void /* PRIVATE */\r
2760 png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,\r
2761    png_uint_32 length, int keep)\r
2762 {\r
2763    int handled = 0; /* the chunk was handled */\r
2764 \r
2765    png_debug(1, "in png_handle_unknown");\r
2766 \r
2767 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED\r
2768    /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing\r
2769     * the bug which meant that setting a non-default behavior for a specific\r
2770     * chunk would be ignored (the default was always used unless a user\r
2771     * callback was installed).\r
2772     *\r
2773     * 'keep' is the value from the png_chunk_unknown_handling, the setting for\r
2774     * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it\r
2775     * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here.\r
2776     * This is just an optimization to avoid multiple calls to the lookup\r
2777     * function.\r
2778     */\r
2779 #  ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED\r
2780 #     ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED\r
2781          keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);\r
2782 #     endif\r
2783 #  endif\r
2784 \r
2785    /* One of the following methods will read the chunk or skip it (at least one\r
2786     * of these is always defined because this is the only way to switch on\r
2787     * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)\r
2788     */\r
2789 #  ifdef PNG_READ_USER_CHUNKS_SUPPORTED\r
2790       /* The user callback takes precedence over the chunk keep value, but the\r
2791        * keep value is still required to validate a save of a critical chunk.\r
2792        */\r
2793       if (png_ptr->read_user_chunk_fn != NULL)\r
2794       {\r
2795          if (png_cache_unknown_chunk(png_ptr, length))\r
2796          {\r
2797             /* Callback to user unknown chunk handler */\r
2798             int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,\r
2799                &png_ptr->unknown_chunk);\r
2800 \r
2801             /* ret is:\r
2802              * negative: An error occured, png_chunk_error will be called.\r
2803              *     zero: The chunk was not handled, the chunk will be discarded\r
2804              *           unless png_set_keep_unknown_chunks has been used to set\r
2805              *           a 'keep' behavior for this particular chunk, in which\r
2806              *           case that will be used.  A critical chunk will cause an\r
2807              *           error at this point unless it is to be saved.\r
2808              * positive: The chunk was handled, libpng will ignore/discard it.\r
2809              */\r
2810             if (ret < 0)\r
2811                png_chunk_error(png_ptr, "error in user chunk");\r
2812 \r
2813             else if (ret == 0)\r
2814             {\r
2815                /* If the keep value is 'default' or 'never' override it, but\r
2816                 * still error out on critical chunks unless the keep value is\r
2817                 * 'always'  While this is weird it is the behavior in 1.4.12.\r
2818                 * A possible improvement would be to obey the value set for the\r
2819                 * chunk, but this would be an API change that would probably\r
2820                 * damage some applications.\r
2821                 *\r
2822                 * The png_app_warning below catches the case that matters, where\r
2823                 * the application has not set specific save or ignore for this\r
2824                 * chunk or global save or ignore.\r
2825                 */\r
2826                if (keep < PNG_HANDLE_CHUNK_IF_SAFE)\r
2827                {\r
2828 #                 ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED\r
2829                      if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)\r
2830                      {\r
2831                         png_chunk_warning(png_ptr, "Saving unknown chunk:");\r
2832                         png_app_warning(png_ptr,\r
2833                            "forcing save of an unhandled chunk;"\r
2834                            " please call png_set_keep_unknown_chunks");\r
2835                            /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */\r
2836                      }\r
2837 #                 endif\r
2838                   keep = PNG_HANDLE_CHUNK_IF_SAFE;\r
2839                }\r
2840             }\r
2841 \r
2842             else /* chunk was handled */\r
2843             {\r
2844                handled = 1;\r
2845                /* Critical chunks can be safely discarded at this point. */\r
2846                keep = PNG_HANDLE_CHUNK_NEVER;\r
2847             }\r
2848          }\r
2849 \r
2850          else\r
2851             keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */\r
2852       }\r
2853 \r
2854       else\r
2855          /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */\r
2856 #  endif /* PNG_READ_USER_CHUNKS_SUPPORTED */\r
2857 \r
2858 #  ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED\r
2859       {\r
2860          /* keep is currently just the per-chunk setting, if there was no\r
2861           * setting change it to the global default now (not that this may\r
2862           * still be AS_DEFAULT) then obtain the cache of the chunk if required,\r
2863           * if not simply skip the chunk.\r
2864           */\r
2865          if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)\r
2866             keep = png_ptr->unknown_default;\r
2867 \r
2868          if (keep == PNG_HANDLE_CHUNK_ALWAYS ||\r
2869             (keep == PNG_HANDLE_CHUNK_IF_SAFE &&\r
2870              PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))\r
2871          {\r
2872             if (!png_cache_unknown_chunk(png_ptr, length))\r
2873                keep = PNG_HANDLE_CHUNK_NEVER;\r
2874          }\r
2875 \r
2876          else\r
2877             png_crc_finish(png_ptr, length);\r
2878       }\r
2879 #  else\r
2880 #     ifndef PNG_READ_USER_CHUNKS_SUPPORTED\r
2881 #        error no method to support READ_UNKNOWN_CHUNKS\r
2882 #     endif\r
2883 \r
2884       {\r
2885          /* If here there is no read callback pointer set and no support is\r
2886           * compiled in to just save the unknown chunks, so simply skip this\r
2887           * chunk.  If 'keep' is something other than AS_DEFAULT or NEVER then\r
2888           * the app has erroneously asked for unknown chunk saving when there\r
2889           * is no support.\r
2890           */\r
2891          if (keep > PNG_HANDLE_CHUNK_NEVER)\r
2892             png_app_error(png_ptr, "no unknown chunk support available");\r
2893 \r
2894          png_crc_finish(png_ptr, length);\r
2895       }\r
2896 #  endif\r
2897 \r
2898 #  ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED\r
2899       /* Now store the chunk in the chunk list if appropriate, and if the limits\r
2900        * permit it.\r
2901        */\r
2902       if (keep == PNG_HANDLE_CHUNK_ALWAYS ||\r
2903          (keep == PNG_HANDLE_CHUNK_IF_SAFE &&\r
2904           PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))\r
2905       {\r
2906 #     ifdef PNG_USER_LIMITS_SUPPORTED\r
2907          switch (png_ptr->user_chunk_cache_max)\r
2908          {\r
2909             case 2:\r
2910                png_ptr->user_chunk_cache_max = 1;\r
2911                png_chunk_benign_error(png_ptr, "no space in chunk cache");\r
2912                /* FALL THROUGH */\r
2913             case 1:\r
2914                /* NOTE: prior to 1.6.0 this case resulted in an unknown critical\r
2915                 * chunk being skipped, now there will be a hard error below.\r
2916                 */\r
2917                break;\r
2918 \r
2919             default: /* not at limit */\r
2920                --(png_ptr->user_chunk_cache_max);\r
2921                /* FALL THROUGH */\r
2922             case 0: /* no limit */\r
2923 #     endif /* PNG_USER_LIMITS_SUPPORTED */\r
2924                /* Here when the limit isn't reached or when limits are compiled\r
2925                 * out; store the chunk.\r
2926                 */\r
2927                png_set_unknown_chunks(png_ptr, info_ptr,\r
2928                   &png_ptr->unknown_chunk, 1);\r
2929                handled = 1;\r
2930 #     ifdef PNG_USER_LIMITS_SUPPORTED\r
2931                break;\r
2932          }\r
2933 #     endif\r
2934       }\r
2935 #  else /* no store support! */\r
2936       PNG_UNUSED(info_ptr)\r
2937 #     error untested code (reading unknown chunks with no store support)\r
2938 #  endif\r
2939 \r
2940    /* Regardless of the error handling below the cached data (if any) can be\r
2941     * freed now.  Notice that the data is not freed if there is a png_error, but\r
2942     * it will be freed by destroy_read_struct.\r
2943     */\r
2944    if (png_ptr->unknown_chunk.data != NULL)\r
2945       png_free(png_ptr, png_ptr->unknown_chunk.data);\r
2946    png_ptr->unknown_chunk.data = NULL;\r
2947 \r
2948 #else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */\r
2949    /* There is no support to read an unknown chunk, so just skip it. */\r
2950    png_crc_finish(png_ptr, length);\r
2951    PNG_UNUSED(info_ptr)\r
2952    PNG_UNUSED(keep)\r
2953 #endif /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */\r
2954 \r
2955    /* Check for unhandled critical chunks */\r
2956    if (!handled && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))\r
2957       png_chunk_error(png_ptr, "unhandled critical chunk");\r
2958 }\r
2959 \r
2960 /* This function is called to verify that a chunk name is valid.\r
2961  * This function can't have the "critical chunk check" incorporated\r
2962  * into it, since in the future we will need to be able to call user\r
2963  * functions to handle unknown critical chunks after we check that\r
2964  * the chunk name itself is valid.\r
2965  */\r
2966 \r
2967 /* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:\r
2968  *\r
2969  * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))\r
2970  */\r
2971 \r
2972 void /* PRIVATE */\r
2973 png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name)\r
2974 {\r
2975    int i;\r
2976 \r
2977    png_debug(1, "in png_check_chunk_name");\r
2978 \r
2979    for (i=1; i<=4; ++i)\r
2980    {\r
2981       int c = chunk_name & 0xff;\r
2982 \r
2983       if (c < 65 || c > 122 || (c > 90 && c < 97))\r
2984          png_chunk_error(png_ptr, "invalid chunk type");\r
2985 \r
2986       chunk_name >>= 8;\r
2987    }\r
2988 }\r
2989 \r
2990 /* Combines the row recently read in with the existing pixels in the row.  This\r
2991  * routine takes care of alpha and transparency if requested.  This routine also\r
2992  * handles the two methods of progressive display of interlaced images,\r
2993  * depending on the 'display' value; if 'display' is true then the whole row\r
2994  * (dp) is filled from the start by replicating the available pixels.  If\r
2995  * 'display' is false only those pixels present in the pass are filled in.\r
2996  */\r
2997 void /* PRIVATE */\r
2998 png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)\r
2999 {\r
3000    unsigned int pixel_depth = png_ptr->transformed_pixel_depth;\r
3001    png_const_bytep sp = png_ptr->row_buf + 1;\r
3002    png_uint_32 row_width = png_ptr->width;\r
3003    unsigned int pass = png_ptr->pass;\r
3004    png_bytep end_ptr = 0;\r
3005    png_byte end_byte = 0;\r
3006    unsigned int end_mask;\r
3007 \r
3008    png_debug(1, "in png_combine_row");\r
3009 \r
3010    /* Added in 1.5.6: it should not be possible to enter this routine until at\r
3011     * least one row has been read from the PNG data and transformed.\r
3012     */\r
3013    if (pixel_depth == 0)\r
3014       png_error(png_ptr, "internal row logic error");\r
3015 \r
3016    /* Added in 1.5.4: the pixel depth should match the information returned by\r
3017     * any call to png_read_update_info at this point.  Do not continue if we got\r
3018     * this wrong.\r
3019     */\r
3020    if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes !=\r
3021           PNG_ROWBYTES(pixel_depth, row_width))\r
3022       png_error(png_ptr, "internal row size calculation error");\r
3023 \r
3024    /* Don't expect this to ever happen: */\r
3025    if (row_width == 0)\r
3026       png_error(png_ptr, "internal row width error");\r
3027 \r
3028    /* Preserve the last byte in cases where only part of it will be overwritten,\r
3029     * the multiply below may overflow, we don't care because ANSI-C guarantees\r
3030     * we get the low bits.\r
3031     */\r
3032    end_mask = (pixel_depth * row_width) & 7;\r
3033    if (end_mask != 0)\r
3034    {\r
3035       /* end_ptr == NULL is a flag to say do nothing */\r
3036       end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;\r
3037       end_byte = *end_ptr;\r
3038 #     ifdef PNG_READ_PACKSWAP_SUPPORTED\r
3039          if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */\r
3040             end_mask = 0xff << end_mask;\r
3041 \r
3042          else /* big-endian byte */\r
3043 #     endif\r
3044          end_mask = 0xff >> end_mask;\r
3045       /* end_mask is now the bits to *keep* from the destination row */\r
3046    }\r
3047 \r
3048    /* For non-interlaced images this reduces to a memcpy(). A memcpy()\r
3049     * will also happen if interlacing isn't supported or if the application\r
3050     * does not call png_set_interlace_handling().  In the latter cases the\r
3051     * caller just gets a sequence of the unexpanded rows from each interlace\r
3052     * pass.\r
3053     */\r
3054 #ifdef PNG_READ_INTERLACING_SUPPORTED\r
3055    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) &&\r
3056       pass < 6 && (display == 0 ||\r
3057       /* The following copies everything for 'display' on passes 0, 2 and 4. */\r
3058       (display == 1 && (pass & 1) != 0)))\r
3059    {\r
3060       /* Narrow images may have no bits in a pass; the caller should handle\r
3061        * this, but this test is cheap:\r
3062        */\r
3063       if (row_width <= PNG_PASS_START_COL(pass))\r
3064          return;\r
3065 \r
3066       if (pixel_depth < 8)\r
3067       {\r
3068          /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit\r
3069           * into 32 bits, then a single loop over the bytes using the four byte\r
3070           * values in the 32-bit mask can be used.  For the 'display' option the\r
3071           * expanded mask may also not require any masking within a byte.  To\r
3072           * make this work the PACKSWAP option must be taken into account - it\r
3073           * simply requires the pixels to be reversed in each byte.\r