graphics

experiments with opengl3.2/ogles3.3 on linux and win7
git clone http://frotz.net/git/graphics.git
Log | Files | Refs

pngrutil.c (98297B)


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