176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* pngrutil.c - utilities to read a PNG file
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Last changed in libpng 1.2.44 [June 26, 2010]
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 1998-2010 Glenn Randers-Pehrson
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This code is released under the libpng license.
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * For conditions of distribution and use, see the disclaimer
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and license in png.h
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This file contains routines that are only called from within
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * libpng itself during the course of reading an image.
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PNG_INTERNAL
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PNG_NO_PEDANTIC_WARNINGS
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "png.h"
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_SUPPORTED
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  define WIN32_WCE_OLD
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  ifdef WIN32_WCE_OLD
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The strtod() function is not supported on WindowsCE */
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr,
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char **endptr)
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   double result = 0;
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int len;
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   wchar_t *str, *end;
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ( NULL != str )
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      result = wcstod(str, &end);
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, str);
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return result;
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  else
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#    define png_strtod(p,a,b) strtod(a,b)
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  endif
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_uint_32 PNGAPI
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_get_uint_31(png_structp png_ptr, png_bytep buf)
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 i = png_get_uint_32(buf);
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Avoid an extra function call by inlining the result. */
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((png_uint_32)(*(buf + 1)) << 16) +
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((png_uint_32)(*(buf + 2)) << 8) +
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_32)(*(buf + 3));
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (i > PNG_UINT_31_MAX)
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_error(png_ptr, "PNG unsigned integer out of range.");
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return (i);
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_uint_32 PNGAPI
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_get_uint_32(png_bytep buf)
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((png_uint_32)(*(buf + 1)) << 16) +
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((png_uint_32)(*(buf + 2)) << 8) +
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_32)(*(buf + 3));
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return (i);
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * data is stored in the PNG file in two's complement format, and it is
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * assumed that the machine format for signed integers is the same.
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_int_32 PNGAPI
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_get_int_32(png_bytep buf)
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_int_32 i = ((png_int_32)(*buf) << 24) +
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((png_int_32)(*(buf + 1)) << 16) +
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((png_int_32)(*(buf + 2)) << 8) +
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_int_32)(*(buf + 3));
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return (i);
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_uint_16 PNGAPI
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_get_uint_16(png_bytep buf)
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_16)(*(buf + 1)));
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return (i);
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read the chunk header (length + type name).
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Put the type name into png_ptr->chunk_name, and return the length.
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_uint_32 /* PRIVATE */
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_read_chunk_header(png_structp png_ptr)
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[8];
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 length;
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Read the length and the chunk name */
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_read_data(png_ptr, buf, 8);
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   length = png_get_uint_31(png_ptr, buf);
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Put the chunk name into png_ptr->chunk_name */
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_memcpy(png_ptr->chunk_name, buf + 4, 4);
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug2(0, "Reading %s chunk, length = %lu",
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunk_name, length);
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Reset the crc and run it over the chunk name */
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_reset_crc(png_ptr);
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Check to see if chunk name is valid */
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return length;
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read data, and (optionally) run it through the CRC. */
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr == NULL)
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_read_data(png_ptr, buf, length);
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_calculate_crc(png_ptr, buf, length);
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Optionally skip data and then check the CRC.  Depending on whether we
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * are reading a ancillary or critical chunk, and how the program has set
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * things up, we may calculate the CRC on the data and print a message.
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns '1' if there was a CRC error, '0' otherwise.
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint /* PRIVATE */
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_crc_finish(png_structp png_ptr, png_uint_32 skip)
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t i;
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t istop = png_ptr->zbuf_size;
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = (png_size_t)skip; i > istop; i -= istop)
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (i)
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, png_ptr->zbuf, i);
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_error(png_ptr))
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_chunk_warning(png_ptr, "CRC error");
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_chunk_error(png_ptr, "CRC error");
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return (1);
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   return (0);
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Compare the CRC stored in the PNG file with that calculated by libpng from
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the data it has read thus far.
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint /* PRIVATE */
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_crc_error(png_structp png_ptr)
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte crc_bytes[4];
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 crc;
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int need_crc = 1;
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         need_crc = 0;
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else                                                    /* critical */
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         need_crc = 0;
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_read_data(png_ptr, crc_bytes, 4);
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (need_crc)
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      crc = png_get_uint_32(crc_bytes);
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return ((int)(crc != png_ptr->crc));
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return (0);
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    defined(PNG_READ_iCCP_SUPPORTED)
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic png_size_t
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        png_bytep output, png_size_t output_size)
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t count = 0;
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->zstream.avail_in = size;
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   while (1)
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      int ret, avail;
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Reset the output buffer each time round - we empty it
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * after every inflate call.
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->zstream.next_out = png_ptr->zbuf;
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* First copy/count any new output - but only if we didn't
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * get an error code.
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (output != 0 && output_size > count)
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int copy = output_size - count;
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (avail < copy) copy = avail;
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_memcpy(output + count, png_ptr->zbuf, copy);
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         count += avail;
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (ret == Z_OK)
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         continue;
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Termination conditions - always reset the zstream, it
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * must be left in inflateInit state.
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->zstream.avail_in = 0;
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      inflateReset(&png_ptr->zstream);
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (ret == Z_STREAM_END)
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return count; /* NOTE: may be zero. */
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Now handle the error codes - the API always returns 0
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * and the error message is dumped into the uncompressed
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * buffer if available.
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         PNG_CONST char *msg;
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->zstream.msg != 0)
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            msg = png_ptr->zstream.msg;
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            char umsg[52];
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            switch (ret)
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               case Z_BUF_ERROR:
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  msg = "Buffer error in compressed datastream in %s chunk";
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  break;
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               case Z_DATA_ERROR:
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  msg = "Data error in compressed datastream in %s chunk";
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  break;
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               default:
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  msg = "Incomplete compressed datastream in %s chunk";
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  break;
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            msg = umsg;
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            msg = "Damaged compressed datastream in chunk other than IDAT";
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, msg);
30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* 0 means an error - notice that this code simple ignores
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * zero length compressed chunks as a result.
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return 0;
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Decompress trailing data in a chunk.  The assumption is that chunkdata
31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * points at an allocated area holding the contents of a chunk with a
31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * trailing compressed part.  What we get back is an allocated area
31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * holding the original prefix part and an uncompressed version of the
31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * trailing part (the malloc area passed in is freed).
31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_decompress_chunk(png_structp png_ptr, int comp_type,
32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    png_size_t chunklength,
32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    png_size_t prefix_size, png_size_t *newlength)
32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* The caller should guarantee this */
32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (prefix_size > chunklength)
32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* The recovery is to delete the chunk. */
32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "invalid chunklength");
32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      prefix_size = 0; /* To delete everything */
33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_size_t expanded_size = png_inflate(png_ptr,
33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (png_bytep)(png_ptr->chunkdata + prefix_size),
33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                chunklength - prefix_size,
33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                0/*output*/, 0/*output size*/);
33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Now check the limits on this chunk - if the limit fails the
34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * compressed data will be removed, the prefix will remain.
34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->user_chunk_malloc_max &&
34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  ifdef PNG_USER_CHUNK_MALLOC_MAX
34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  endif
35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Exceeded size limit while expanding chunk");
35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* If the size is zero either there was an error and a message
35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * has already been output (warning) or the size really is zero
35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * and we have nothing to do - the code will exit through the
35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * error case below.
35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    defined(PNG_USER_CHUNK_MALLOC_MAX)
36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (expanded_size > 0)
36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         /* Success (maybe) - really uncompress the chunk. */
36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_size_t new_size = 0;
36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_charp text = png_malloc_warn(png_ptr,
36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        prefix_size + expanded_size + 1);
36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (text != NULL)
37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_memcpy(text, png_ptr->chunkdata, prefix_size);
37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            new_size = png_inflate(png_ptr,
37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (png_bytep)(png_ptr->chunkdata + prefix_size),
37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                chunklength - prefix_size,
37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (png_bytep)(text + prefix_size), expanded_size);
37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            text[prefix_size + expanded_size] = 0; /* just in case */
37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (new_size == expanded_size)
37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_free(png_ptr, png_ptr->chunkdata);
38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_ptr->chunkdata = text;
38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               *newlength = prefix_size + expanded_size;
38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               return; /* The success return! */
38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_warning(png_ptr, "png_inflate logic error");
38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_free(png_ptr, text);
38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          png_warning(png_ptr, "Not enough memory to decompress chunk.");
39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      char umsg[50];
39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          comp_type);
40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, umsg);
40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Unknown zTXt compression type");
40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* The recovery is to simply drop the data. */
40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Generic error return - leave the prefix, delete the compressed
41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * data, reallocate the chunkdata to remove the potentially large
41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * amount of compressed data.
41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    */
41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (text != NULL)
41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (prefix_size > 0)
41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_memcpy(text, png_ptr->chunkdata, prefix_size);
41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_free(png_ptr, png_ptr->chunkdata);
42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->chunkdata = text;
42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         /* This is an extra zero in the 'uncompressed' part. */
42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         *(png_ptr->chunkdata + prefix_size) = 0x00;
42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Ignore a malloc error here - it is safe. */
42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   *newlength = prefix_size;
42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read and check the IDHR chunk */
43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[13];
43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 width, height;
43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int bit_depth, color_type, compression_type, filter_type;
43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int interlace_type;
44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_IHDR");
44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->mode & PNG_HAVE_IHDR)
44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Out of place IHDR");
44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Check the length */
44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 13)
44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Invalid IHDR chunk");
44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->mode |= PNG_HAVE_IHDR;
45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 13);
45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_finish(png_ptr, 0);
45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   width = png_get_uint_31(png_ptr, buf);
45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   height = png_get_uint_31(png_ptr, buf + 4);
45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   bit_depth = buf[8];
45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   color_type = buf[9];
45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   compression_type = buf[10];
46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   filter_type = buf[11];
46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   interlace_type = buf[12];
46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Set internal variables */
46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->width = width;
46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->height = height;
46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->bit_depth = (png_byte)bit_depth;
46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->interlaced = (png_byte)interlace_type;
46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->color_type = (png_byte)color_type;
46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MNG_FEATURES_SUPPORTED
47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->filter_type = (png_byte)filter_type;
47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->compression_type = (png_byte)compression_type;
47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Find number of channels */
47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   switch (png_ptr->color_type)
47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_COLOR_TYPE_GRAY:
47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_COLOR_TYPE_PALETTE:
47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->channels = 1;
48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_COLOR_TYPE_RGB:
48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->channels = 3;
48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_COLOR_TYPE_GRAY_ALPHA:
48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->channels = 2;
48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_COLOR_TYPE_RGB_ALPHA:
49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->channels = 4;
49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Set up other useful info */
49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->channels);
49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "channels = %d", png_ptr->channels);
50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      color_type, interlace_type, compression_type, filter_type);
50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read and check the palette */
50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_color palette[PNG_MAX_PALETTE_LENGTH];
51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int num, i;
51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_POINTER_INDEXING_SUPPORTED
51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_colorp pal_ptr;
51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_PLTE");
51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before PLTE");
52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid PLTE after IDAT");
52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_PLTE)
52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Duplicate PLTE chunk");
53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->mode |= PNG_HAVE_PLTE;
53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr,
53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        "Ignoring PLTE chunk in grayscale PNG");
53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PNG_READ_OPT_PLTE_SUPPORTED
54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Invalid palette chunk");
55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_error(png_ptr, "Invalid palette chunk");
56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   num = (int)length / 3;
56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_POINTER_INDEXING_SUPPORTED
56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_byte buf[3];
56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, buf, 3);
57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      pal_ptr->red = buf[0];
57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      pal_ptr->green = buf[1];
57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      pal_ptr->blue = buf[2];
57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = 0; i < num; i++)
57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_byte buf[3];
57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, buf, 3);
58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Don't depend upon png_color being any order */
58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      palette[i].red = buf[0];
58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      palette[i].green = buf[1];
58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      palette[i].blue = buf[2];
58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * whatever the normal CRC configuration tells us.  However, if we
59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * have an RGB image, the PLTE can be considered ancillary, so
59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * we will act as though it is.
59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    */
59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PNG_READ_OPT_PLTE_SUPPORTED
59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, 0);
59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PNG_READ_OPT_PLTE_SUPPORTED
60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* If we don't want to use the data from an ancillary chunk,
60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         we have two options: an error abort, or a warning and we
60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         ignore the data in this chunk (which should be OK, since
60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         it's considered ancillary for a RGB or RGBA image). */
60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_chunk_error(png_ptr, "CRC error");
61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_chunk_warning(png_ptr, "CRC error");
61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            return;
61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Otherwise, we (optionally) emit a warning and use the chunk. */
61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_chunk_warning(png_ptr, "CRC error");
62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_PLTE(png_ptr, info_ptr, palette, num);
62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_tRNS_SUPPORTED
62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->num_trans > (png_uint_16)num)
63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->num_trans = (png_uint_16)num;
63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (info_ptr->num_trans > (png_uint_16)num)
63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            info_ptr->num_trans = (png_uint_16)num;
64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_IEND");
65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "No image in file");
65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 0)
66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect IEND chunk length");
66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_finish(png_ptr, length);
66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_gAMA_SUPPORTED
67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_fixed_point igamma;
67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   float file_gamma;
67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[4];
67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_gAMA");
68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before gAMA");
68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid gAMA after IDAT");
68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_PLTE)
69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Should be an error, but we can cope with it */
69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of place gAMA chunk");
69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sRGB_SUPPORTED
69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      && !(info_ptr->valid & PNG_INFO_sRGB)
69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      )
69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate gAMA chunk");
70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 4)
70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect gAMA chunk length");
70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 4);
71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   igamma = (png_fixed_point)png_get_uint_32(buf);
71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Check for zero gamma */
71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (igamma == 0)
71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr,
72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           "Ignoring gAMA chunk with gamma=0");
72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sRGB_SUPPORTED
72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr,
73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           "Ignoring incorrect gAMA value when sRGB is also present");
73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_CONSOLE_IO_SUPPORTED
73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_sRGB_SUPPORTED */
73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   file_gamma = (float)igamma / (float)100000.0;
74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  ifdef PNG_READ_GAMMA_SUPPORTED
74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->gamma = file_gamma;
74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  endif
74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_set_gAMA(png_ptr, info_ptr, file_gamma);
74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sBIT_SUPPORTED
75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t truelen;
75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[4];
75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_sBIT");
75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   buf[0] = buf[1] = buf[2] = buf[3] = 0;
76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before sBIT");
76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid sBIT after IDAT");
76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_PLTE)
77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Should be an error, but we can cope with it */
77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of place sBIT chunk");
77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate sBIT chunk");
77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      truelen = 3;
78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      truelen = (png_size_t)png_ptr->channels;
78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != truelen || length > 4)
78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect sBIT chunk length");
79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, truelen);
79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.red = buf[0];
80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.green = buf[1];
80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.blue = buf[2];
80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.alpha = buf[3];
80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.gray = buf[0];
80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.red = buf[0];
80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.green = buf[0];
81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.blue = buf[0];
81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->sig_bit.alpha = buf[1];
81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_cHRM_SUPPORTED
81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[32];
82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      int_y_green, int_x_blue, int_y_blue;
82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 uint_x, uint_y;
82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_cHRM");
83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before cHRM");
83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid cHRM after IDAT");
83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_PLTE)
84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Should be an error, but we can cope with it */
84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Missing PLTE before cHRM");
84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sRGB_SUPPORTED
84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      && !(info_ptr->valid & PNG_INFO_sRGB)
84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      )
84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate cHRM chunk");
85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 32)
85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect cHRM chunk length");
85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 32);
86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_x = png_get_uint_32(buf);
86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_y = png_get_uint_32(buf + 4);
86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_x_white = (png_fixed_point)uint_x;
86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_y_white = (png_fixed_point)uint_y;
87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_x = png_get_uint_32(buf + 8);
87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_y = png_get_uint_32(buf + 12);
87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_x_red = (png_fixed_point)uint_x;
87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_y_red = (png_fixed_point)uint_y;
87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_x = png_get_uint_32(buf + 16);
87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_y = png_get_uint_32(buf + 20);
87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_x_green = (png_fixed_point)uint_x;
87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_y_green = (png_fixed_point)uint_y;
88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_x = png_get_uint_32(buf + 24);
88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   uint_y = png_get_uint_32(buf + 28);
88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_x_blue = (png_fixed_point)uint_x;
88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int_y_blue = (png_fixed_point)uint_y;
88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
88676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   white_x = (float)int_x_white / (float)100000.0;
88876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   white_y = (float)int_y_white / (float)100000.0;
88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   red_x   = (float)int_x_red   / (float)100000.0;
89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   red_y   = (float)int_y_red   / (float)100000.0;
89176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   green_x = (float)int_x_green / (float)100000.0;
89276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   green_y = (float)int_y_green / (float)100000.0;
89376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   blue_x  = (float)int_x_blue  / (float)100000.0;
89476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   blue_y  = (float)int_y_blue  / (float)100000.0;
89576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
89676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
89776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sRGB_SUPPORTED
89876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
89976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
90076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
90176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
90276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
90376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
90476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
90576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
90676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
90776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
90876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
90976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_warning(png_ptr,
91076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              "Ignoring incorrect cHRM value when sRGB is also present");
91176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_CONSOLE_IO_SUPPORTED
91276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
91376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
91476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               white_x, white_y, red_x, red_y);
91576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
91676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               green_x, green_y, blue_x, blue_y);
91776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
91876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
91976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               (long)int_x_white, (long)int_y_white,
92076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               (long)int_x_red, (long)int_y_red);
92176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
92276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               (long)int_x_green, (long)int_y_green,
92376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               (long)int_x_blue, (long)int_y_blue);
92476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
92576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_CONSOLE_IO_SUPPORTED */
92676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
92776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
92876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
92976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_sRGB_SUPPORTED */
93076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
93176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
93276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_cHRM(png_ptr, info_ptr,
93376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
93476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
93576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
93676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_cHRM_fixed(png_ptr, info_ptr,
93776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
93876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      int_y_green, int_x_blue, int_y_blue);
93976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
94076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
94176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
94276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
94376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sRGB_SUPPORTED
94476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
94576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
94676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
94776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int intent;
94876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[1];
94976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
95076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_sRGB");
95176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
95276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
95376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before sRGB");
95476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
95576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
95676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid sRGB after IDAT");
95776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
95876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
95976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
96076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_PLTE)
96176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Should be an error, but we can cope with it */
96276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of place sRGB chunk");
96376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
96476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
96576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
96676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate sRGB chunk");
96776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
96876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
96976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
97076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
97176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 1)
97276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
97376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect sRGB chunk length");
97476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
97576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
97676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
97776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
97876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 1);
97976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
98076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
98176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
98276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   intent = buf[0];
98376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Check for bad intent */
98476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (intent >= PNG_sRGB_INTENT_LAST)
98576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
98676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Unknown sRGB intent");
98776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
98876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
98976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
99076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
99176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
99276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
99376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_fixed_point igamma;
99476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
99576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      igamma=info_ptr->int_gamma;
99676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
99776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  ifdef PNG_FLOATING_POINT_SUPPORTED
99876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
99976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  endif
100076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
100176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
100276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
100376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr,
100476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           "Ignoring incorrect gAMA value when sRGB is also present");
100576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_CONSOLE_IO_SUPPORTED
100676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  ifdef PNG_FIXED_POINT_SUPPORTED
100776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
100876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            (int)png_ptr->int_gamma);
100976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  else
101076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#    ifdef PNG_FLOATING_POINT_SUPPORTED
101176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
101276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#    endif
101376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  endif
101476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
101576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
101676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
101776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_gAMA_SUPPORTED */
101876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
101976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_cHRM_SUPPORTED
102076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
102176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
102276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
102376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
102476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
102576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
102676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
102776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
102876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
102976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
103076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
103176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_warning(png_ptr,
103276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              "Ignoring incorrect cHRM value when sRGB is also present");
103376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
103476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_FIXED_POINT_SUPPORTED */
103576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_cHRM_SUPPORTED */
103676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
103776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
103876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
103976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_sRGB_SUPPORTED */
104076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
104176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_iCCP_SUPPORTED
104276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
104376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
104476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Note: this does not properly handle chunks that are > 64K under DOS */
104576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
104676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte compression_type;
104776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_bytep pC;
104876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp profile;
104976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 skip = 0;
105076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 profile_size, profile_length;
105176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength, prefix_length, data_length;
105276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
105376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_iCCP");
105476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
105576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
105676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before iCCP");
105776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
105876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
105976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid iCCP after IDAT");
106076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
106176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
106276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
106376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_PLTE)
106476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Should be an error, but we can cope with it */
106576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of place iCCP chunk");
106676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
106776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
106876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
106976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate iCCP chunk");
107076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
107176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
107276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
107376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
107476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
107576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length > (png_uint_32)65535L)
107676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
107776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
107876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      skip = length - (png_uint_32)65535L;
107976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      length = (png_uint_32)65535L;
108076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
108176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
108276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
108376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
108476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
108576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
108676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
108776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
108876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, skip))
108976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
109076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
109176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
109276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
109376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
109476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
109576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata[slength] = 0x00;
109676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
109776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (profile = png_ptr->chunkdata; *profile; profile++)
109876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop to find end of name */ ;
109976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
110076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ++profile;
110176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
110276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* There should be at least one zero (the compression type byte)
110376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * following the separator, and we should be on it
110476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    */
110576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ( profile >= png_ptr->chunkdata + slength - 1)
110676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
110776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
110876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
110976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Malformed iCCP chunk");
111076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
111176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
111276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
111376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Compression_type should always be zero */
111476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   compression_type = *profile++;
111576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (compression_type)
111676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
111776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
111876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
111976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                                 wrote nonzero) */
112076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
112176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
112276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   prefix_length = profile - png_ptr->chunkdata;
112376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_decompress_chunk(png_ptr, compression_type,
112476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     slength, prefix_length, &data_length);
112576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
112676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   profile_length = data_length - prefix_length;
112776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
112876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ( prefix_length > data_length || profile_length < 4)
112976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
113076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
113176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
113276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
113376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
113476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
113576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
113676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
113776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
113876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   profile_size = ((*(pC    ))<<24) |
113976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  ((*(pC + 1))<<16) |
114076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  ((*(pC + 2))<< 8) |
114176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  ((*(pC + 3))    );
114276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
114376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (profile_size < profile_length)
114476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      profile_length = profile_size;
114576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
114676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (profile_size > profile_length)
114776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
114876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
114976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
115076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Ignoring truncated iCCP profile.");
115176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
115276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
115376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
115476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
115576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     compression_type, png_ptr->chunkdata + prefix_length, profile_length);
115676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
115776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
115876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
115976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_iCCP_SUPPORTED */
116076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
116176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sPLT_SUPPORTED
116276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
116376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
116476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Note: this does not properly handle chunks that are > 64K under DOS */
116576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
116676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_bytep entry_start;
116776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_sPLT_t new_palette;
116876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_POINTER_INDEXING_SUPPORTED
116976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_sPLT_entryp pp;
117076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
117176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int data_length, entry_size, i;
117276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 skip = 0;
117376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength;
117476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
117576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_sPLT");
117676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
117776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USER_LIMITS_SUPPORTED
117876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
117976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->user_chunk_cache_max != 0)
118076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
118176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->user_chunk_cache_max == 1)
118276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
118376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
118476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
118576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
118676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (--png_ptr->user_chunk_cache_max == 1)
118776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
118876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "No space in chunk cache for sPLT");
118976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
119076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
119176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
119276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
119376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
119476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
119576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
119676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before sPLT");
119776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
119876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
119976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid sPLT after IDAT");
120076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
120176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
120276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
120376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
120476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
120576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length > (png_uint_32)65535L)
120676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
120776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
120876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      skip = length - (png_uint_32)65535L;
120976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      length = (png_uint_32)65535L;
121076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
121176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
121276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
121376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
121476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
121576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
121676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
121776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
121876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, skip))
121976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
122076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
122176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
122276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
122376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
122476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
122576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata[slength] = 0x00;
122676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
122776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
122876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       entry_start++)
122976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop to find end of name */ ;
123076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ++entry_start;
123176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
123276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* A sample depth should follow the separator, and we should be on it  */
123376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
123476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
123576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
123676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
123776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "malformed sPLT chunk");
123876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
123976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
124076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
124176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   new_palette.depth = *entry_start++;
124276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   entry_size = (new_palette.depth == 8 ? 6 : 10);
124376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
124476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
124576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Integrity-check the data length */
124676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (data_length % entry_size)
124776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
124876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
124976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
125076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "sPLT chunk has bad length");
125176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
125276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
125376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
125476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   new_palette.nentries = (png_int_32) ( data_length / entry_size);
125576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((png_uint_32) new_palette.nentries >
125676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
125776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
125876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_warning(png_ptr, "sPLT chunk too long");
125976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       return;
126076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
126176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
126276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
126376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (new_palette.entries == NULL)
126476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
126576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_warning(png_ptr, "sPLT chunk requires too much memory");
126676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       return;
126776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
126876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
126976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_POINTER_INDEXING_SUPPORTED
127076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = 0; i < new_palette.nentries; i++)
127176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
127276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      pp = new_palette.entries + i;
127376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
127476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (new_palette.depth == 8)
127576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
127676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->red = *entry_start++;
127776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->green = *entry_start++;
127876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->blue = *entry_start++;
127976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->alpha = *entry_start++;
128076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
128176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
128276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
128376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
128476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->green = png_get_uint_16(entry_start); entry_start += 2;
128576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
128676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
128776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
128876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
128976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
129076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
129176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   pp = new_palette.entries;
129276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = 0; i < new_palette.nentries; i++)
129376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
129476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
129576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (new_palette.depth == 8)
129676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
129776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].red   = *entry_start++;
129876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].green = *entry_start++;
129976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].blue  = *entry_start++;
130076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].alpha = *entry_start++;
130176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
130276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
130376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
130476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
130576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
130676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
130776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
130876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
130976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
131076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
131176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
131276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
131376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Discard all chunk data except the name and stash that */
131476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   new_palette.name = png_ptr->chunkdata;
131576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
131676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
131776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
131876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
131976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
132076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, new_palette.entries);
132176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
132276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_sPLT_SUPPORTED */
132376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
132476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_tRNS_SUPPORTED
132576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
132676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
132776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
132876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
132976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
133076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_tRNS");
133176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
133276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
133376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before tRNS");
133476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
133576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
133676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid tRNS after IDAT");
133776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
133876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
133976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
134076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
134176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
134276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate tRNS chunk");
134376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
134476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
134576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
134676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
134776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
134876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
134976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_byte buf[2];
135076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
135176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (length != 2)
135276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
135376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Incorrect tRNS chunk length");
135476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
135576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
135676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
135776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
135876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, buf, 2);
135976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->num_trans = 1;
136076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->trans_values.gray = png_get_uint_16(buf);
136176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
136276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
136376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
136476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_byte buf[6];
136576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
136676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (length != 6)
136776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
136876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Incorrect tRNS chunk length");
136976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
137076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
137176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
137276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, buf, (png_size_t)length);
137376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->num_trans = 1;
137476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->trans_values.red = png_get_uint_16(buf);
137576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
137676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
137776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
137876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
137976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
138076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (!(png_ptr->mode & PNG_HAVE_PLTE))
138176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
138276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         /* Should be an error, but we can cope with it. */
138376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Missing PLTE before tRNS");
138476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
138576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (length > (png_uint_32)png_ptr->num_palette ||
138676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          length > PNG_MAX_PALETTE_LENGTH)
138776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
138876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Incorrect tRNS chunk length");
138976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
139076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
139176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
139276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (length == 0)
139376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
139476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Zero length tRNS chunk");
139576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
139676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
139776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
139876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, readbuf, (png_size_t)length);
139976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->num_trans = (png_uint_16)length;
140076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
140176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
140276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
140376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
140476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
140576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
140676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
140776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
140876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
140976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
141076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->num_trans = 0;
141176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
141276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
141376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
141476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
141576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      &(png_ptr->trans_values));
141676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
141776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
141876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
141976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_bKGD_SUPPORTED
142076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
142176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
142276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
142376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t truelen;
142476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[6];
142576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
142676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_bKGD");
142776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
142876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
142976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before bKGD");
143076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
143176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
143276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid bKGD after IDAT");
143376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
143476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
143576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
143676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
143776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            !(png_ptr->mode & PNG_HAVE_PLTE))
143876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
143976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Missing PLTE before bKGD");
144076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
144176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
144276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
144376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
144476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
144576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate bKGD chunk");
144676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
144776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
144876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
144976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
145076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
145176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      truelen = 1;
145276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
145376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      truelen = 6;
145476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
145576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      truelen = 2;
145676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
145776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != truelen)
145876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
145976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect bKGD chunk length");
146076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
146176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
146276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
146376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
146476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, truelen);
146576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
146676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
146776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
146876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* We convert the index value into RGB components so that we can allow
146976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * arbitrary RGB values for background when we have transparency, and
147076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * so it is easy to determine the RGB values of the background color
147176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * from the info_ptr struct. */
147276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
147376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
147476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.index = buf[0];
147576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (info_ptr && info_ptr->num_palette)
147676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
147776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (buf[0] >= info_ptr->num_palette)
147876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          {
147976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             png_warning(png_ptr, "Incorrect bKGD chunk index value");
148076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             return;
148176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
148276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          png_ptr->background.red =
148376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             (png_uint_16)png_ptr->palette[buf[0]].red;
148476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          png_ptr->background.green =
148576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             (png_uint_16)png_ptr->palette[buf[0]].green;
148676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          png_ptr->background.blue =
148776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             (png_uint_16)png_ptr->palette[buf[0]].blue;
148876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
148976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
149076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
149176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
149276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.red =
149376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.green =
149476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.blue =
149576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.gray = png_get_uint_16(buf);
149676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
149776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
149876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
149976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.red = png_get_uint_16(buf);
150076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.green = png_get_uint_16(buf + 2);
150176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->background.blue = png_get_uint_16(buf + 4);
150276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
150376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
150476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
150576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
150676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
150776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
150876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_hIST_SUPPORTED
150976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
151076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
151176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
151276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   unsigned int num, i;
151376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
151476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
151576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_hIST");
151676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
151776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
151876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before hIST");
151976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
152076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
152176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid hIST after IDAT");
152276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
152376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
152476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
152576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
152676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
152776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Missing PLTE before hIST");
152876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
152976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
153076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
153176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
153276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
153376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate hIST chunk");
153476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
153576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
153676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
153776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
153876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   num = length / 2 ;
153976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (num != (unsigned int) png_ptr->num_palette || num >
154076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (unsigned int) PNG_MAX_PALETTE_LENGTH)
154176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
154276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect hIST chunk length");
154376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
154476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
154576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
154676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
154776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = 0; i < num; i++)
154876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
154976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_byte buf[2];
155076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
155176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_read(png_ptr, buf, 2);
155276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      readbuf[i] = png_get_uint_16(buf);
155376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
155476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
155576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
155676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
155776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
155876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_hIST(png_ptr, info_ptr, readbuf);
155976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
156076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
156176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
156276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_pHYs_SUPPORTED
156376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
156476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
156576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
156676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[9];
156776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 res_x, res_y;
156876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int unit_type;
156976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
157076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_pHYs");
157176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
157276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
157376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before pHYs");
157476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
157576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
157676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid pHYs after IDAT");
157776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
157876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
157976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
158076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
158176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
158276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate pHYs chunk");
158376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
158476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
158576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
158676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
158776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 9)
158876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
158976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect pHYs chunk length");
159076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
159176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
159276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
159376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
159476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 9);
159576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
159676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
159776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
159876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   res_x = png_get_uint_32(buf);
159976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   res_y = png_get_uint_32(buf + 4);
160076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   unit_type = buf[8];
160176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
160276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
160376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
160476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
160576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_oFFs_SUPPORTED
160676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
160776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
160876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
160976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[9];
161076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_int_32 offset_x, offset_y;
161176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int unit_type;
161276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
161376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_oFFs");
161476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
161576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
161676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before oFFs");
161776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
161876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
161976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid oFFs after IDAT");
162076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
162176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
162276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
162376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
162476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
162576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate oFFs chunk");
162676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
162776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
162876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
162976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
163076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 9)
163176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
163276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect oFFs chunk length");
163376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
163476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
163576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
163676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
163776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 9);
163876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
163976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
164076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
164176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   offset_x = png_get_int_32(buf);
164276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   offset_y = png_get_int_32(buf + 4);
164376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   unit_type = buf[8];
164476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
164576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
164676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
164776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
164876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_pCAL_SUPPORTED
164976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read the pCAL chunk (described in the PNG Extensions document) */
165076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
165176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
165276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
165376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_int_32 X0, X1;
165476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte type, nparams;
165576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp buf, units, endptr;
165676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charpp params;
165776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength;
165876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int i;
165976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
166076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_pCAL");
166176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
166276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
166376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before pCAL");
166476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
166576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
166676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid pCAL after IDAT");
166776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
166876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
166976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
167076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
167176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
167276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate pCAL chunk");
167376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
167476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
167576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
167676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
167776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
167876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      length + 1);
167976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
168076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
168176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata == NULL)
168276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     {
168376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_warning(png_ptr, "No memory for pCAL purpose.");
168476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       return;
168576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
168676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
168776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
168876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
168976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
169076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
169176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
169276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
169376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
169476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
169576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
169676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
169776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
169876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(3, "Finding end of pCAL purpose string");
169976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (buf = png_ptr->chunkdata; *buf; buf++)
170076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop */ ;
170176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
170276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   endptr = png_ptr->chunkdata + slength;
170376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
170476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* We need to have at least 12 bytes after the purpose string
170576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      in order to get the parameter information. */
170676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (endptr <= buf + 12)
170776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
170876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid pCAL data");
170976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
171076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
171176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
171276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
171376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
171476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
171576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   X0 = png_get_int_32((png_bytep)buf+1);
171676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   X1 = png_get_int_32((png_bytep)buf+5);
171776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   type = buf[9];
171876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   nparams = buf[10];
171976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   units = buf + 11;
172076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
172176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(3, "Checking pCAL equation type and number of parameters");
172276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Check that we have the right number of parameters for known
172376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      equation types. */
172476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
172576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
172676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
172776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
172876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
172976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid pCAL parameters for equation type");
173076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
173176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
173276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
173376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
173476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (type >= PNG_EQUATION_LAST)
173576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
173676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
173776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
173876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
173976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (buf = units; *buf; buf++)
174076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop to move past the units string. */ ;
174176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
174276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(3, "Allocating pCAL parameters array");
174376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   params = (png_charpp)png_malloc_warn(png_ptr,
174476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_32)(nparams * png_sizeof(png_charp))) ;
174576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (params == NULL)
174676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     {
174776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_free(png_ptr, png_ptr->chunkdata);
174876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_ptr->chunkdata = NULL;
174976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_warning(png_ptr, "No memory for pCAL params.");
175076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       return;
175176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
175276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
175376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Get pointers to the start of each parameter string. */
175476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (i = 0; i < (int)nparams; i++)
175576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
175676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      buf++; /* Skip the null string terminator from previous parameter. */
175776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
175876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_debug1(3, "Reading pCAL parameter %d", i);
175976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
176076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         /* Empty loop to move past each parameter string */ ;
176176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
176276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Make sure we haven't run out of data yet */
176376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (buf > endptr)
176476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
176576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Invalid pCAL data");
176676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_free(png_ptr, png_ptr->chunkdata);
176776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->chunkdata = NULL;
176876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_free(png_ptr, params);
176976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
177076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
177176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
177276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
177376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
177476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      units, params);
177576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
177676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
177776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
177876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, params);
177976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
178076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
178176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
178276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_sCAL_SUPPORTED
178376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read the sCAL chunk */
178476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
178576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
178676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
178776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp ep;
178876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
178976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   double width, height;
179076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp vp;
179176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
179276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
179376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp swidth, sheight;
179476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
179576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
179676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength;
179776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
179876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_sCAL");
179976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
180076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
180176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before sCAL");
180276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (png_ptr->mode & PNG_HAVE_IDAT)
180376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
180476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid sCAL after IDAT");
180576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
180676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
180776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
180876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
180976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
181076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate sCAL chunk");
181176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
181276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
181376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
181476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
181576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
181676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      length + 1);
181776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
181876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata == NULL)
181976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
182076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of memory while processing sCAL chunk");
182176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
182276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
182376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
182476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
182576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
182676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
182776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
182876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
182976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
183076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
183176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
183276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
183376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
183476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
183576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
183676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ep = png_ptr->chunkdata + 1;        /* Skip unit byte */
183776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
183876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
183976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   width = png_strtod(png_ptr, ep, &vp);
184076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (*vp)
184176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
184276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "malformed width string in sCAL chunk");
184376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
184476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
184576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
184676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
184776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
184876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
184976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
185076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (swidth == NULL)
185176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
185276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
185376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
185476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
185576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
185676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
185776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
185876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
185976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
186076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
186176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (ep = png_ptr->chunkdata; *ep; ep++)
186276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop */ ;
186376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ep++;
186476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
186576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata + slength < ep)
186676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
186776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Truncated sCAL chunk");
186876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
186976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, swidth);
187076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
187176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
187276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
187376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
187476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
187576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
187676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
187776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   height = png_strtod(png_ptr, ep, &vp);
187876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (*vp)
187976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
188076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "malformed height string in sCAL chunk");
188176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
188276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
188376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
188476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, swidth);
188576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
188676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
188776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
188876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
188976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
189076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
189176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (sheight == NULL)
189276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
189376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
189476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
189576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
189676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
189776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, swidth);
189876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
189976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
190076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
190176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
190276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
190376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
190476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
190576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata + slength < ep
190676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
190776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      || width <= 0. || height <= 0.
190876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
190976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      )
191076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
191176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Invalid sCAL data");
191276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
191376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
191476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
191576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, swidth);
191676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, sheight);
191776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
191876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
191976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
192076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
192176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
192276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FLOATING_POINT_SUPPORTED
192376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
192476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
192576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_FIXED_POINT_SUPPORTED
192676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
192776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
192876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
192976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
193076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
193176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
193276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
193376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, swidth);
193476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, sheight);
193576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
193676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
193776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
193876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
193976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_tIME_SUPPORTED
194076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
194176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
194276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
194376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_byte buf[7];
194476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_time mod_time;
194576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
194676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_tIME");
194776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
194876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
194976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Out of place tIME chunk");
195076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
195176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
195276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Duplicate tIME chunk");
195376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
195476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
195576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
195676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
195776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->mode & PNG_HAVE_IDAT)
195876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->mode |= PNG_AFTER_IDAT;
195976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
196076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length != 7)
196176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
196276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Incorrect tIME chunk length");
196376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_crc_finish(png_ptr, length);
196476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
196576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
196676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
196776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, buf, 7);
196876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
196976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
197076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
197176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   mod_time.second = buf[6];
197276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   mod_time.minute = buf[5];
197376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   mod_time.hour = buf[4];
197476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   mod_time.day = buf[3];
197576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   mod_time.month = buf[2];
197676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   mod_time.year = png_get_uint_16(buf);
197776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
197876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_set_tIME(png_ptr, info_ptr, &mod_time);
197976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
198076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
198176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
198276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_tEXt_SUPPORTED
198376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Note: this does not properly handle chunks that are > 64K under DOS */
198476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
198576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
198676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
198776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_textp text_ptr;
198876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp key;
198976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp text;
199076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 skip = 0;
199176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength;
199276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int ret;
199376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
199476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_tEXt");
199576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
199676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USER_LIMITS_SUPPORTED
199776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->user_chunk_cache_max != 0)
199876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
199976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->user_chunk_cache_max == 1)
200076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
200176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
200276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
200376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
200476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (--png_ptr->user_chunk_cache_max == 1)
200576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
200676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "No space in chunk cache for tEXt");
200776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
200876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
200976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
201076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
201176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
201276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
201376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
201476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before tEXt");
201576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
201676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->mode & PNG_HAVE_IDAT)
201776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->mode |= PNG_AFTER_IDAT;
201876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
201976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
202076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length > (png_uint_32)65535L)
202176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
202276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
202376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      skip = length - (png_uint_32)65535L;
202476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      length = (png_uint_32)65535L;
202576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
202676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
202776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
202876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
202976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
203076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
203176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata == NULL)
203276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
203376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "No memory to process text chunk.");
203476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
203576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
203676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
203776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
203876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
203976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, skip))
204076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
204176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
204276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
204376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
204476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
204576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
204676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   key = png_ptr->chunkdata;
204776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
204876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   key[slength] = 0x00;
204976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
205076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (text = key; *text; text++)
205176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop to find end of key */ ;
205276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
205376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (text != key + slength)
205476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      text++;
205576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
205676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr = (png_textp)png_malloc_warn(png_ptr,
205776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_32)png_sizeof(png_text));
205876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (text_ptr == NULL)
205976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
206076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "Not enough memory to process text chunk.");
206176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_free(png_ptr, png_ptr->chunkdata);
206276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->chunkdata = NULL;
206376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
206476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
206576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
206676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->key = key;
206776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_iTXt_SUPPORTED
206876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->lang = NULL;
206976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->lang_key = NULL;
207076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->itxt_length = 0;
207176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
207276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->text = text;
207376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->text_length = png_strlen(text);
207476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
207576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
207676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
207776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
207876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
207976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, text_ptr);
208076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (ret)
208176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "Insufficient memory to process text chunk.");
208276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
208376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
208476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
208576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_zTXt_SUPPORTED
208676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Note: this does not correctly handle chunks that are > 64K under DOS */
208776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
208876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
208976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
209076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_textp text_ptr;
209176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp text;
209276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int comp_type;
209376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int ret;
209476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength, prefix_len, data_len;
209576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
209676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_zTXt");
209776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
209876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USER_LIMITS_SUPPORTED
209976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->user_chunk_cache_max != 0)
210076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
210176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->user_chunk_cache_max == 1)
210276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
210376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
210476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
210576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
210676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (--png_ptr->user_chunk_cache_max == 1)
210776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
210876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "No space in chunk cache for zTXt");
210976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
211076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
211176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
211276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
211376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
211476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
211576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
211676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before zTXt");
211776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
211876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->mode & PNG_HAVE_IDAT)
211976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->mode |= PNG_AFTER_IDAT;
212076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
212176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
212276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* We will no doubt have problems with chunks even half this size, but
212376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      there is no hard and fast rule to tell us where to stop. */
212476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length > (png_uint_32)65535L)
212576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
212676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "zTXt chunk too large to fit in memory");
212776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_crc_finish(png_ptr, length);
212876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
212976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
213076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
213176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
213276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
213376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
213476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata == NULL)
213576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
213676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "Out of memory processing zTXt chunk.");
213776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
213876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
213976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
214076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
214176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
214276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
214376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
214476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
214576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
214676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
214776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
214876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata[slength] = 0x00;
214976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
215076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (text = png_ptr->chunkdata; *text; text++)
215176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop */ ;
215276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
215376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* zTXt must have some text after the chunkdataword */
215476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (text >= png_ptr->chunkdata + slength - 2)
215576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
215676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Truncated zTXt chunk");
215776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
215876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
215976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
216076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
216176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
216276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
216376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       comp_type = *(++text);
216476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
216576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       {
216676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          png_warning(png_ptr, "Unknown compression type in zTXt chunk");
216776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          comp_type = PNG_TEXT_COMPRESSION_zTXt;
216876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       }
216976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       text++;        /* Skip the compression_method byte */
217076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
217176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   prefix_len = text - png_ptr->chunkdata;
217276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
217376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_decompress_chunk(png_ptr, comp_type,
217476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     (png_size_t)length, prefix_len, &data_len);
217576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
217676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr = (png_textp)png_malloc_warn(png_ptr,
217776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_32)png_sizeof(png_text));
217876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (text_ptr == NULL)
217976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
218076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
218176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_free(png_ptr, png_ptr->chunkdata);
218276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->chunkdata = NULL;
218376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
218476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
218576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->compression = comp_type;
218676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->key = png_ptr->chunkdata;
218776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_iTXt_SUPPORTED
218876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->lang = NULL;
218976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->lang_key = NULL;
219076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->itxt_length = 0;
219176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
219276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->text = png_ptr->chunkdata + prefix_len;
219376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->text_length = data_len;
219476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
219576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
219676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
219776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, text_ptr);
219876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
219976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
220076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (ret)
220176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
220276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
220376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
220476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
220576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_iTXt_SUPPORTED
220676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Note: this does not correctly handle chunks that are > 64K under DOS */
220776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
220876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
220976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
221076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_textp text_ptr;
221176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_charp key, lang, text, lang_key;
221276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int comp_flag;
221376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int comp_type = 0;
221476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int ret;
221576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t slength, prefix_len, data_len;
221676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
221776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_iTXt");
221876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
221976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USER_LIMITS_SUPPORTED
222076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->user_chunk_cache_max != 0)
222176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
222276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->user_chunk_cache_max == 1)
222376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
222476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
222576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
222676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
222776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (--png_ptr->user_chunk_cache_max == 1)
222876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
222976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "No space in chunk cache for iTXt");
223076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
223176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
223276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
223376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
223476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
223576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
223676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->mode & PNG_HAVE_IHDR))
223776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Missing IHDR before iTXt");
223876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
223976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->mode & PNG_HAVE_IDAT)
224076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->mode |= PNG_AFTER_IDAT;
224176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
224276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
224376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* We will no doubt have problems with chunks even half this size, but
224476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      there is no hard and fast rule to tell us where to stop. */
224576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (length > (png_uint_32)65535L)
224676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
224776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "iTXt chunk too large to fit in memory");
224876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_crc_finish(png_ptr, length);
224976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
225076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
225176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
225276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
225376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
225476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
225576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->chunkdata == NULL)
225676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
225776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "No memory to process iTXt chunk.");
225876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
225976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
226076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   slength = (png_size_t)length;
226176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
226276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_crc_finish(png_ptr, 0))
226376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
226476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
226576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
226676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
226776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
226876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
226976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata[slength] = 0x00;
227076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
227176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (lang = png_ptr->chunkdata; *lang; lang++)
227276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop */ ;
227376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   lang++;        /* Skip NUL separator */
227476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
227576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* iTXt must have a language tag (possibly empty), two compression bytes,
227676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * translated keyword (possibly empty), and possibly some text after the
227776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * keyword
227876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    */
227976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
228076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (lang >= png_ptr->chunkdata + slength - 3)
228176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
228276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Truncated iTXt chunk");
228376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
228476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
228576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
228676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
228776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
228876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
228976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       comp_flag = *lang++;
229076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       comp_type = *lang++;
229176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
229276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
229376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (lang_key = lang; *lang_key; lang_key++)
229476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop */ ;
229576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   lang_key++;        /* Skip NUL separator */
229676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
229776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (lang_key >= png_ptr->chunkdata + slength)
229876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
229976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Truncated iTXt chunk");
230076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
230176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
230276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
230376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
230476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
230576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   for (text = lang_key; *text; text++)
230676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Empty loop */ ;
230776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text++;        /* Skip NUL separator */
230876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (text >= png_ptr->chunkdata + slength)
230976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
231076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Malformed iTXt chunk");
231176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->chunkdata);
231276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->chunkdata = NULL;
231376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
231476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
231576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
231676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   prefix_len = text - png_ptr->chunkdata;
231776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
231876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   key=png_ptr->chunkdata;
231976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (comp_flag)
232076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_decompress_chunk(png_ptr, comp_type,
232176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         (size_t)length, prefix_len, &data_len);
232276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
232376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       data_len = png_strlen(png_ptr->chunkdata + prefix_len);
232476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr = (png_textp)png_malloc_warn(png_ptr,
232576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (png_uint_32)png_sizeof(png_text));
232676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (text_ptr == NULL)
232776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
232876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
232976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_free(png_ptr, png_ptr->chunkdata);
233076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->chunkdata = NULL;
233176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     return;
233276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
233376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->compression = (int)comp_flag + 1;
233476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
233576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->lang = png_ptr->chunkdata + (lang - key);
233676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->itxt_length = data_len;
233776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->text_length = 0;
233876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->key = png_ptr->chunkdata;
233976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   text_ptr->text = png_ptr->chunkdata + prefix_len;
234076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
234176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
234276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
234376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, text_ptr);
234476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_free(png_ptr, png_ptr->chunkdata);
234576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->chunkdata = NULL;
234676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (ret)
234776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
234876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
234976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
235076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
235176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* This function is called when we haven't found a handler for a
235276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   chunk.  If there isn't a problem with the chunk itself (ie bad
235376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   chunk name, CRC, or a critical chunk), the chunk is silently ignored
235476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
235576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   case it will be saved away to be written out later. */
235676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
235776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
235876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
235976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 skip = 0;
236076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
236176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_handle_unknown");
236276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
236376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USER_LIMITS_SUPPORTED
236476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->user_chunk_cache_max != 0)
236576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
236676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->user_chunk_cache_max == 1)
236776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
236876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
236976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
237076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
237176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (--png_ptr->user_chunk_cache_max == 1)
237276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
237376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "No space in chunk cache for unknown chunk");
237476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_finish(png_ptr, length);
237576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
237676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
237776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
237876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
237976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
238076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->mode & PNG_HAVE_IDAT)
238176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
238276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USE_LOCAL_ARRAYS
238376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PNG_CONST PNG_IDAT;
238476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
238576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* Not an IDAT */
238676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->mode |= PNG_AFTER_IDAT;
238776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
238876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
238976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->chunk_name[0] & 0x20))
239076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
239176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
239276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
239376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           PNG_HANDLE_CHUNK_ALWAYS
239476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
239576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           && png_ptr->read_user_chunk_fn == NULL
239676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
239776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        )
239876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
239976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          png_chunk_error(png_ptr, "unknown critical chunk");
240076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
240176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
240276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
240376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
240476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
240576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       || (png_ptr->read_user_chunk_fn != NULL)
240676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
240776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        )
240876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
240976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
241076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       if (length > (png_uint_32)65535L)
241176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       {
241276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           png_warning(png_ptr, "unknown chunk too large to fit in memory");
241376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           skip = length - (png_uint_32)65535L;
241476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           length = (png_uint_32)65535L;
241576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       }
241676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
241776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_memcpy((png_charp)png_ptr->unknown_chunk.name,
241876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  (png_charp)png_ptr->chunk_name,
241976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  png_sizeof(png_ptr->unknown_chunk.name));
242076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
242176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           = '\0';
242276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_ptr->unknown_chunk.size = (png_size_t)length;
242376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       if (length == 0)
242476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->unknown_chunk.data = NULL;
242576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       else
242676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       {
242776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
242876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
242976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       }
243076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
243176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       if (png_ptr->read_user_chunk_fn != NULL)
243276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       {
243376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          /* Callback to user unknown chunk handler */
243476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          int ret;
243576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ret = (*(png_ptr->read_user_chunk_fn))
243676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            (png_ptr, &png_ptr->unknown_chunk);
243776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (ret < 0)
243876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             png_chunk_error(png_ptr, "error in user chunk");
243976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (ret == 0)
244076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          {
244176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             if (!(png_ptr->chunk_name[0] & 0x20))
244276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
244376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
244476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     PNG_HANDLE_CHUNK_ALWAYS)
244576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
244676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                   png_chunk_error(png_ptr, "unknown critical chunk");
244776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             png_set_unknown_chunks(png_ptr, info_ptr,
244876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               &png_ptr->unknown_chunk, 1);
244976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
245076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       }
245176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       else
245276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
245376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
245476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_free(png_ptr, png_ptr->unknown_chunk.data);
245576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       png_ptr->unknown_chunk.data = NULL;
245676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
245776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
245876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
245976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      skip = length;
246076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
246176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_crc_finish(png_ptr, skip);
246276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
246376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
246476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
246576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
246676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
246776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
246876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* This function is called to verify that a chunk name is valid.
246976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   This function can't have the "critical chunk check" incorporated
247076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   into it, since in the future we will need to be able to call user
247176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   functions to handle unknown critical chunks after we check that
247276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   the chunk name itself is valid. */
247376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
247476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
247576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
247676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
247776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
247876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
247976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_check_chunk_name");
248076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
248176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
248276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
248376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_chunk_error(png_ptr, "invalid chunk type");
248476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
248576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
248676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
248776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Combines the row recently read in with the existing pixels in the
248876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   row.  This routine takes care of alpha and transparency if requested.
248976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   This routine also handles the two methods of progressive display
249076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   of interlaced images, depending on the mask value.
249176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   The mask value describes which pixels are to be combined with
249276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   the row.  The pattern always repeats every 8 pixels, so just 8
249376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   bits are needed.  A one indicates the pixel is to be combined,
249476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   a zero indicates the pixel is to be skipped.  This is in addition
249576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   to any alpha or transparency value associated with the pixel.  If
249676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   you want all pixels to be combined, pass 0xff (255) in mask.  */
249776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
249876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
249976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_combine_row(png_structp png_ptr, png_bytep row, int mask)
250076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
250176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_combine_row");
250276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (mask == 0xff)
250376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
250476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_memcpy(row, png_ptr->row_buf + 1,
250576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
250676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
250776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
250876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
250976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      switch (png_ptr->row_info.pixel_depth)
251076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
251176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         case 1:
251276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
251376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = png_ptr->row_buf + 1;
251476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row;
251576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int s_inc, s_start, s_end;
251676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int m = 0x80;
251776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int shift;
251876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
251976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 row_width = png_ptr->width;
252076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
252176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACKSWAP_SUPPORTED
252276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (png_ptr->transformations & PNG_PACKSWAP)
252376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
252476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_start = 0;
252576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_end = 7;
252676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_inc = 1;
252776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
252876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
252976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
253076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
253176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_start = 7;
253276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_end = 0;
253376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_inc = -1;
253476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
253576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
253676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            shift = s_start;
253776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
253876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_width; i++)
253976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
254076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m & mask)
254176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
254276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  int value;
254376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
254476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  value = (*sp >> shift) & 0x01;
254576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
254676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp |= (png_byte)(value << shift);
254776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
254876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
254976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (shift == s_end)
255076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
255176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  shift = s_start;
255276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sp++;
255376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  dp++;
255476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
255576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
255676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  shift += s_inc;
255776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
255876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m == 1)
255976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m = 0x80;
256076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
256176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m >>= 1;
256276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
256376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
256476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
256576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         case 2:
256676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
256776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = png_ptr->row_buf + 1;
256876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row;
256976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int s_start, s_end, s_inc;
257076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int m = 0x80;
257176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int shift;
257276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
257376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 row_width = png_ptr->width;
257476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int value;
257576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
257676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACKSWAP_SUPPORTED
257776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (png_ptr->transformations & PNG_PACKSWAP)
257876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
257976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 0;
258076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 6;
258176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = 2;
258276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
258376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
258476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
258576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
258676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 6;
258776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 0;
258876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = -2;
258976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
259076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
259176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            shift = s_start;
259276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
259376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_width; i++)
259476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
259576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m & mask)
259676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
259776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  value = (*sp >> shift) & 0x03;
259876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
259976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp |= (png_byte)(value << shift);
260076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
260176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
260276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (shift == s_end)
260376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
260476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  shift = s_start;
260576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sp++;
260676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  dp++;
260776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
260876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
260976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  shift += s_inc;
261076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m == 1)
261176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m = 0x80;
261276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
261376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m >>= 1;
261476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
261576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
261676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
261776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         case 4:
261876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
261976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = png_ptr->row_buf + 1;
262076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row;
262176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int s_start, s_end, s_inc;
262276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int m = 0x80;
262376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int shift;
262476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
262576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 row_width = png_ptr->width;
262676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int value;
262776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
262876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACKSWAP_SUPPORTED
262976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (png_ptr->transformations & PNG_PACKSWAP)
263076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
263176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 0;
263276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 4;
263376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = 4;
263476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
263576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
263676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
263776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
263876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 4;
263976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 0;
264076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = -4;
264176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
264276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            shift = s_start;
264376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
264476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_width; i++)
264576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
264676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m & mask)
264776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
264876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  value = (*sp >> shift) & 0xf;
264976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
265076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp |= (png_byte)(value << shift);
265176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
265276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
265376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (shift == s_end)
265476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
265576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  shift = s_start;
265676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sp++;
265776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  dp++;
265876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
265976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
266076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  shift += s_inc;
266176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m == 1)
266276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m = 0x80;
266376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
266476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m >>= 1;
266576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
266676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
266776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
266876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         default:
266976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
267076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = png_ptr->row_buf + 1;
267176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row;
267276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
267376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
267476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 row_width = png_ptr->width;
267576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_byte m = 0x80;
267676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
267776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
267876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_width; i++)
267976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
268076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m & mask)
268176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
268276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  png_memcpy(dp, sp, pixel_bytes);
268376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
268476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
268576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               sp += pixel_bytes;
268676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               dp += pixel_bytes;
268776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
268876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (m == 1)
268976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m = 0x80;
269076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
269176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  m >>= 1;
269276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
269376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
269476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
269576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
269676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
269776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
269876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
269976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_INTERLACING_SUPPORTED
270076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* OLD pre-1.0.9 interface:
270176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
270276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 transformations)
270376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
270476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
270576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_do_read_interlace(png_structp png_ptr)
270676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
270776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_row_infop row_info = &(png_ptr->row_info);
270876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_bytep row = png_ptr->row_buf + 1;
270976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int pass = png_ptr->pass;
271076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_uint_32 transformations = png_ptr->transformations;
271176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
271276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Offset to next interlace block */
271376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
271476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
271576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_do_read_interlace");
271676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (row != NULL && row_info != NULL)
271776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
271876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_uint_32 final_width;
271976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
272076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      final_width = row_info->width * png_pass_inc[pass];
272176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
272276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      switch (row_info->pixel_depth)
272376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
272476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         case 1:
272576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
272676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
272776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
272876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int sshift, dshift;
272976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int s_start, s_end, s_inc;
273076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int jstop = png_pass_inc[pass];
273176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_byte v;
273276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
273376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int j;
273476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
273576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACKSWAP_SUPPORTED
273676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (transformations & PNG_PACKSWAP)
273776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
273876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                sshift = (int)((row_info->width + 7) & 0x07);
273976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                dshift = (int)((final_width + 7) & 0x07);
274076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_start = 7;
274176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_end = 0;
274276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_inc = -1;
274376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
274476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
274576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
274676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
274776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                sshift = 7 - (int)((row_info->width + 7) & 0x07);
274876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                dshift = 7 - (int)((final_width + 7) & 0x07);
274976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_start = 0;
275076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_end = 7;
275176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                s_inc = 1;
275276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
275376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
275476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_info->width; i++)
275576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
275676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               v = (png_byte)((*sp >> sshift) & 0x01);
275776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               for (j = 0; j < jstop; j++)
275876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
275976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
276076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp |= (png_byte)(v << dshift);
276176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  if (dshift == s_end)
276276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  {
276376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dshift = s_start;
276476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dp--;
276576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  }
276676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  else
276776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dshift += s_inc;
276876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
276976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (sshift == s_end)
277076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
277176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sshift = s_start;
277276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sp--;
277376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
277476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
277576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sshift += s_inc;
277676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
277776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
277876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
277976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         case 2:
278076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
278176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
278276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
278376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int sshift, dshift;
278476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int s_start, s_end, s_inc;
278576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int jstop = png_pass_inc[pass];
278676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
278776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
278876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACKSWAP_SUPPORTED
278976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (transformations & PNG_PACKSWAP)
279076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
279176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
279276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               dshift = (int)(((final_width + 3) & 0x03) << 1);
279376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 6;
279476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 0;
279576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = -2;
279676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
279776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
279876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
279976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
280076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
280176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
280276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 0;
280376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 6;
280476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = 2;
280576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
280676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
280776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_info->width; i++)
280876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
280976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_byte v;
281076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               int j;
281176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
281276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               v = (png_byte)((*sp >> sshift) & 0x03);
281376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               for (j = 0; j < jstop; j++)
281476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
281576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
281676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp |= (png_byte)(v << dshift);
281776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  if (dshift == s_end)
281876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  {
281976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dshift = s_start;
282076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dp--;
282176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  }
282276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  else
282376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dshift += s_inc;
282476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
282576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (sshift == s_end)
282676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
282776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sshift = s_start;
282876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sp--;
282976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
283076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
283176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sshift += s_inc;
283276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
283376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
283476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
283576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         case 4:
283676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
283776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
283876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
283976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int sshift, dshift;
284076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int s_start, s_end, s_inc;
284176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
284276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int jstop = png_pass_inc[pass];
284376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
284476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACKSWAP_SUPPORTED
284576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (transformations & PNG_PACKSWAP)
284676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
284776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
284876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               dshift = (int)(((final_width + 1) & 0x01) << 2);
284976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 4;
285076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 0;
285176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = -4;
285276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
285376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
285476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
285576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
285676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
285776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
285876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_start = 0;
285976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_end = 4;
286076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               s_inc = 4;
286176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
286276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
286376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_info->width; i++)
286476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
286576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
286676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               int j;
286776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
286876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               for (j = 0; j < jstop; j++)
286976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
287076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
287176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  *dp |= (png_byte)(v << dshift);
287276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  if (dshift == s_end)
287376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  {
287476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dshift = s_start;
287576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dp--;
287676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  }
287776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  else
287876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     dshift += s_inc;
287976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
288076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (sshift == s_end)
288176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
288276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sshift = s_start;
288376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sp--;
288476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
288576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
288676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  sshift += s_inc;
288776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
288876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
288976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
289076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         default:
289176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
289276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
289376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep sp = row + (png_size_t)(row_info->width - 1)
289476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                * pixel_bytes;
289576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
289676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
289776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int jstop = png_pass_inc[pass];
289876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_uint_32 i;
289976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
290076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            for (i = 0; i < row_info->width; i++)
290176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
290276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_byte v[8];
290376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               int j;
290476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
290576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_memcpy(v, sp, pixel_bytes);
290676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               for (j = 0; j < jstop; j++)
290776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               {
290876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  png_memcpy(dp, v, pixel_bytes);
290976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  dp -= pixel_bytes;
291076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               }
291176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               sp -= pixel_bytes;
291276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
291376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
291476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
291576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
291676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      row_info->width = final_width;
291776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
291876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
291976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PNG_READ_PACKSWAP_SUPPORTED
292076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   transformations = transformations; /* Silence compiler warning */
292176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
292276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
292376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_INTERLACING_SUPPORTED */
292476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
292576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
292676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
292776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_bytep prev_row, int filter)
292876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
292976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_read_filter_row");
293076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
293176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   switch (filter)
293276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
293376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_FILTER_VALUE_NONE:
293476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
293576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_FILTER_VALUE_SUB:
293676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
293776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 i;
293876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 istop = row_info->rowbytes;
293976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
294076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep rp = row + bpp;
294176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep lp = row;
294276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
294376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         for (i = bpp; i < istop; i++)
294476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
294576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
294676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            rp++;
294776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
294876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
294976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
295076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_FILTER_VALUE_UP:
295176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
295276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 i;
295376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 istop = row_info->rowbytes;
295476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep rp = row;
295576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep pp = prev_row;
295676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
295776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         for (i = 0; i < istop; i++)
295876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
295976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
296076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            rp++;
296176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
296276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
296376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
296476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_FILTER_VALUE_AVG:
296576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
296676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 i;
296776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep rp = row;
296876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep pp = prev_row;
296976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep lp = row;
297076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
297176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 istop = row_info->rowbytes - bpp;
297276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
297376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         for (i = 0; i < bpp; i++)
297476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
297576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            *rp = (png_byte)(((int)(*rp) +
297676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               ((int)(*pp++) / 2 )) & 0xff);
297776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            rp++;
297876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
297976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
298076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         for (i = 0; i < istop; i++)
298176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
298276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            *rp = (png_byte)(((int)(*rp) +
298376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               (int)(*pp++ + *lp++) / 2 ) & 0xff);
298476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            rp++;
298576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
298676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
298776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
298876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case PNG_FILTER_VALUE_PAETH:
298976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
299076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 i;
299176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep rp = row;
299276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep pp = prev_row;
299376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep lp = row;
299476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_bytep cp = prev_row;
299576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
299676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_uint_32 istop=row_info->rowbytes - bpp;
299776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
299876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         for (i = 0; i < bpp; i++)
299976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
300076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
300176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            rp++;
300276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
300376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
300476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         for (i = 0; i < istop; i++)   /* Use leftover rp,pp */
300576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
300676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int a, b, c, pa, pb, pc, p;
300776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
300876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            a = *lp++;
300976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            b = *pp++;
301076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            c = *cp++;
301176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
301276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            p = b - c;
301376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pc = a - c;
301476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
301576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USE_ABS
301676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pa = abs(p);
301776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pb = abs(pc);
301876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pc = abs(p + pc);
301976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
302076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pa = p < 0 ? -p : p;
302176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pb = pc < 0 ? -pc : pc;
302276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            pc = (p + pc) < 0 ? -(p + pc) : p + pc;
302376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
302476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
302576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            /*
302676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (pa <= pb && pa <= pc)
302776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  p = a;
302876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else if (pb <= pc)
302976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  p = b;
303076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               else
303176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  p = c;
303276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             */
303376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
303476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
303576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
303676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            *rp = (png_byte)(((int)(*rp) + p) & 0xff);
303776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            rp++;
303876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
303976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
304076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
304176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      default:
304276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_warning(png_ptr, "Ignoring bad adaptive filter type");
304376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         *row = 0;
304476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         break;
304576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
304676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
304776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
304876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
304976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
305076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_read_finish_row(png_structp png_ptr)
305176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
305276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_INTERLACING_SUPPORTED
305376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
305476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
305576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Start of interlace block */
305676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
305776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
305876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Offset to next interlace block */
305976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
306076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
306176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Start of interlace block in the y direction */
306276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
306376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
306476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Offset to next interlace block in the y direction */
306576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
306676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_INTERLACING_SUPPORTED */
306776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
306876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_read_finish_row");
306976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->row_number++;
307076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->row_number < png_ptr->num_rows)
307176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return;
307276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
307376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_INTERLACING_SUPPORTED
307476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->interlaced)
307576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
307676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->row_number = 0;
307776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_memset_check(png_ptr, png_ptr->prev_row, 0,
307876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->rowbytes + 1);
307976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      do
308076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
308176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->pass++;
308276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->pass >= 7)
308376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
308476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->iwidth = (png_ptr->width +
308576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_pass_inc[png_ptr->pass] - 1 -
308676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_pass_start[png_ptr->pass]) /
308776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_pass_inc[png_ptr->pass];
308876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
308976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (!(png_ptr->transformations & PNG_INTERLACE))
309076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
309176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->num_rows = (png_ptr->height +
309276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_pass_yinc[png_ptr->pass] - 1 -
309376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_pass_ystart[png_ptr->pass]) /
309476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_pass_yinc[png_ptr->pass];
309576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (!(png_ptr->num_rows))
309676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               continue;
309776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
309876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
309976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
310076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } while (png_ptr->iwidth == 0);
310176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
310276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->pass < 7)
310376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         return;
310476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
310576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_INTERLACING_SUPPORTED */
310676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
310776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
310876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
310976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_USE_LOCAL_ARRAYS
311076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PNG_CONST PNG_IDAT;
311176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
311276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      char extra;
311376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      int ret;
311476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
311576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->zstream.next_out = (Byte *)&extra;
311676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->zstream.avail_out = (uInt)1;
311776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      for (;;)
311876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
311976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (!(png_ptr->zstream.avail_in))
312076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
312176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            while (!png_ptr->idat_size)
312276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            {
312376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_byte chunk_length[4];
312476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
312576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_crc_finish(png_ptr, 0);
312676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
312776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_read_data(png_ptr, chunk_length, 4);
312876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
312976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_reset_crc(png_ptr);
313076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_crc_read(png_ptr, png_ptr->chunk_name, 4);
313176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
313276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                  png_error(png_ptr, "Not enough image data");
313376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
313476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
313576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
313676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->zstream.next_in = png_ptr->zbuf;
313776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (png_ptr->zbuf_size > png_ptr->idat_size)
313876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
313976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
314076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->idat_size -= png_ptr->zstream.avail_in;
314176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
314276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
314376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (ret == Z_STREAM_END)
314476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
314576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
314676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_ptr->idat_size)
314776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               png_warning(png_ptr, "Extra compressed data.");
314876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->mode |= PNG_AFTER_IDAT;
314976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
315076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
315176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
315276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (ret != Z_OK)
315376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
315476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                      "Decompression Error");
315576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
315676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (!(png_ptr->zstream.avail_out))
315776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
315876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_warning(png_ptr, "Extra compressed data.");
315976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->mode |= PNG_AFTER_IDAT;
316076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
316176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
316276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
316376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
316476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
316576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->zstream.avail_out = 0;
316676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
316776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
316876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->idat_size || png_ptr->zstream.avail_in)
316976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_warning(png_ptr, "Extra compression data.");
317076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
317176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   inflateReset(&png_ptr->zstream);
317276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
317376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->mode |= PNG_AFTER_IDAT;
317476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
317576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
317676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
317776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid /* PRIVATE */
317876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpng_read_start_row(png_structp png_ptr)
317976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
318076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_INTERLACING_SUPPORTED
318176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
318276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
318376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Start of interlace block */
318476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
318576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
318676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Offset to next interlace block */
318776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
318876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
318976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Start of interlace block in the y direction */
319076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
319176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
319276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Offset to next interlace block in the y direction */
319376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
319476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
319576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
319676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   int max_pixel_depth;
319776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_size_t row_bytes;
319876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
319976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug(1, "in png_read_start_row");
320076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->zstream.avail_in = 0;
320176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_init_read_transformations(png_ptr);
320276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_INTERLACING_SUPPORTED
320376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->interlaced)
320476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
320576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (!(png_ptr->transformations & PNG_INTERLACE))
320676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
320776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            png_pass_ystart[0]) / png_pass_yinc[0];
320876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
320976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->num_rows = png_ptr->height;
321076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
321176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->iwidth = (png_ptr->width +
321276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_pass_inc[png_ptr->pass] - 1 -
321376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_pass_start[png_ptr->pass]) /
321476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_pass_inc[png_ptr->pass];
321576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
321676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   else
321776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_INTERLACING_SUPPORTED */
321876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
321976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->num_rows = png_ptr->height;
322076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->iwidth = png_ptr->width;
322176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
322276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   max_pixel_depth = png_ptr->pixel_depth;
322376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
322476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_PACK_SUPPORTED
322576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
322676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      max_pixel_depth = 8;
322776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
322876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
322976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_EXPAND_SUPPORTED
323076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->transformations & PNG_EXPAND)
323176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
323276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
323376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
323476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->num_trans)
323576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 32;
323676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
323776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 24;
323876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
323976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
324076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
324176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (max_pixel_depth < 8)
324276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 8;
324376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->num_trans)
324476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth *= 2;
324576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
324676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
324776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
324876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (png_ptr->num_trans)
324976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         {
325076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth *= 4;
325176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth /= 3;
325276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         }
325376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
325476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
325576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
325676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
325776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_FILLER_SUPPORTED
325876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->transformations & (PNG_FILLER))
325976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
326076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
326176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         max_pixel_depth = 32;
326276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
326376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
326476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (max_pixel_depth <= 8)
326576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 16;
326676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
326776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 32;
326876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
326976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
327076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
327176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (max_pixel_depth <= 32)
327276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 32;
327376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
327476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 64;
327576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
327676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
327776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
327876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
327976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
328076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
328176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
328276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (
328376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_EXPAND_SUPPORTED
328476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
328576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
328676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_READ_FILLER_SUPPORTED
328776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        (png_ptr->transformations & (PNG_FILLER)) ||
328876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
328976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
329076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
329176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (max_pixel_depth <= 16)
329276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 32;
329376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
329476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 64;
329576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
329676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else
329776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      {
329876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         if (max_pixel_depth <= 8)
329976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           {
330076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
330176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               max_pixel_depth = 32;
330276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman             else
330376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               max_pixel_depth = 24;
330476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           }
330576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
330676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 64;
330776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         else
330876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            max_pixel_depth = 48;
330976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
331076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
331176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
331276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
331376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
331476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmandefined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
331576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (png_ptr->transformations & PNG_USER_TRANSFORM)
331676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     {
331776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       int user_pixel_depth = png_ptr->user_transform_depth*
331876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         png_ptr->user_transform_channels;
331976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       if (user_pixel_depth > max_pixel_depth)
332076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         max_pixel_depth=user_pixel_depth;
332176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
332276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
332376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
332476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Align the width on the next larger 8 pixels.  Mainly used
332576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * for interlacing
332676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    */
332776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
332876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   /* Calculate the maximum bytes needed, adding a byte and a pixel
332976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    * for safety's sake
333076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    */
333176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
333276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      1 + ((max_pixel_depth + 7) >> 3);
333376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
333476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (row_bytes > (png_uint_32)65536L)
333576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "This image requires a row greater than 64KB");
333676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
333776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
333876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
333976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
334076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_free(png_ptr, png_ptr->big_row_buf);
334176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     if (png_ptr->interlaced)
334276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
334376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            row_bytes + 64);
334476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     else
334576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
334676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            row_bytes + 64);
334776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->old_big_row_buf_size = row_bytes + 64;
334876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
334976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     /* Use 32 bytes of padding before and after row_buf. */
335076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->row_buf = png_ptr->big_row_buf + 32;
335176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     png_ptr->old_big_row_buf_size = row_bytes + 64;
335276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
335376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
335476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef PNG_MAX_MALLOC_64K
335576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
335676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "This image requires a row greater than 64KB");
335776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
335876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
335976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_error(png_ptr, "Row has too many bytes to allocate in memory.");
336076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
336176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   if (row_bytes + 1 > png_ptr->old_prev_row_size)
336276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
336376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_free(png_ptr, png_ptr->prev_row);
336476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
336576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        row_bytes + 1));
336676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
336776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      png_ptr->old_prev_row_size = row_bytes + 1;
336876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
336976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
337076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->rowbytes = row_bytes;
337176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
337276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "width = %lu,", png_ptr->width);
337376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "height = %lu,", png_ptr->height);
337476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
337576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
337676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
337776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_debug1(3, "irowbytes = %lu",
337876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
337976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
338076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   png_ptr->flags |= PNG_FLAG_ROW_INIT;
338176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
338276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PNG_READ_SUPPORTED */
3383