PageRenderTime 104ms CodeModel.GetById 18ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 1ms

/src/compiler/android/jni/ftk/pngrutil.c

http://ftk.googlecode.com/
C | 2274 lines | 1849 code | 285 blank | 140 comment | 404 complexity | 6dd551fbad69fa49ae32c4118455856f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1
   2/* pngrutil.c - utilities to read a PNG file
   3 *
   4 * Last changed in libpng 1.2.44 [June 26, 2010]
   5 * Copyright (c) 1998-2010 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
  53png_uint_32 PNGAPI
  54png_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. */
  71png_uint_32 PNGAPI
  72png_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 */
  86png_int_32 PNGAPI
  87png_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. */
  98png_uint_16 PNGAPI
  99png_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 */
 111png_uint_32 /* PRIVATE */
 112png_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. */
 138void /* PRIVATE */
 139png_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#ifdef PNG_INDEX_SUPPORTED
 148/* Optionally skip data and then check the CRC.  Depending on whether we
 149 * are reading a ancillary or critical chunk, and how the program has set
 150 * things up, we may calculate the CRC on the data and print a message.
 151 * Returns '1' if there was a CRC error, '0' otherwise.
 152 */
 153int /* PRIVATE */
 154png_opt_crc_finish(png_structp png_ptr, png_uint_32 skip, int check_crc)
 155{
 156   png_size_t i;
 157   png_size_t istop = png_ptr->zbuf_size;
 158
 159   for (i = (png_size_t)skip; i > istop; i -= istop)
 160   {
 161      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
 162   }
 163   if (i)
 164   {
 165      png_crc_read(png_ptr, png_ptr->zbuf, i);
 166   }
 167
 168   if (png_crc_error(png_ptr))
 169   {
 170      if (!check_crc) {
 171         png_chunk_warning(png_ptr, "CRC error");
 172         return (1);
 173      }
 174      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
 175          !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
 176          (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
 177          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
 178      {
 179         png_chunk_warning(png_ptr, "CRC error");
 180      }
 181      else
 182      {
 183         png_chunk_error(png_ptr, "CRC error");
 184      }
 185      return (1);
 186   }
 187
 188   return (0);
 189}
 190#endif
 191
 192/* Optionally skip data and then check the CRC.  Depending on whether we
 193 * are reading a ancillary or critical chunk, and how the program has set
 194 * things up, we may calculate the CRC on the data and print a message.
 195 * Returns '1' if there was a CRC error, '0' otherwise.
 196 */
 197int /* PRIVATE */
 198png_crc_finish(png_structp png_ptr, png_uint_32 skip)
 199{
 200   return png_opt_crc_finish(png_ptr, skip, 1);
 201}
 202
 203/* Compare the CRC stored in the PNG file with that calculated by libpng from
 204 * the data it has read thus far.
 205 */
 206int /* PRIVATE */
 207png_crc_error(png_structp png_ptr)
 208{
 209   png_byte crc_bytes[4];
 210   png_uint_32 crc;
 211   int need_crc = 1;
 212
 213   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
 214   {
 215      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
 216          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
 217         need_crc = 0;
 218   }
 219   else                                                    /* critical */
 220   {
 221      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
 222         need_crc = 0;
 223   }
 224
 225   png_read_data(png_ptr, crc_bytes, 4);
 226
 227   if (need_crc)
 228   {
 229      crc = png_get_uint_32(crc_bytes);
 230      return ((int)(crc != png_ptr->crc));
 231   }
 232   else
 233      return (0);
 234}
 235
 236#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
 237    defined(PNG_READ_iCCP_SUPPORTED)
 238static png_size_t
 239png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
 240        png_bytep output, png_size_t output_size)
 241{
 242   png_size_t count = 0;
 243
 244   png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
 245   png_ptr->zstream.avail_in = size;
 246
 247   while (1)
 248   {
 249      int ret, avail;
 250
 251      /* Reset the output buffer each time round - we empty it
 252       * after every inflate call.
 253       */
 254      png_ptr->zstream.next_out = png_ptr->zbuf;
 255      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
 256
 257      ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
 258      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
 259
 260      /* First copy/count any new output - but only if we didn't
 261       * get an error code.
 262       */
 263      if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
 264      {
 265         if (output != 0 && output_size > count)
 266         {
 267            int copy = output_size - count;
 268            if (avail < copy) copy = avail;
 269            png_memcpy(output + count, png_ptr->zbuf, copy);
 270         }
 271         count += avail;
 272      }
 273
 274      if (ret == Z_OK)
 275         continue;
 276
 277      /* Termination conditions - always reset the zstream, it
 278       * must be left in inflateInit state.
 279       */
 280      png_ptr->zstream.avail_in = 0;
 281      inflateReset(&png_ptr->zstream);
 282
 283      if (ret == Z_STREAM_END)
 284         return count; /* NOTE: may be zero. */
 285
 286      /* Now handle the error codes - the API always returns 0
 287       * and the error message is dumped into the uncompressed
 288       * buffer if available.
 289       */
 290      {
 291         PNG_CONST char *msg;
 292         if (png_ptr->zstream.msg != 0)
 293            msg = png_ptr->zstream.msg;
 294         else
 295         {
 296#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
 297            char umsg[52];
 298
 299            switch (ret)
 300            {
 301               case Z_BUF_ERROR:
 302                  msg = "Buffer error in compressed datastream in %s chunk";
 303                  break;
 304               case Z_DATA_ERROR:
 305                  msg = "Data error in compressed datastream in %s chunk";
 306                  break;
 307               default:
 308                  msg = "Incomplete compressed datastream in %s chunk";
 309                  break;
 310            }
 311
 312            png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
 313            msg = umsg;
 314#else
 315            msg = "Damaged compressed datastream in chunk other than IDAT";
 316#endif
 317         }
 318
 319         png_warning(png_ptr, msg);
 320      }
 321
 322      /* 0 means an error - notice that this code simple ignores
 323       * zero length compressed chunks as a result.
 324       */
 325      return 0;
 326   }
 327}
 328
 329/*
 330 * Decompress trailing data in a chunk.  The assumption is that chunkdata
 331 * points at an allocated area holding the contents of a chunk with a
 332 * trailing compressed part.  What we get back is an allocated area
 333 * holding the original prefix part and an uncompressed version of the
 334 * trailing part (the malloc area passed in is freed).
 335 */
 336void /* PRIVATE */
 337png_decompress_chunk(png_structp png_ptr, int comp_type,
 338    png_size_t chunklength,
 339    png_size_t prefix_size, png_size_t *newlength)
 340{
 341   /* The caller should guarantee this */
 342   if (prefix_size > chunklength)
 343   {
 344      /* The recovery is to delete the chunk. */
 345      png_warning(png_ptr, "invalid chunklength");
 346      prefix_size = 0; /* To delete everything */
 347   }
 348
 349   else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
 350   {
 351      png_size_t expanded_size = png_inflate(png_ptr,
 352                (png_bytep)(png_ptr->chunkdata + prefix_size),
 353                chunklength - prefix_size,
 354                0/*output*/, 0/*output size*/);
 355
 356      /* Now check the limits on this chunk - if the limit fails the
 357       * compressed data will be removed, the prefix will remain.
 358       */
 359#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
 360      if (png_ptr->user_chunk_malloc_max &&
 361          (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
 362#else
 363#  ifdef PNG_USER_CHUNK_MALLOC_MAX
 364      if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
 365          prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
 366#  endif
 367#endif
 368         png_warning(png_ptr, "Exceeded size limit while expanding chunk");
 369
 370      /* If the size is zero either there was an error and a message
 371       * has already been output (warning) or the size really is zero
 372       * and we have nothing to do - the code will exit through the
 373       * error case below.
 374       */
 375#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
 376    defined(PNG_USER_CHUNK_MALLOC_MAX)
 377      else
 378#endif
 379      if (expanded_size > 0)
 380      {
 381         /* Success (maybe) - really uncompress the chunk. */
 382         png_size_t new_size = 0;
 383         png_charp text = png_malloc_warn(png_ptr,
 384                        prefix_size + expanded_size + 1);
 385
 386         if (text != NULL)
 387         {
 388            png_memcpy(text, png_ptr->chunkdata, prefix_size);
 389            new_size = png_inflate(png_ptr,
 390                (png_bytep)(png_ptr->chunkdata + prefix_size),
 391                chunklength - prefix_size,
 392                (png_bytep)(text + prefix_size), expanded_size);
 393            text[prefix_size + expanded_size] = 0; /* just in case */
 394
 395            if (new_size == expanded_size)
 396            {
 397               png_free(png_ptr, png_ptr->chunkdata);
 398               png_ptr->chunkdata = text;
 399               *newlength = prefix_size + expanded_size;
 400               return; /* The success return! */
 401            }
 402
 403            png_warning(png_ptr, "png_inflate logic error");
 404            png_free(png_ptr, text);
 405         }
 406         else
 407          png_warning(png_ptr, "Not enough memory to decompress chunk.");
 408      }
 409   }
 410
 411   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
 412   {
 413#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
 414      char umsg[50];
 415
 416      png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
 417          comp_type);
 418      png_warning(png_ptr, umsg);
 419#else
 420      png_warning(png_ptr, "Unknown zTXt compression type");
 421#endif
 422
 423      /* The recovery is to simply drop the data. */
 424   }
 425
 426   /* Generic error return - leave the prefix, delete the compressed
 427    * data, reallocate the chunkdata to remove the potentially large
 428    * amount of compressed data.
 429    */
 430   {
 431      png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
 432      if (text != NULL)
 433      {
 434         if (prefix_size > 0)
 435            png_memcpy(text, png_ptr->chunkdata, prefix_size);
 436         png_free(png_ptr, png_ptr->chunkdata);
 437         png_ptr->chunkdata = text;
 438
 439         /* This is an extra zero in the 'uncompressed' part. */
 440         *(png_ptr->chunkdata + prefix_size) = 0x00;
 441      }
 442      /* Ignore a malloc error here - it is safe. */
 443   }
 444
 445   *newlength = prefix_size;
 446}
 447#endif
 448
 449/* Read and check the IDHR chunk */
 450void /* PRIVATE */
 451png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 452{
 453   png_byte buf[13];
 454   png_uint_32 width, height;
 455   int bit_depth, color_type, compression_type, filter_type;
 456   int interlace_type;
 457
 458   png_debug(1, "in png_handle_IHDR");
 459
 460   if (png_ptr->mode & PNG_HAVE_IHDR)
 461      png_error(png_ptr, "Out of place IHDR");
 462
 463   /* Check the length */
 464   if (length != 13)
 465      png_error(png_ptr, "Invalid IHDR chunk");
 466
 467   png_ptr->mode |= PNG_HAVE_IHDR;
 468
 469   png_crc_read(png_ptr, buf, 13);
 470   png_crc_finish(png_ptr, 0);
 471
 472   width = png_get_uint_31(png_ptr, buf);
 473   height = png_get_uint_31(png_ptr, buf + 4);
 474   bit_depth = buf[8];
 475   color_type = buf[9];
 476   compression_type = buf[10];
 477   filter_type = buf[11];
 478   interlace_type = buf[12];
 479
 480   /* Set internal variables */
 481   png_ptr->width = width;
 482   png_ptr->height = height;
 483   png_ptr->bit_depth = (png_byte)bit_depth;
 484   png_ptr->interlaced = (png_byte)interlace_type;
 485   png_ptr->color_type = (png_byte)color_type;
 486#ifdef PNG_MNG_FEATURES_SUPPORTED
 487   png_ptr->filter_type = (png_byte)filter_type;
 488#endif
 489   png_ptr->compression_type = (png_byte)compression_type;
 490
 491   /* Find number of channels */
 492   switch (png_ptr->color_type)
 493   {
 494      case PNG_COLOR_TYPE_GRAY:
 495      case PNG_COLOR_TYPE_PALETTE:
 496         png_ptr->channels = 1;
 497         break;
 498
 499      case PNG_COLOR_TYPE_RGB:
 500         png_ptr->channels = 3;
 501         break;
 502
 503      case PNG_COLOR_TYPE_GRAY_ALPHA:
 504         png_ptr->channels = 2;
 505         break;
 506
 507      case PNG_COLOR_TYPE_RGB_ALPHA:
 508         png_ptr->channels = 4;
 509         break;
 510   }
 511
 512   /* Set up other useful info */
 513   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
 514   png_ptr->channels);
 515   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
 516   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
 517   png_debug1(3, "channels = %d", png_ptr->channels);
 518   png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
 519   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
 520      color_type, interlace_type, compression_type, filter_type);
 521}
 522
 523/* Read and check the palette */
 524void /* PRIVATE */
 525png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 526{
 527   png_color palette[PNG_MAX_PALETTE_LENGTH];
 528   int num, i;
 529#ifdef PNG_POINTER_INDEXING_SUPPORTED
 530   png_colorp pal_ptr;
 531#endif
 532
 533   png_debug(1, "in png_handle_PLTE");
 534
 535   if (!(png_ptr->mode & PNG_HAVE_IHDR))
 536      png_error(png_ptr, "Missing IHDR before PLTE");
 537
 538   else if (png_ptr->mode & PNG_HAVE_IDAT)
 539   {
 540      png_warning(png_ptr, "Invalid PLTE after IDAT");
 541      png_crc_finish(png_ptr, length);
 542      return;
 543   }
 544
 545   else if (png_ptr->mode & PNG_HAVE_PLTE)
 546      png_error(png_ptr, "Duplicate PLTE chunk");
 547
 548   png_ptr->mode |= PNG_HAVE_PLTE;
 549
 550   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
 551   {
 552      png_warning(png_ptr,
 553        "Ignoring PLTE chunk in grayscale PNG");
 554      png_crc_finish(png_ptr, length);
 555      return;
 556   }
 557#ifndef PNG_READ_OPT_PLTE_SUPPORTED
 558   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
 559   {
 560      png_crc_finish(png_ptr, length);
 561      return;
 562   }
 563#endif
 564
 565   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
 566   {
 567      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
 568      {
 569         png_warning(png_ptr, "Invalid palette chunk");
 570         png_crc_finish(png_ptr, length);
 571         return;
 572      }
 573
 574      else
 575      {
 576         png_error(png_ptr, "Invalid palette chunk");
 577      }
 578   }
 579
 580   num = (int)length / 3;
 581
 582#ifdef PNG_POINTER_INDEXING_SUPPORTED
 583   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
 584   {
 585      png_byte buf[3];
 586
 587      png_crc_read(png_ptr, buf, 3);
 588      pal_ptr->red = buf[0];
 589      pal_ptr->green = buf[1];
 590      pal_ptr->blue = buf[2];
 591   }
 592#else
 593   for (i = 0; i < num; i++)
 594   {
 595      png_byte buf[3];
 596
 597      png_crc_read(png_ptr, buf, 3);
 598      /* Don't depend upon png_color being any order */
 599      palette[i].red = buf[0];
 600      palette[i].green = buf[1];
 601      palette[i].blue = buf[2];
 602   }
 603#endif
 604
 605   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
 606    * whatever the normal CRC configuration tells us.  However, if we
 607    * have an RGB image, the PLTE can be considered ancillary, so
 608    * we will act as though it is.
 609    */
 610#ifndef PNG_READ_OPT_PLTE_SUPPORTED
 611   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
 612#endif
 613   {
 614      png_crc_finish(png_ptr, 0);
 615   }
 616#ifndef PNG_READ_OPT_PLTE_SUPPORTED
 617   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
 618   {
 619      /* If we don't want to use the data from an ancillary chunk,
 620         we have two options: an error abort, or a warning and we
 621         ignore the data in this chunk (which should be OK, since
 622         it's considered ancillary for a RGB or RGBA image). */
 623      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
 624      {
 625         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
 626         {
 627            png_chunk_error(png_ptr, "CRC error");
 628         }
 629         else
 630         {
 631            png_chunk_warning(png_ptr, "CRC error");
 632            return;
 633         }
 634      }
 635      /* Otherwise, we (optionally) emit a warning and use the chunk. */
 636      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
 637      {
 638         png_chunk_warning(png_ptr, "CRC error");
 639      }
 640   }
 641#endif
 642
 643   png_set_PLTE(png_ptr, info_ptr, palette, num);
 644
 645#ifdef PNG_READ_tRNS_SUPPORTED
 646   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
 647   {
 648      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
 649      {
 650         if (png_ptr->num_trans > (png_uint_16)num)
 651         {
 652            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
 653            png_ptr->num_trans = (png_uint_16)num;
 654         }
 655         if (info_ptr->num_trans > (png_uint_16)num)
 656         {
 657            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
 658            info_ptr->num_trans = (png_uint_16)num;
 659         }
 660      }
 661   }
 662#endif
 663
 664}
 665
 666void /* PRIVATE */
 667png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 668{
 669   png_debug(1, "in png_handle_IEND");
 670
 671   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
 672   {
 673      png_error(png_ptr, "No image in file");
 674   }
 675
 676   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
 677
 678   if (length != 0)
 679   {
 680      png_warning(png_ptr, "Incorrect IEND chunk length");
 681   }
 682   png_crc_finish(png_ptr, length);
 683
 684   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
 685}
 686
 687#ifdef PNG_READ_gAMA_SUPPORTED
 688void /* PRIVATE */
 689png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 690{
 691   png_fixed_point igamma;
 692#ifdef PNG_FLOATING_POINT_SUPPORTED
 693   float file_gamma;
 694#endif
 695   png_byte buf[4];
 696
 697   png_debug(1, "in png_handle_gAMA");
 698
 699   if (!(png_ptr->mode & PNG_HAVE_IHDR))
 700      png_error(png_ptr, "Missing IHDR before gAMA");
 701   else if (png_ptr->mode & PNG_HAVE_IDAT)
 702   {
 703      png_warning(png_ptr, "Invalid gAMA after IDAT");
 704      png_crc_finish(png_ptr, length);
 705      return;
 706   }
 707   else if (png_ptr->mode & PNG_HAVE_PLTE)
 708      /* Should be an error, but we can cope with it */
 709      png_warning(png_ptr, "Out of place gAMA chunk");
 710
 711   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
 712#ifdef PNG_READ_sRGB_SUPPORTED
 713      && !(info_ptr->valid & PNG_INFO_sRGB)
 714#endif
 715      )
 716   {
 717      png_warning(png_ptr, "Duplicate gAMA chunk");
 718      png_crc_finish(png_ptr, length);
 719      return;
 720   }
 721
 722   if (length != 4)
 723   {
 724      png_warning(png_ptr, "Incorrect gAMA chunk length");
 725      png_crc_finish(png_ptr, length);
 726      return;
 727   }
 728
 729   png_crc_read(png_ptr, buf, 4);
 730   if (png_crc_finish(png_ptr, 0))
 731      return;
 732
 733   igamma = (png_fixed_point)png_get_uint_32(buf);
 734   /* Check for zero gamma */
 735   if (igamma == 0)
 736      {
 737         png_warning(png_ptr,
 738           "Ignoring gAMA chunk with gamma=0");
 739         return;
 740      }
 741
 742#ifdef PNG_READ_sRGB_SUPPORTED
 743   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
 744      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
 745      {
 746         png_warning(png_ptr,
 747           "Ignoring incorrect gAMA value when sRGB is also present");
 748#ifdef PNG_CONSOLE_IO_SUPPORTED
 749         fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
 750#endif
 751         return;
 752      }
 753#endif /* PNG_READ_sRGB_SUPPORTED */
 754
 755#ifdef PNG_FLOATING_POINT_SUPPORTED
 756   file_gamma = (float)igamma / (float)100000.0;
 757#  ifdef PNG_READ_GAMMA_SUPPORTED
 758     png_ptr->gamma = file_gamma;
 759#  endif
 760     png_set_gAMA(png_ptr, info_ptr, file_gamma);
 761#endif
 762#ifdef PNG_FIXED_POINT_SUPPORTED
 763   png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
 764#endif
 765}
 766#endif
 767
 768#ifdef PNG_READ_sBIT_SUPPORTED
 769void /* PRIVATE */
 770png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 771{
 772   png_size_t truelen;
 773   png_byte buf[4];
 774
 775   png_debug(1, "in png_handle_sBIT");
 776
 777   buf[0] = buf[1] = buf[2] = buf[3] = 0;
 778
 779   if (!(png_ptr->mode & PNG_HAVE_IHDR))
 780      png_error(png_ptr, "Missing IHDR before sBIT");
 781   else if (png_ptr->mode & PNG_HAVE_IDAT)
 782   {
 783      png_warning(png_ptr, "Invalid sBIT after IDAT");
 784      png_crc_finish(png_ptr, length);
 785      return;
 786   }
 787   else if (png_ptr->mode & PNG_HAVE_PLTE)
 788   {
 789      /* Should be an error, but we can cope with it */
 790      png_warning(png_ptr, "Out of place sBIT chunk");
 791   }
 792   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
 793   {
 794      png_warning(png_ptr, "Duplicate sBIT chunk");
 795      png_crc_finish(png_ptr, length);
 796      return;
 797   }
 798
 799   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
 800      truelen = 3;
 801   else
 802      truelen = (png_size_t)png_ptr->channels;
 803
 804   if (length != truelen || length > 4)
 805   {
 806      png_warning(png_ptr, "Incorrect sBIT chunk length");
 807      png_crc_finish(png_ptr, length);
 808      return;
 809   }
 810
 811   png_crc_read(png_ptr, buf, truelen);
 812   if (png_crc_finish(png_ptr, 0))
 813      return;
 814
 815   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
 816   {
 817      png_ptr->sig_bit.red = buf[0];
 818      png_ptr->sig_bit.green = buf[1];
 819      png_ptr->sig_bit.blue = buf[2];
 820      png_ptr->sig_bit.alpha = buf[3];
 821   }
 822   else
 823   {
 824      png_ptr->sig_bit.gray = buf[0];
 825      png_ptr->sig_bit.red = buf[0];
 826      png_ptr->sig_bit.green = buf[0];
 827      png_ptr->sig_bit.blue = buf[0];
 828      png_ptr->sig_bit.alpha = buf[1];
 829   }
 830   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
 831}
 832#endif
 833
 834#ifdef PNG_READ_cHRM_SUPPORTED
 835void /* PRIVATE */
 836png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 837{
 838   png_byte buf[32];
 839#ifdef PNG_FLOATING_POINT_SUPPORTED
 840   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 841#endif
 842   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
 843      int_y_green, int_x_blue, int_y_blue;
 844
 845   png_uint_32 uint_x, uint_y;
 846
 847   png_debug(1, "in png_handle_cHRM");
 848
 849   if (!(png_ptr->mode & PNG_HAVE_IHDR))
 850      png_error(png_ptr, "Missing IHDR before cHRM");
 851   else if (png_ptr->mode & PNG_HAVE_IDAT)
 852   {
 853      png_warning(png_ptr, "Invalid cHRM after IDAT");
 854      png_crc_finish(png_ptr, length);
 855      return;
 856   }
 857   else if (png_ptr->mode & PNG_HAVE_PLTE)
 858      /* Should be an error, but we can cope with it */
 859      png_warning(png_ptr, "Missing PLTE before cHRM");
 860
 861   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
 862#ifdef PNG_READ_sRGB_SUPPORTED
 863      && !(info_ptr->valid & PNG_INFO_sRGB)
 864#endif
 865      )
 866   {
 867      png_warning(png_ptr, "Duplicate cHRM chunk");
 868      png_crc_finish(png_ptr, length);
 869      return;
 870   }
 871
 872   if (length != 32)
 873   {
 874      png_warning(png_ptr, "Incorrect cHRM chunk length");
 875      png_crc_finish(png_ptr, length);
 876      return;
 877   }
 878
 879   png_crc_read(png_ptr, buf, 32);
 880   if (png_crc_finish(png_ptr, 0))
 881      return;
 882
 883   uint_x = png_get_uint_32(buf);
 884   uint_y = png_get_uint_32(buf + 4);
 885   int_x_white = (png_fixed_point)uint_x;
 886   int_y_white = (png_fixed_point)uint_y;
 887
 888   uint_x = png_get_uint_32(buf + 8);
 889   uint_y = png_get_uint_32(buf + 12);
 890   int_x_red = (png_fixed_point)uint_x;
 891   int_y_red = (png_fixed_point)uint_y;
 892
 893   uint_x = png_get_uint_32(buf + 16);
 894   uint_y = png_get_uint_32(buf + 20);
 895   int_x_green = (png_fixed_point)uint_x;
 896   int_y_green = (png_fixed_point)uint_y;
 897
 898   uint_x = png_get_uint_32(buf + 24);
 899   uint_y = png_get_uint_32(buf + 28);
 900   int_x_blue = (png_fixed_point)uint_x;
 901   int_y_blue = (png_fixed_point)uint_y;
 902
 903#ifdef PNG_FLOATING_POINT_SUPPORTED
 904   white_x = (float)int_x_white / (float)100000.0;
 905   white_y = (float)int_y_white / (float)100000.0;
 906   red_x   = (float)int_x_red   / (float)100000.0;
 907   red_y   = (float)int_y_red   / (float)100000.0;
 908   green_x = (float)int_x_green / (float)100000.0;
 909   green_y = (float)int_y_green / (float)100000.0;
 910   blue_x  = (float)int_x_blue  / (float)100000.0;
 911   blue_y  = (float)int_y_blue  / (float)100000.0;
 912#endif
 913
 914#ifdef PNG_READ_sRGB_SUPPORTED
 915   if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
 916      {
 917      if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
 918          PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
 919          PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
 920          PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
 921          PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
 922          PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
 923          PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
 924          PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
 925         {
 926            png_warning(png_ptr,
 927              "Ignoring incorrect cHRM value when sRGB is also present");
 928#ifdef PNG_CONSOLE_IO_SUPPORTED
 929#ifdef PNG_FLOATING_POINT_SUPPORTED
 930            fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
 931               white_x, white_y, red_x, red_y);
 932            fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
 933               green_x, green_y, blue_x, blue_y);
 934#else
 935            fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
 936               (long)int_x_white, (long)int_y_white,
 937               (long)int_x_red, (long)int_y_red);
 938            fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
 939               (long)int_x_green, (long)int_y_green,
 940               (long)int_x_blue, (long)int_y_blue);
 941#endif
 942#endif /* PNG_CONSOLE_IO_SUPPORTED */
 943         }
 944         return;
 945      }
 946#endif /* PNG_READ_sRGB_SUPPORTED */
 947
 948#ifdef PNG_FLOATING_POINT_SUPPORTED
 949   png_set_cHRM(png_ptr, info_ptr,
 950      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
 951#endif
 952#ifdef PNG_FIXED_POINT_SUPPORTED
 953   png_set_cHRM_fixed(png_ptr, info_ptr,
 954      int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
 955      int_y_green, int_x_blue, int_y_blue);
 956#endif
 957}
 958#endif
 959
 960#ifdef PNG_READ_sRGB_SUPPORTED
 961void /* PRIVATE */
 962png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 963{
 964   int intent;
 965   png_byte buf[1];
 966
 967   png_debug(1, "in png_handle_sRGB");
 968
 969   if (!(png_ptr->mode & PNG_HAVE_IHDR))
 970      png_error(png_ptr, "Missing IHDR before sRGB");
 971   else if (png_ptr->mode & PNG_HAVE_IDAT)
 972   {
 973      png_warning(png_ptr, "Invalid sRGB after IDAT");
 974      png_crc_finish(png_ptr, length);
 975      return;
 976   }
 977   else if (png_ptr->mode & PNG_HAVE_PLTE)
 978      /* Should be an error, but we can cope with it */
 979      png_warning(png_ptr, "Out of place sRGB chunk");
 980
 981   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
 982   {
 983      png_warning(png_ptr, "Duplicate sRGB chunk");
 984      png_crc_finish(png_ptr, length);
 985      return;
 986   }
 987
 988   if (length != 1)
 989   {
 990      png_warning(png_ptr, "Incorrect sRGB chunk length");
 991      png_crc_finish(png_ptr, length);
 992      return;
 993   }
 994
 995   png_crc_read(png_ptr, buf, 1);
 996   if (png_crc_finish(png_ptr, 0))
 997      return;
 998
 999   intent = buf[0];
1000   /* Check for bad intent */
1001   if (intent >= PNG_sRGB_INTENT_LAST)
1002   {
1003      png_warning(png_ptr, "Unknown sRGB intent");
1004      return;
1005   }
1006
1007#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
1008   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
1009   {
1010   png_fixed_point igamma;
1011#ifdef PNG_FIXED_POINT_SUPPORTED
1012      igamma=info_ptr->int_gamma;
1013#else
1014#  ifdef PNG_FLOATING_POINT_SUPPORTED
1015      igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
1016#  endif
1017#endif
1018      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
1019      {
1020         png_warning(png_ptr,
1021           "Ignoring incorrect gAMA value when sRGB is also present");
1022#ifdef PNG_CONSOLE_IO_SUPPORTED
1023#  ifdef PNG_FIXED_POINT_SUPPORTED
1024         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
1025            (int)png_ptr->int_gamma);
1026#  else
1027#    ifdef PNG_FLOATING_POINT_SUPPORTED
1028         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
1029#    endif
1030#  endif
1031#endif
1032      }
1033   }
1034#endif /* PNG_READ_gAMA_SUPPORTED */
1035
1036#ifdef PNG_READ_cHRM_SUPPORTED
1037#ifdef PNG_FIXED_POINT_SUPPORTED
1038   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
1039      if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
1040          PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
1041          PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
1042          PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
1043          PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
1044          PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
1045          PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
1046          PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
1047         {
1048            png_warning(png_ptr,
1049              "Ignoring incorrect cHRM value when sRGB is also present");
1050         }
1051#endif /* PNG_FIXED_POINT_SUPPORTED */
1052#endif /* PNG_READ_cHRM_SUPPORTED */
1053
1054   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1055}
1056#endif /* PNG_READ_sRGB_SUPPORTED */
1057
1058#ifdef PNG_READ_iCCP_SUPPORTED
1059void /* PRIVATE */
1060png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1061/* Note: this does not properly handle chunks that are > 64K under DOS */
1062{
1063   png_byte compression_type;
1064   png_bytep pC;
1065   png_charp profile;
1066   png_uint_32 skip = 0;
1067   png_uint_32 profile_size, profile_length;
1068   png_size_t slength, prefix_length, data_length;
1069
1070   png_debug(1, "in png_handle_iCCP");
1071
1072   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1073      png_error(png_ptr, "Missing IHDR before iCCP");
1074   else if (png_ptr->mode & PNG_HAVE_IDAT)
1075   {
1076      png_warning(png_ptr, "Invalid iCCP after IDAT");
1077      png_crc_finish(png_ptr, length);
1078      return;
1079   }
1080   else if (png_ptr->mode & PNG_HAVE_PLTE)
1081      /* Should be an error, but we can cope with it */
1082      png_warning(png_ptr, "Out of place iCCP chunk");
1083
1084   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1085   {
1086      png_warning(png_ptr, "Duplicate iCCP chunk");
1087      png_crc_finish(png_ptr, length);
1088      return;
1089   }
1090
1091#ifdef PNG_MAX_MALLOC_64K
1092   if (length > (png_uint_32)65535L)
1093   {
1094      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1095      skip = length - (png_uint_32)65535L;
1096      length = (png_uint_32)65535L;
1097   }
1098#endif
1099
1100   png_free(png_ptr, png_ptr->chunkdata);
1101   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1102   slength = (png_size_t)length;
1103   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1104
1105   if (png_crc_finish(png_ptr, skip))
1106   {
1107      png_free(png_ptr, png_ptr->chunkdata);
1108      png_ptr->chunkdata = NULL;
1109      return;
1110   }
1111
1112   png_ptr->chunkdata[slength] = 0x00;
1113
1114   for (profile = png_ptr->chunkdata; *profile; profile++)
1115      /* Empty loop to find end of name */ ;
1116
1117   ++profile;
1118
1119   /* There should be at least one zero (the compression type byte)
1120    * following the separator, and we should be on it
1121    */
1122   if ( profile >= png_ptr->chunkdata + slength - 1)
1123   {
1124      png_free(png_ptr, png_ptr->chunkdata);
1125      png_ptr->chunkdata = NULL;
1126      png_warning(png_ptr, "Malformed iCCP chunk");
1127      return;
1128   }
1129
1130   /* Compression_type should always be zero */
1131   compression_type = *profile++;
1132   if (compression_type)
1133   {
1134      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1135      compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
1136                                 wrote nonzero) */
1137   }
1138
1139   prefix_length = profile - png_ptr->chunkdata;
1140   png_decompress_chunk(png_ptr, compression_type,
1141     slength, prefix_length, &data_length);
1142
1143   profile_length = data_length - prefix_length;
1144
1145   if ( prefix_length > data_length || profile_length < 4)
1146   {
1147      png_free(png_ptr, png_ptr->chunkdata);
1148      png_ptr->chunkdata = NULL;
1149      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1150      return;
1151   }
1152
1153   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1154   pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1155   profile_size = ((*(pC    ))<<24) |
1156                  ((*(pC + 1))<<16) |
1157                  ((*(pC + 2))<< 8) |
1158                  ((*(pC + 3))    );
1159
1160   if (profile_size < profile_length)
1161      profile_length = profile_size;
1162
1163   if (profile_size > profile_length)
1164   {
1165      png_free(png_ptr, png_ptr->chunkdata);
1166      png_ptr->chunkdata = NULL;
1167      png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1168      return;
1169   }
1170
1171   png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1172     compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1173   png_free(png_ptr, png_ptr->chunkdata);
1174   png_ptr->chunkdata = NULL;
1175}
1176#endif /* PNG_READ_iCCP_SUPPORTED */
1177
1178#ifdef PNG_READ_sPLT_SUPPORTED
1179void /* PRIVATE */
1180png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1181/* Note: this does not properly handle chunks that are > 64K under DOS */
1182{
1183   png_bytep entry_start;
1184   png_sPLT_t new_palette;
1185#ifdef PNG_POINTER_INDEXING_SUPPORTED
1186   png_sPLT_entryp pp;
1187#endif
1188   int data_length, entry_size, i;
1189   png_uint_32 skip = 0;
1190   png_size_t slength;
1191
1192   png_debug(1, "in png_handle_sPLT");
1193
1194#ifdef PNG_USER_LIMITS_SUPPORTED
1195
1196   if (png_ptr->user_chunk_cache_max != 0)
1197   {
1198      if (png_ptr->user_chunk_cache_max == 1)
1199      {
1200         png_crc_finish(png_ptr, length);
1201         return;
1202      }
1203      if (--png_ptr->user_chunk_cache_max == 1)
1204      {
1205         png_warning(png_ptr, "No space in chunk cache for sPLT");
1206         png_crc_finish(png_ptr, length);
1207         return;
1208      }
1209   }
1210#endif
1211
1212   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1213      png_error(png_ptr, "Missing IHDR before sPLT");
1214   else if (png_ptr->mode & PNG_HAVE_IDAT)
1215   {
1216      png_warning(png_ptr, "Invalid sPLT after IDAT");
1217      png_crc_finish(png_ptr, length);
1218      return;
1219   }
1220
1221#ifdef PNG_MAX_MALLOC_64K
1222   if (length > (png_uint_32)65535L)
1223   {
1224      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1225      skip = length - (png_uint_32)65535L;
1226      length = (png_uint_32)65535L;
1227   }
1228#endif
1229
1230   png_free(png_ptr, png_ptr->chunkdata);
1231   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1232   slength = (png_size_t)length;
1233   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1234
1235   if (png_crc_finish(png_ptr, skip))
1236   {
1237      png_free(png_ptr, png_ptr->chunkdata);
1238      png_ptr->chunkdata = NULL;
1239      return;
1240   }
1241
1242   png_ptr->chunkdata[slength] = 0x00;
1243
1244   for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1245       entry_start++)
1246      /* Empty loop to find end of name */ ;
1247   ++entry_start;
1248
1249   /* A sample depth should follow the separator, and we should be on it  */
1250   if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
1251   {
1252      png_free(png_ptr, png_ptr->chunkdata);
1253      png_ptr->chunkdata = NULL;
1254      png_warning(png_ptr, "malformed sPLT chunk");
1255      return;
1256   }
1257
1258   new_palette.depth = *entry_start++;
1259   entry_size = (new_palette.depth == 8 ? 6 : 10);
1260   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
1261
1262   /* Integrity-check the data length */
1263   if (data_length % entry_size)
1264   {
1265      png_free(png_ptr, png_ptr->chunkdata);
1266      png_ptr->chunkdata = NULL;
1267      png_warning(png_ptr, "sPLT chunk has bad length");
1268      return;
1269   }
1270
1271   new_palette.nentries = (png_int_32) ( data_length / entry_size);
1272   if ((png_uint_32) new_palette.nentries >
1273       (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
1274   {
1275       png_warning(png_ptr, "sPLT chunk too long");
1276       return;
1277   }
1278   new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1279       png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1280   if (new_palette.entries == NULL)
1281   {
1282       png_warning(png_ptr, "sPLT chunk requires too much memory");
1283       return;
1284   }
1285
1286#ifdef PNG_POINTER_INDEXING_SUPPORTED
1287   for (i = 0; i < new_palette.nentries; i++)
1288   {
1289      pp = new_palette.entries + i;
1290
1291      if (new_palette.depth == 8)
1292      {
1293          pp->red = *entry_start++;
1294          pp->green = *entry_start++;
1295          pp->blue = *entry_start++;
1296          pp->alpha = *entry_start++;
1297      }
1298      else
1299      {
1300          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
1301          pp->green = png_get_uint_16(entry_start); entry_start += 2;
1302          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
1303          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1304      }
1305      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1306   }
1307#else
1308   pp = new_palette.entries;
1309   for (i = 0; i < new_palette.nentries; i++)
1310   {
1311
1312      if (new_palette.depth == 8)
1313      {
1314          pp[i].red   = *entry_start++;
1315          pp[i].green = *entry_start++;
1316          pp[i].blue  = *entry_start++;
1317          pp[i].alpha = *entry_start++;
1318      }
1319      else
1320      {
1321          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
1322          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1323          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
1324          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1325      }
1326      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1327   }
1328#endif
1329
1330   /* Discard all chunk data except the name and stash that */
1331   new_palette.name = png_ptr->chunkdata;
1332
1333   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1334
1335   png_free(png_ptr, png_ptr->chunkdata);
1336   png_ptr->chunkdata = NULL;
1337   png_free(png_ptr, new_palette.entries);
1338}
1339#endif /* PNG_READ_sPLT_SUPPORTED */
1340
1341#ifdef PNG_READ_tRNS_SUPPORTED
1342void /* PRIVATE */
1343png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1344{
1345   png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1346
1347   png_debug(1, "in png_handle_tRNS");
1348
1349   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1350      png_error(png_ptr, "Missing IHDR before tRNS");
1351   else if (png_ptr->mode & PNG_HAVE_IDAT)
1352   {
1353      png_warning(png_ptr, "Invalid tRNS after IDAT");
1354      png_crc_finish(png_ptr, length);
1355      return;
1356   }
1357   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1358   {
1359      png_warning(png_ptr, "Duplicate tRNS chunk");
1360      png_crc_finish(png_ptr, length);
1361      return;
1362   }
1363
1364   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1365   {
1366      png_byte buf[2];
1367
1368      if (length != 2)
1369      {
1370         png_warning(png_ptr, "Incorrect tRNS chunk length");
1371         png_crc_finish(png_ptr, length);
1372         return;
1373      }
1374
1375      png_crc_read(png_ptr, buf, 2);
1376      png_ptr->num_trans = 1;
1377      png_ptr->trans_values.gray = png_get_uint_16(buf);
1378   }
1379   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1380   {
1381      png_byte buf[6];
1382
1383      if (length != 6)
1384      {
1385         png_warning(png_ptr, "Incorrect tRNS chunk length");
1386         png_crc_finish(png_ptr, length);
1387         return;
1388      }
1389      png_crc_read(png_ptr, buf, (png_size_t)length);
1390      png_ptr->num_trans = 1;
1391      png_ptr->trans_values.red = png_get_uint_16(buf);
1392      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1393      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1394   }
1395   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1396   {
1397      if (!(png_ptr->mode & PNG_HAVE_PLTE))
1398      {
1399         /* Should be an error, but we can cope with it. */
1400         png_warning(png_ptr, "Missing PLTE before tRNS");
1401      }
1402      if (length > (png_uint_32)png_ptr->num_palette ||
1403          length > PNG_MAX_PALETTE_LENGTH)
1404      {
1405         png_warning(png_ptr, "Incorrect tRNS chunk length");
1406         png_crc_finish(png_ptr, length);
1407         return;
1408      }
1409      if (length == 0)
1410      {
1411         png_warning(png_ptr, "Zero length tRNS chunk");
1412         png_crc_finish(png_ptr, length);
1413         return;
1414      }
1415      png_crc_read(png_ptr, readbuf, (png_size_t)length);
1416      png_ptr->num_trans = (png_uint_16)length;
1417   }
1418   else
1419   {
1420      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1421      png_crc_finish(png_ptr, length);
1422      return;
1423   }
1424
1425   if (png_crc_finish(png_ptr, 0))
1426   {
1427      png_ptr->num_trans = 0;
1428      return;
1429   }
1430
1431   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1432      &(png_ptr->trans_values));
1433}
1434#endif
1435
1436#ifdef PNG_READ_bKGD_SUPPORTED
1437void /* PRIVATE */
1438png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1439{
1440   png_size_t truelen;
1441   png_byte buf[6];
1442
1443   png_debug(1, "in png_handle_bKGD");
1444
1445   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1446      png_error(png_ptr, "Missing IHDR before bKGD");
1447   else if (png_ptr->mode & PNG_HAVE_IDAT)
1448   {
1449      png_warning(png_ptr, "Invalid bKGD after IDAT");
1450      png_crc_finish(png_ptr, length);
1451      return;
1452   }
1453   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1454            !(png_ptr->mode & PNG_HAVE_PLTE))
1455   {
1456      png_warning(png_ptr, "Missing PLTE before bKGD");
1457      png_crc_finish(png_ptr, length);
1458      return;
1459   }
1460   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1461   {
1462      png_warning(png_ptr, "Duplicate bKGD chunk");
1463      png_crc_finish(png_ptr, length);
1464      return;
1465   }
1466
1467   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1468      truelen = 1;
1469   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1470      truelen = 6;
1471   else
1472      truelen = 2;
1473
1474   if (length != truelen)
1475   {
1476      png_warning(png_ptr, "Incorrect bKGD chunk length");
1477      png_crc_finish(png_ptr, length);
1478      return;
1479   }
1480
1481   png_crc_read(png_ptr, buf, truelen);
1482   if (png_crc_finish(png_ptr, 0))
1483      return;
1484
1485   /* We convert the index value into RGB components so that we can allow
1486    * arbitrary RGB values for background when we have transparency, and
1487    * so it is easy to determine the RGB values of the background color
1488    * from the info_ptr struct. */
1489   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1490   {
1491      png_ptr->background.index = buf[0];
1492      if (info_ptr && info_ptr->num_palette)
1493      {
1494          if (buf[0] >= info_ptr->num_palette)
1495          {
1496             png_warning(png_ptr, "Incorrect bKGD chunk index value");
1497             return;
1498          }
1499          png_ptr->background.red =
1500             (png_uint_16)png_ptr->palette[buf[0]].red;
1501          png_ptr->background.green =
1502             (png_uint_16)png_ptr->palette[buf[0]].green;
1503          png_ptr->background.blue =
1504             (png_uint_16)png_ptr->palette[buf[0]].blue;
1505      }
1506   }
1507   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1508   {
1509      png_ptr->background.red =
1510      png_ptr->background.green =
1511      png_ptr->background.blue =
1512      png_ptr->background.gray = png_get_uint_16(buf);
1513   }
1514   else
1515   {
1516      png_ptr->background.red = png_get_uint_16(buf);
1517      png_ptr->background.green = png_get_uint_16(buf + 2);
1518      png_ptr->background.blue = png_get_uint_16(buf + 4);
1519   }
1520
1521   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1522}
1523#endif
1524
1525#ifdef PNG_READ_hIST_SUPPORTED
1526void /* PRIVATE */
1527png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1528{
1529   unsigned int num, i;
1530   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1531
1532   png_debug(1, "in png_handle_hIST");
1533
1534   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1535      png_error(png_ptr, "Missing IHDR before hIST");
1536   else if (png_ptr->mode & PNG_HAVE_IDAT)
1537   {
1538      png_warning(png_ptr, "Invalid hIST after IDAT");
1539      png_crc_finish(png_ptr, length);
1540      return;
1541   }
1542   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1543   {
1544      png_warning(png_ptr, "Missing PLTE before hIST");
1545      png_crc_finish(png_ptr, length);
1546      return;
1547   }
1548   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1549   {
1550      png_warning(png_ptr, "Duplicate hIST chunk");
1551      png_crc_finish(png_ptr, length);
1552      return;
1553   }
1554
1555   num = length / 2 ;
1556   if (num != (unsigned int) png_ptr->num_palette || num >
1557      (unsigned int) PNG_MAX_PALETTE_LENGTH)
1558   {
1559      png_warning(png_ptr, "Incorrect hIST chunk length");
1560      png_crc_finish(png_ptr, length);
1561      return;
1562   }
1563
1564   for (i = 0; i < num; i++)
1565   {
1566      png_byte buf[2];
1567
1568      png_crc_read(png_ptr, buf, 2);
1569      readbuf[i] = png_get_uint_16(buf);
1570   }
1571
1572   if (png_crc_finish(png_ptr, 0))
1573      return;
1574
1575   png_set_hIST(png_ptr, info_ptr, readbuf);
1576}
1577#endif
1578
1579#ifdef PNG_READ_pHYs_SUPPORTED
1580void /* PRIVATE */
1581png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1582{
1583   png_byte buf[9];
1584   png_uint_32 res_x, res_y;
1585   int unit_type;
1586
1587   png_debug(1, "in png_handle_pHYs");
1588
1589   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1590      png_error(png_ptr, "Missing IHDR before pHYs");
1591   else if (png_ptr->mode & PNG_HAVE_IDAT)
1592   {
1593      png_warning(png_ptr, "Invalid pHYs after IDAT");
1594      png_crc_finish(png_ptr, length);
1595      return;
1596   }
1597   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1598   {
1599      png_warning(png_ptr, "Duplicate pHYs chunk");
1600      png_crc_finish(png_ptr, length);
1601      return;
1602   }
1603
1604   if (length != 9)
1605   {
1606      png_warning(png_ptr, "Incorrect pHYs chunk length");
1607      png_crc_finish(png_ptr, length);
1608      return;
1609   }
1610
1611   png_crc_read(png_ptr, buf, 9);
1612   if (png_crc_finish(png_ptr, 0))
1613      return;
1614
1615   res_x = png_get_uint_32(buf);
1616   res_y = png_get_uint_32(buf + 4);
1617   unit_type = buf[8];
1618   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1619}
1620#endif
1621
1622#ifdef PNG_READ_oFFs_SUPPORTED
1623void /* PRIVATE */
1624png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1625{
1626   png_byte buf[9];
1627   png_int_32 offset_x, offset_y;
1628   int unit_type;
1629
1630   png_debug(1, "in png_handle_oFFs");
1631
1632   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1633      png_error(png_ptr, "Missing IHDR before oFFs");
1634   else if (png_ptr->mode & PNG_HAVE_IDAT)
1635   {
1636      png_warning(png_ptr, "Invalid oFFs after IDAT");
1637      png_crc_finish(png_ptr, length);
1638      return;
1639   }
1640   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1641   {
1642      png_warning(png_ptr, "Duplicate oFFs chunk");
1643      png_crc_finish(png_ptr, length);
1644      return;
1645   }
1646
1647   if (length != 9)
1648   {
1649      png_warning(png_ptr, "Incorrect oFFs chunk length");
1650      png_crc_finish(png_ptr, length);
1651      return;
1652   }
1653
1654   png_crc_read(png_ptr, buf, 9);
1655   if (png_crc_finish(png_ptr, 0))
1656      return;
1657
1658   offset_x = png_get_int_32(buf);
1659   offset_y = png_get_int_32(buf + 4);
1660   unit_type = buf[8];
1661   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1662}
1663#endif
1664
1665#ifdef PNG_READ_pCAL_SUPPORTED
1666/* Read the pCAL chunk (described in the PNG Extensions document) */
1667void /* PRIVATE */
1668png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1669{
1670   png_int_32 X0, X1;
1671   png_byte type, nparams;
1672   png_charp buf, units, endptr;
1673   png_charpp params;
1674   png_size_t slength;
1675   int i;
1676
1677   png_debug(1, "in png_handle_pCAL");
1678
1679   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1680      png_error(png_ptr, "Missing IHDR before pCAL");
1681   else if (png_ptr->mode & PNG_HAVE_IDAT)
1682   {
1683      png_warning(png_ptr, "Invalid pCAL after IDAT");
1684      png_crc_finish(png_ptr, length);
1685      return;
1686   }
1687   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1688   {
1689      png_warning(png_ptr, "Duplicate pCAL chunk");
1690      png_crc_finish(png_ptr, length);
1691      return;
1692   }
1693
1694   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
1695      length + 1);
1696   png_free(png_ptr, png_ptr->chunkdata);
1697   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1698   if (png_ptr->chunkdata == NULL)
1699     {
1700       png_warning(png_ptr, "No memory for pCAL purpose.");
1701       return;
1702     }
1703   slength = (png_size_t)length;
1704   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1705
1706   if (png_crc_finish(png_ptr, 0))
1707   {
1708      png_free(png_ptr, png_ptr->chunkdata);
1709      png_ptr->chunkdata = NULL;
1710      return;
1711   }
1712
1713   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
1714
1715   png_debug(3, "Finding end of pCAL purpose string");
1716   for (buf = png_ptr->chunkdata; *buf; buf++)
1717      /* Empty loop */ ;
1718
1719   end

Large files files are truncated, but you can click here to view the full file