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