source: trunk/third/libpng/pngrutil.c @ 20647

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