pngrutil.c 95.2 KB
Newer Older
1

A
Andreas Dilger 已提交
2
/* pngrutil.c - utilities to read a PNG file
3
 *
4
 * Last changed in libpng 1.4.1 [March 30, 2010]
5
 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (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 15
 * libpng itself during the course of reading an image.
 */
G
Guy Schalnat 已提交
16

17
#include "pngpriv.h"
18

19 20
#ifdef PNG_READ_SUPPORTED

21
#    define png_strtod(p,a,b) strtod(a,b)
22
png_uint_32 PNGAPI
23 24 25 26
png_get_uint_31(png_structp png_ptr, png_bytep buf)
{
   png_uint_32 i = png_get_uint_32(buf);
   if (i > PNG_UINT_31_MAX)
27
      png_error(png_ptr, "PNG unsigned integer out of range");
28 29
   return (i);
}
30
#ifndef PNG_USE_READ_MACROS
31
/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
32
png_uint_32 PNGAPI
G
Guy Schalnat 已提交
33
png_get_uint_32(png_bytep buf)
G
Guy Schalnat 已提交
34
{
35 36
   png_uint_32 i =
       ((png_uint_32)(*(buf    )) << 24) +
37
       ((png_uint_32)(*(buf + 1)) << 16) +
38 39
       ((png_uint_32)(*(buf + 2)) <<  8) +
       ((png_uint_32)(*(buf + 3))      ) ;
G
Guy Schalnat 已提交
40

41
   return (i);
G
Guy Schalnat 已提交
42 43
}

44
/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
A
Andreas Dilger 已提交
45
 * data is stored in the PNG file in two's complement format, and it is
46 47
 * assumed that the machine format for signed integers is the same.
 */
48
png_int_32 PNGAPI
A
Andreas Dilger 已提交
49 50
png_get_int_32(png_bytep buf)
{
51
   png_int_32 i = ((png_int_32)(*buf) << 24) +
52 53 54
       ((png_int_32)(*(buf + 1)) << 16) +
       ((png_int_32)(*(buf + 2)) << 8) +
       (png_int_32)(*(buf + 3));
A
Andreas Dilger 已提交
55

56
   return (i);
A
Andreas Dilger 已提交
57 58
}

59
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
60
png_uint_16 PNGAPI
G
Guy Schalnat 已提交
61
png_get_uint_16(png_bytep buf)
G
Guy Schalnat 已提交
62
{
63
   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
64
       (png_uint_16)(*(buf + 1)));
G
Guy Schalnat 已提交
65

66
   return (i);
G
Guy Schalnat 已提交
67
}
68
#endif /* PNG_USE_READ_MACROS */
G
Guy Schalnat 已提交
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
/* Read the chunk header (length + type name).
 * Put the type name into png_ptr->chunk_name, and return the length.
 */
png_uint_32 /* PRIVATE */
png_read_chunk_header(png_structp png_ptr)
{
   png_byte buf[8];
   png_uint_32 length;

#ifdef PNG_IO_STATE_SUPPORTED
   /* Inform the I/O callback that the chunk header is being read.
    * PNG_IO_CHUNK_HDR requires a single I/O call.
    */
   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
#endif

86
   /* Read the length and the chunk name */
87 88 89
   png_read_data(png_ptr, buf, 8);
   length = png_get_uint_31(png_ptr, buf);

90
   /* Put the chunk name into png_ptr->chunk_name */
91 92
   png_memcpy(png_ptr->chunk_name, buf + 4, 4);

93
   png_debug2(0, "Reading %s chunk, length = %u",
94
       png_ptr->chunk_name, length);
95

96
   /* Reset the crc and run it over the chunk name */
97 98 99
   png_reset_crc(png_ptr);
   png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);

100
   /* Check to see if chunk name is valid */
101 102
   png_check_chunk_name(png_ptr, png_ptr->chunk_name);

103 104 105 106 107 108 109 110 111 112
#ifdef PNG_IO_STATE_SUPPORTED
   /* Inform the I/O callback that chunk data will (possibly) be read.
    * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
    */
   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
#endif

   return length;
}

113
/* Read data, and (optionally) run it through the CRC. */
114
void /* PRIVATE */
A
Andreas Dilger 已提交
115
png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
G
Guy Schalnat 已提交
116
{
117 118
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
119
   png_read_data(png_ptr, buf, length);
A
Andreas Dilger 已提交
120
   png_calculate_crc(png_ptr, buf, length);
G
Guy Schalnat 已提交
121 122
}

A
Andreas Dilger 已提交
123
/* Optionally skip data and then check the CRC.  Depending on whether we
124 125 126 127
 * are reading a ancillary or critical chunk, and how the program has set
 * things up, we may calculate the CRC on the data and print a message.
 * Returns '1' if there was a CRC error, '0' otherwise.
 */
128
int /* PRIVATE */
A
Andreas Dilger 已提交
129
png_crc_finish(png_structp png_ptr, png_uint_32 skip)
G
Guy Schalnat 已提交
130
{
131 132
   png_size_t i;
   png_size_t istop = png_ptr->zbuf_size;
G
Guy Schalnat 已提交
133

134
   for (i = (png_size_t)skip; i > istop; i -= istop)
A
Andreas Dilger 已提交
135
   {
A
Andreas Dilger 已提交
136
      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
G
Guy Schalnat 已提交
137
   }
138
   if (i)
G
Guy Schalnat 已提交
139
   {
140
      png_crc_read(png_ptr, png_ptr->zbuf, i);
A
Andreas Dilger 已提交
141 142
   }

A
Andreas Dilger 已提交
143
   if (png_crc_error(png_ptr))
A
Andreas Dilger 已提交
144
   {
145
      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
146
          !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
147
          (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
148
          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
A
Andreas Dilger 已提交
149
      {
150
         png_chunk_warning(png_ptr, "CRC error");
A
Andreas Dilger 已提交
151 152 153
      }
      else
      {
154 155
         png_chunk_benign_error(png_ptr, "CRC error");
         return (0);
A
Andreas Dilger 已提交
156
      }
157
      return (1);
G
Guy Schalnat 已提交
158
   }
A
Andreas Dilger 已提交
159

160
   return (0);
G
Guy Schalnat 已提交
161 162
}

163
/* Compare the CRC stored in the PNG file with that calculated by libpng from
164 165
 * the data it has read thus far.
 */
166
int /* PRIVATE */
A
Andreas Dilger 已提交
167 168 169 170
png_crc_error(png_structp png_ptr)
{
   png_byte crc_bytes[4];
   png_uint_32 crc;
A
Andreas Dilger 已提交
171
   int need_crc = 1;
A
Andreas Dilger 已提交
172

A
Andreas Dilger 已提交
173 174 175 176 177 178 179 180 181 182 183
   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
   {
      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
         need_crc = 0;
   }
   else                                                    /* critical */
   {
      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
         need_crc = 0;
   }
A
Andreas Dilger 已提交
184

185
#ifdef PNG_IO_STATE_SUPPORTED
186
   /* Inform the I/O callback that the chunk CRC is being read */
187 188 189
   /* PNG_IO_CHUNK_CRC requires the I/O to be done at once */
   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
#endif
190

A
Andreas Dilger 已提交
191
   png_read_data(png_ptr, crc_bytes, 4);
A
Andreas Dilger 已提交
192

A
Andreas Dilger 已提交
193 194 195
   if (need_crc)
   {
      crc = png_get_uint_32(crc_bytes);
196
      return ((int)(crc != png_ptr->crc));
A
Andreas Dilger 已提交
197 198
   }
   else
199
      return (0);
A
Andreas Dilger 已提交
200 201
}

202
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
203
    defined(PNG_READ_iCCP_SUPPORTED)
204 205
static png_size_t
png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
206
    png_bytep output, png_size_t output_size)
207
{
208
   png_size_t count = 0;
209

210 211 212 213
   png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
   png_ptr->zstream.avail_in = size;

   while (1)
214
   {
215
      int ret, avail;
216

217 218 219
      /* Reset the output buffer each time round - we empty it
       * after every inflate call.
       */
220
      png_ptr->zstream.next_out = png_ptr->zbuf;
221
      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
222

223 224
      ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
225

226 227 228 229
      /* First copy/count any new output - but only if we didn't
       * get an error code.
       */
      if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
230
      {
231
         if (output != 0 && output_size > count)
232 233 234 235 236 237
         {
            int copy = output_size - count;
            if (avail < copy)
               copy = avail;
            png_memcpy(output + count, png_ptr->zbuf, copy);
         }
238 239
         count += avail;
      }
240

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
      if (ret == Z_OK)
         continue;

      /* Termination conditions - always reset the zstream, it
       * must be left in inflateInit state.
       */
      png_ptr->zstream.avail_in = 0;
      inflateReset(&png_ptr->zstream);

      if (ret == Z_STREAM_END)
         return count; /* NOTE: may be zero. */

      /* Now handle the error codes - the API always returns 0
       * and the error message is dumped into the uncompressed
       * buffer if available.
       */
      {
258 259 260 261
         char *msg;
#ifdef PNG_CONSOLE_IO_SUPPORTED
	 char umsg[52];
#endif
262 263 264 265
         if (png_ptr->zstream.msg != 0)
            msg = png_ptr->zstream.msg;
         else
         {
266
#ifdef PNG_CONSOLE_IO_SUPPORTED
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
            switch (ret)
            {
               case Z_BUF_ERROR:
                  msg = "Buffer error in compressed datastream in %s chunk";
                  break;
               case Z_DATA_ERROR:
                  msg = "Data error in compressed datastream in %s chunk";
                  break;
               default:
                  msg = "Incomplete compressed datastream in %s chunk";
                  break;
            }

            png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
            msg = umsg;
282
#else
283
            msg = "Damaged compressed datastream in chunk other than IDAT";
284
#endif
285
         }
286 287

         png_warning(png_ptr, msg);
288 289
      }

290
      /* 0 means an error - notice that this code simply ignores
291 292 293
       * zero length compressed chunks as a result.
       */
      return 0;
294 295 296
   }
}

297 298 299 300 301 302 303
/*
 * Decompress trailing data in a chunk.  The assumption is that chunkdata
 * points at an allocated area holding the contents of a chunk with a
 * trailing compressed part.  What we get back is an allocated area
 * holding the original prefix part and an uncompressed version of the
 * trailing part (the malloc area passed in is freed).
 */
304
void /* PRIVATE */
305
png_decompress_chunk(png_structp png_ptr, int comp_type,
306 307
    png_size_t chunklength,
    png_size_t prefix_size, png_size_t *newlength)
308
{
309 310
   /* The caller should guarantee this */
   if (prefix_size > chunklength)
311
   {
312 313 314
      /* The recovery is to delete the chunk. */
      png_warning(png_ptr, "invalid chunklength");
      prefix_size = 0; /* To delete everything */
315
   }
316

317
   else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
318
   {
319
      png_size_t expanded_size = png_inflate(png_ptr,
320 321 322 323
          (png_bytep)(png_ptr->chunkdata + prefix_size),
          chunklength - prefix_size,
          0,            /*output*/
          0);           /*output size*/
324 325 326 327 328 329 330

      /* Now check the limits on this chunk - if the limit fails the
       * compressed data will be removed, the prefix will remain.
       */
#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
      if (png_ptr->user_chunk_malloc_max &&
          (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
331
#else
332
#  ifdef PNG_USER_CHUNK_MALLOC_MAX
333 334
      if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
          prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
335
#  endif
336
#endif
337 338 339 340 341 342 343
         png_warning(png_ptr, "Exceeded size limit while expanding chunk");

      /* If the size is zero either there was an error and a message
       * has already been output (warning) or the size really is zero
       * and we have nothing to do - the code will exit through the
       * error case below.
       */
344 345
#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
    defined(PNG_USER_CHUNK_MALLOC_MAX)
346
      else if (expanded_size > 0)
347 348 349
#else
      if (expanded_size > 0)
#endif
350 351
      {
         /* Success (maybe) - really uncompress the chunk. */
352 353 354
         png_size_t new_size = 0;
         png_charp text = png_malloc_warn(png_ptr,
             prefix_size + expanded_size + 1);
355 356

         if (text != NULL)
357
         {
358 359
            png_memcpy(text, png_ptr->chunkdata, prefix_size);
            new_size = png_inflate(png_ptr,
360
                (png_bytep)(png_ptr->chunkdata + prefix_size),
361
                chunklength - prefix_size,
362
                (png_bytep)(text + prefix_size), expanded_size);
363 364 365 366 367 368 369 370 371
            text[prefix_size + expanded_size] = 0; /* just in case */

            if (new_size == expanded_size)
            {
               png_free(png_ptr, png_ptr->chunkdata);
               png_ptr->chunkdata = text;
               *newlength = prefix_size + expanded_size;
               return; /* The success return! */
            }
372
      
373 374 375 376 377
            png_warning(png_ptr, "png_inflate logic error");
            png_free(png_ptr, text);
         }
         else
            png_warning(png_ptr, "Not enough memory to decompress chunk");
378 379
      }
   }
380

381 382
   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
   {
383
#ifdef PNG_STDIO_SUPPORTED
384 385
      char umsg[50];

386 387
      png_snprintf(umsg, sizeof umsg,
          "Unknown zTXt compression type %d", comp_type);
388 389 390 391 392
      png_warning(png_ptr, umsg);
#else
      png_warning(png_ptr, "Unknown zTXt compression type");
#endif

393
      /* The recovery is to simply drop the data. */
394 395
   }

396 397 398 399
   /* Generic error return - leave the prefix, delete the compressed
    * data, reallocate the chunkdata to remove the potentially large
    * amount of compressed data.
    */
400
   {
401 402
      png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
      if (text != NULL)
403
      {
404
         if (prefix_size > 0)
405
            png_memcpy(text, png_ptr->chunkdata, prefix_size);
406 407
         png_free(png_ptr, png_ptr->chunkdata);
         png_ptr->chunkdata = text;
408

409 410
         /* This is an extra zero in the 'uncompressed' part. */
         *(png_ptr->chunkdata + prefix_size) = 0x00;
411 412
      }
      /* Ignore a malloc error here - it is safe. */
413 414
   }

415
   *newlength = prefix_size;
416 417
}
#endif
A
Andreas Dilger 已提交
418

419
/* Read and check the IDHR chunk */
420
void /* PRIVATE */
A
Andreas Dilger 已提交
421
png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
422 423 424 425 426 427
{
   png_byte buf[13];
   png_uint_32 width, height;
   int bit_depth, color_type, compression_type, filter_type;
   int interlace_type;

428
   png_debug(1, "in png_handle_IHDR");
A
Andreas Dilger 已提交
429

430
   if (png_ptr->mode & PNG_HAVE_IHDR)
G
Guy Schalnat 已提交
431 432
      png_error(png_ptr, "Out of place IHDR");

433
   /* Check the length */
G
Guy Schalnat 已提交
434
   if (length != 13)
G
Guy Schalnat 已提交
435
      png_error(png_ptr, "Invalid IHDR chunk");
G
Guy Schalnat 已提交
436

A
Andreas Dilger 已提交
437 438
   png_ptr->mode |= PNG_HAVE_IHDR;

G
Guy Schalnat 已提交
439
   png_crc_read(png_ptr, buf, 13);
A
Andreas Dilger 已提交
440
   png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
441

442 443
   width = png_get_uint_31(png_ptr, buf);
   height = png_get_uint_31(png_ptr, buf + 4);
G
Guy Schalnat 已提交
444 445 446 447 448 449
   bit_depth = buf[8];
   color_type = buf[9];
   compression_type = buf[10];
   filter_type = buf[11];
   interlace_type = buf[12];

450
   /* Set internal variables */
G
Guy Schalnat 已提交
451 452
   png_ptr->width = width;
   png_ptr->height = height;
G
Guy Schalnat 已提交
453 454 455
   png_ptr->bit_depth = (png_byte)bit_depth;
   png_ptr->interlaced = (png_byte)interlace_type;
   png_ptr->color_type = (png_byte)color_type;
456
#ifdef PNG_MNG_FEATURES_SUPPORTED
457
   png_ptr->filter_type = (png_byte)filter_type;
458
#endif
459
   png_ptr->compression_type = (png_byte)compression_type;
G
Guy Schalnat 已提交
460

461
   /* Find number of channels */
G
Guy Schalnat 已提交
462 463
   switch (png_ptr->color_type)
   {
A
Andreas Dilger 已提交
464 465
      case PNG_COLOR_TYPE_GRAY:
      case PNG_COLOR_TYPE_PALETTE:
G
Guy Schalnat 已提交
466 467
         png_ptr->channels = 1;
         break;
468

A
Andreas Dilger 已提交
469
      case PNG_COLOR_TYPE_RGB:
G
Guy Schalnat 已提交
470 471
         png_ptr->channels = 3;
         break;
472

A
Andreas Dilger 已提交
473
      case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
474 475
         png_ptr->channels = 2;
         break;
476

A
Andreas Dilger 已提交
477
      case PNG_COLOR_TYPE_RGB_ALPHA:
G
Guy Schalnat 已提交
478 479 480
         png_ptr->channels = 4;
         break;
   }
A
Andreas Dilger 已提交
481

482
   /* Set up other useful info */
G
Guy Schalnat 已提交
483
   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
484
   png_ptr->channels);
485
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
486 487
   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
   png_debug1(3, "channels = %d", png_ptr->channels);
488
   png_debug1(3, "rowbytes = %u", png_ptr->rowbytes);
A
Andreas Dilger 已提交
489
   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
490
       color_type, interlace_type, compression_type, filter_type);
G
Guy Schalnat 已提交
491 492
}

493
/* Read and check the palette */
494
void /* PRIVATE */
A
Andreas Dilger 已提交
495
png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
496
{
497
   png_color palette[PNG_MAX_PALETTE_LENGTH];
A
Andreas Dilger 已提交
498
   int num, i;
499
#ifdef PNG_POINTER_INDEXING_SUPPORTED
500 501
   png_colorp pal_ptr;
#endif
G
Guy Schalnat 已提交
502

503
   png_debug(1, "in png_handle_PLTE");
A
Andreas Dilger 已提交
504

G
Guy Schalnat 已提交
505 506
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before PLTE");
507

A
Andreas Dilger 已提交
508 509 510 511 512 513
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid PLTE after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
514

G
Guy Schalnat 已提交
515
   else if (png_ptr->mode & PNG_HAVE_PLTE)
A
Andreas Dilger 已提交
516 517 518
      png_error(png_ptr, "Duplicate PLTE chunk");

   png_ptr->mode |= PNG_HAVE_PLTE;
G
Guy Schalnat 已提交
519

520 521 522
   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
   {
      png_warning(png_ptr,
523
          "Ignoring PLTE chunk in grayscale PNG");
524 525 526
      png_crc_finish(png_ptr, length);
      return;
   }
527
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
G
Guy Schalnat 已提交
528 529
   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
   {
A
Andreas Dilger 已提交
530
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
531 532 533 534
      return;
   }
#endif

535
   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
G
Guy Schalnat 已提交
536 537 538 539
   {
      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
      {
         png_warning(png_ptr, "Invalid palette chunk");
A
Andreas Dilger 已提交
540
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
541 542
         return;
      }
543

G
Guy Schalnat 已提交
544 545 546 547 548
      else
      {
         png_error(png_ptr, "Invalid palette chunk");
      }
   }
G
Guy Schalnat 已提交
549 550

   num = (int)length / 3;
551

552
#ifdef PNG_POINTER_INDEXING_SUPPORTED
553 554 555 556 557 558 559 560 561 562
   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
   {
      png_byte buf[3];

      png_crc_read(png_ptr, buf, 3);
      pal_ptr->red = buf[0];
      pal_ptr->green = buf[1];
      pal_ptr->blue = buf[2];
   }
#else
G
Guy Schalnat 已提交
563
   for (i = 0; i < num; i++)
G
Guy Schalnat 已提交
564 565 566 567
   {
      png_byte buf[3];

      png_crc_read(png_ptr, buf, 3);
568
      /* Don't depend upon png_color being any order */
G
Guy Schalnat 已提交
569 570 571 572
      palette[i].red = buf[0];
      palette[i].green = buf[1];
      palette[i].blue = buf[2];
   }
573
#endif
A
Andreas Dilger 已提交
574

575
   /* If we actually need the PLTE chunk (ie for a paletted image), we do
576 577 578 579
    * whatever the normal CRC configuration tells us.  However, if we
    * have an RGB image, the PLTE can be considered ancillary, so
    * we will act as though it is.
    */
580
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
A
Andreas Dilger 已提交
581
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
582
#endif
A
Andreas Dilger 已提交
583
   {
A
Andreas Dilger 已提交
584
      png_crc_finish(png_ptr, 0);
A
Andreas Dilger 已提交
585
   }
586
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
A
Andreas Dilger 已提交
587 588 589
   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
   {
      /* If we don't want to use the data from an ancillary chunk,
590 591 592 593
       * we have two options: an error abort, or a warning and we
       * ignore the data in this chunk (which should be OK, since
       * it's considered ancillary for a RGB or RGBA image).
       */
A
Andreas Dilger 已提交
594 595 596 597
      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
      {
         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
         {
598
            png_chunk_benign_error(png_ptr, "CRC error");
A
Andreas Dilger 已提交
599 600 601
         }
         else
         {
602
            png_chunk_warning(png_ptr, "CRC error");
A
Andreas Dilger 已提交
603 604 605
            return;
         }
      }
A
Andreas Dilger 已提交
606
      /* Otherwise, we (optionally) emit a warning and use the chunk. */
A
Andreas Dilger 已提交
607 608
      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
      {
609
         png_chunk_warning(png_ptr, "CRC error");
A
Andreas Dilger 已提交
610 611
      }
   }
612
#endif
613

A
Andreas Dilger 已提交
614
   png_set_PLTE(png_ptr, info_ptr, palette, num);
615

616
#ifdef PNG_READ_tRNS_SUPPORTED
617 618
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   {
619
      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
620
      {
621
         if (png_ptr->num_trans > (png_uint_16)num)
622 623
         {
            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
624 625 626 627 628 629
            png_ptr->num_trans = (png_uint_16)num;
         }
         if (info_ptr->num_trans > (png_uint_16)num)
         {
            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
            info_ptr->num_trans = (png_uint_16)num;
630 631 632 633 634
         }
      }
   }
#endif

A
Andreas Dilger 已提交
635
}
G
Guy Schalnat 已提交
636

637
void /* PRIVATE */
A
Andreas Dilger 已提交
638 639
png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
640
   png_debug(1, "in png_handle_IEND");
A
Andreas Dilger 已提交
641

A
Andreas Dilger 已提交
642 643 644 645 646
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
   {
      png_error(png_ptr, "No image in file");
   }

647
   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
A
Andreas Dilger 已提交
648 649 650 651 652

   if (length != 0)
   {
      png_warning(png_ptr, "Incorrect IEND chunk length");
   }
A
Andreas Dilger 已提交
653
   png_crc_finish(png_ptr, length);
654

655
   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
G
Guy Schalnat 已提交
656 657
}

658
#ifdef PNG_READ_gAMA_SUPPORTED
659
void /* PRIVATE */
A
Andreas Dilger 已提交
660
png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
661
{
662
   png_fixed_point igamma;
663
#ifdef PNG_FLOATING_POINT_SUPPORTED
A
Andreas Dilger 已提交
664
   float file_gamma;
665
#endif
G
Guy Schalnat 已提交
666 667
   png_byte buf[4];

668
   png_debug(1, "in png_handle_gAMA");
A
Andreas Dilger 已提交
669

G
Guy Schalnat 已提交
670 671
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before gAMA");
A
Andreas Dilger 已提交
672 673 674 675 676 677
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid gAMA after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
678 679 680
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place gAMA chunk");
681

682
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
683
#ifdef PNG_READ_sRGB_SUPPORTED
684
       && !(info_ptr->valid & PNG_INFO_sRGB)
685
#endif
686
       )
A
Andreas Dilger 已提交
687 688 689 690 691
   {
      png_warning(png_ptr, "Duplicate gAMA chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
692

G
Guy Schalnat 已提交
693 694
   if (length != 4)
   {
G
Guy Schalnat 已提交
695
      png_warning(png_ptr, "Incorrect gAMA chunk length");
A
Andreas Dilger 已提交
696
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
697 698 699 700
      return;
   }

   png_crc_read(png_ptr, buf, 4);
A
Andreas Dilger 已提交
701 702 703
   if (png_crc_finish(png_ptr, 0))
      return;

704
   igamma = (png_fixed_point)png_get_uint_32(buf);
705
   /* Check for zero gamma */
A
Andreas Dilger 已提交
706
   if (igamma == 0)
707 708
      {
         png_warning(png_ptr,
709
             "Ignoring gAMA chunk with gamma=0");
710 711
         return;
      }
G
Guy Schalnat 已提交
712

713
#ifdef PNG_READ_sRGB_SUPPORTED
714
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
715
      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
716 717
      {
         png_warning(png_ptr,
718
             "Ignoring incorrect gAMA value when sRGB is also present");
719
#ifdef PNG_CONSOLE_IO_SUPPORTED
720
         fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
721
#endif
722 723 724 725
         return;
      }
#endif /* PNG_READ_sRGB_SUPPORTED */

726
#ifdef PNG_FLOATING_POINT_SUPPORTED
727
   file_gamma = (float)igamma / (float)100000.0;
728
#  ifdef PNG_READ_GAMMA_SUPPORTED
729
   png_ptr->gamma = file_gamma;
730
#  endif
731
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
732 733 734 735
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
#endif
G
Guy Schalnat 已提交
736
}
G
Guy Schalnat 已提交
737
#endif
G
Guy Schalnat 已提交
738

739
#ifdef PNG_READ_sBIT_SUPPORTED
740
void /* PRIVATE */
A
Andreas Dilger 已提交
741
png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
742
{
A
Andreas Dilger 已提交
743
   png_size_t truelen;
G
Guy Schalnat 已提交
744
   png_byte buf[4];
G
Guy Schalnat 已提交
745

746
   png_debug(1, "in png_handle_sBIT");
A
Andreas Dilger 已提交
747

G
Guy Schalnat 已提交
748
   buf[0] = buf[1] = buf[2] = buf[3] = 0;
G
Guy Schalnat 已提交
749

G
Guy Schalnat 已提交
750 751
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sBIT");
A
Andreas Dilger 已提交
752 753 754 755 756 757
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sBIT after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
758
   else if (png_ptr->mode & PNG_HAVE_PLTE)
759
   {
G
Guy Schalnat 已提交
760 761
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place sBIT chunk");
762
   }
763
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
A
Andreas Dilger 已提交
764 765 766 767 768
   {
      png_warning(png_ptr, "Duplicate sBIT chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
769

G
Guy Schalnat 已提交
770
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
A
Andreas Dilger 已提交
771
      truelen = 3;
G
Guy Schalnat 已提交
772
   else
A
Andreas Dilger 已提交
773
      truelen = (png_size_t)png_ptr->channels;
G
Guy Schalnat 已提交
774

775
   if (length != truelen || length > 4)
G
Guy Schalnat 已提交
776
   {
G
Guy Schalnat 已提交
777
      png_warning(png_ptr, "Incorrect sBIT chunk length");
A
Andreas Dilger 已提交
778
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
779
      return;
G
Guy Schalnat 已提交
780 781
   }

A
Andreas Dilger 已提交
782
   png_crc_read(png_ptr, buf, truelen);
A
Andreas Dilger 已提交
783 784 785
   if (png_crc_finish(png_ptr, 0))
      return;

G
Guy Schalnat 已提交
786 787
   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
   {
G
Guy Schalnat 已提交
788 789 790 791
      png_ptr->sig_bit.red = buf[0];
      png_ptr->sig_bit.green = buf[1];
      png_ptr->sig_bit.blue = buf[2];
      png_ptr->sig_bit.alpha = buf[3];
G
Guy Schalnat 已提交
792 793 794
   }
   else
   {
G
Guy Schalnat 已提交
795
      png_ptr->sig_bit.gray = buf[0];
796 797 798
      png_ptr->sig_bit.red = buf[0];
      png_ptr->sig_bit.green = buf[0];
      png_ptr->sig_bit.blue = buf[0];
G
Guy Schalnat 已提交
799
      png_ptr->sig_bit.alpha = buf[1];
G
Guy Schalnat 已提交
800
   }
A
Andreas Dilger 已提交
801
   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
G
Guy Schalnat 已提交
802
}
G
Guy Schalnat 已提交
803
#endif
G
Guy Schalnat 已提交
804

805
#ifdef PNG_READ_cHRM_SUPPORTED
806
void /* PRIVATE */
A
Andreas Dilger 已提交
807
png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
808
{
809
   png_byte buf[32];
810
#ifdef PNG_FLOATING_POINT_SUPPORTED
G
Guy Schalnat 已提交
811
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
812
#endif
813
   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
814
       int_y_green, int_x_blue, int_y_blue;
G
Guy Schalnat 已提交
815

816 817
   png_uint_32 uint_x, uint_y;

818
   png_debug(1, "in png_handle_cHRM");
A
Andreas Dilger 已提交
819

G
Guy Schalnat 已提交
820
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
821
      png_error(png_ptr, "Missing IHDR before cHRM");
A
Andreas Dilger 已提交
822 823 824 825 826 827
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid cHRM after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
828 829 830
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Missing PLTE before cHRM");
831

832
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
833
#ifdef PNG_READ_sRGB_SUPPORTED
834
       && !(info_ptr->valid & PNG_INFO_sRGB)
835 836
#endif
      )
A
Andreas Dilger 已提交
837 838 839 840 841
   {
      png_warning(png_ptr, "Duplicate cHRM chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
842

G
Guy Schalnat 已提交
843 844
   if (length != 32)
   {
G
Guy Schalnat 已提交
845
      png_warning(png_ptr, "Incorrect cHRM chunk length");
A
Andreas Dilger 已提交
846
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
847
      return;
G
Guy Schalnat 已提交
848 849
   }

850 851 852
   png_crc_read(png_ptr, buf, 32);
   if (png_crc_finish(png_ptr, 0))
      return;
A
Andreas Dilger 已提交
853

854 855
   uint_x = png_get_uint_32(buf);
   uint_y = png_get_uint_32(buf + 4);
856 857
   int_x_white = (png_fixed_point)uint_x;
   int_y_white = (png_fixed_point)uint_y;
G
Guy Schalnat 已提交
858

859 860
   uint_x = png_get_uint_32(buf + 8);
   uint_y = png_get_uint_32(buf + 12);
861 862
   int_x_red = (png_fixed_point)uint_x;
   int_y_red = (png_fixed_point)uint_y;
G
Guy Schalnat 已提交
863

864 865
   uint_x = png_get_uint_32(buf + 16);
   uint_y = png_get_uint_32(buf + 20);
866 867
   int_x_green = (png_fixed_point)uint_x;
   int_y_green = (png_fixed_point)uint_y;
G
Guy Schalnat 已提交
868

869 870
   uint_x = png_get_uint_32(buf + 24);
   uint_y = png_get_uint_32(buf + 28);
871 872 873
   int_x_blue = (png_fixed_point)uint_x;
   int_y_blue = (png_fixed_point)uint_y;

874 875 876 877 878 879 880 881 882 883
#ifdef PNG_FLOATING_POINT_SUPPORTED
   white_x = (float)int_x_white / (float)100000.0;
   white_y = (float)int_y_white / (float)100000.0;
   red_x   = (float)int_x_red   / (float)100000.0;
   red_y   = (float)int_y_red   / (float)100000.0;
   green_x = (float)int_x_green / (float)100000.0;
   green_y = (float)int_y_green / (float)100000.0;
   blue_x  = (float)int_x_blue  / (float)100000.0;
   blue_y  = (float)int_y_blue  / (float)100000.0;
#endif
G
Guy Schalnat 已提交
884

885
#ifdef PNG_READ_sRGB_SUPPORTED
886
   if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
887
      {
888 889 890 891 892 893 894 895
      if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
          PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
          PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
          PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
          PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
          PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
          PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
          PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
896 897
         {
            png_warning(png_ptr,
898
                "Ignoring incorrect cHRM value when sRGB is also present");
899
#ifdef PNG_CONSOLE_IO_SUPPORTED
900
#ifdef PNG_FLOATING_POINT_SUPPORTED
901
            fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
902
                white_x, white_y, red_x, red_y);
903
            fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
904
                green_x, green_y, blue_x, blue_y);
905
#else
906
            fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
907
                int_x_white, int_y_white, int_x_red, int_y_red);
908
            fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
909
                int_x_green, int_y_green, int_x_blue, int_y_blue);
910
#endif
911
#endif /* PNG_CONSOLE_IO_SUPPORTED */
912
         }
913 914 915 916
         return;
      }
#endif /* PNG_READ_sRGB_SUPPORTED */

917
#ifdef PNG_FLOATING_POINT_SUPPORTED
A
Andreas Dilger 已提交
918
   png_set_cHRM(png_ptr, info_ptr,
919
       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
920 921 922
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_set_cHRM_fixed(png_ptr, info_ptr,
923 924
       int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
       int_y_green, int_x_blue, int_y_blue);
925
#endif
G
Guy Schalnat 已提交
926
}
G
Guy Schalnat 已提交
927
#endif
G
Guy Schalnat 已提交
928

929
#ifdef PNG_READ_sRGB_SUPPORTED
930
void /* PRIVATE */
931 932
png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
933
   int intent;
934 935
   png_byte buf[1];

936
   png_debug(1, "in png_handle_sRGB");
937 938 939 940 941 942 943 944 945 946 947 948

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sRGB");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sRGB after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place sRGB chunk");
949

950
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
   {
      png_warning(png_ptr, "Duplicate sRGB chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

   if (length != 1)
   {
      png_warning(png_ptr, "Incorrect sRGB chunk length");
      png_crc_finish(png_ptr, length);
      return;
   }

   png_crc_read(png_ptr, buf, 1);
   if (png_crc_finish(png_ptr, 0))
      return;

   intent = buf[0];
969
   /* Check for bad intent */
970
   if (intent >= PNG_sRGB_INTENT_LAST)
971 972 973 974 975
   {
      png_warning(png_ptr, "Unknown sRGB intent");
      return;
   }

976
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
977
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
978
   {
979
   png_fixed_point igamma;
980
#ifdef PNG_FIXED_POINT_SUPPORTED
981
      igamma=info_ptr->int_gamma;
982
#else
983
#  ifdef PNG_FLOATING_POINT_SUPPORTED
984
      igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
985 986
#  endif
#endif
987
      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
988 989
      {
         png_warning(png_ptr,
990
             "Ignoring incorrect gAMA value when sRGB is also present");
991
#ifdef PNG_CONSOLE_IO_SUPPORTED
992
#  ifdef PNG_FIXED_POINT_SUPPORTED
993
         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
994
             (int)png_ptr->int_gamma);
995 996
#  else
#    ifdef PNG_FLOATING_POINT_SUPPORTED
997
         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
998 999
#    endif
#  endif
1000 1001
#endif
      }
1002
   }
1003 1004 1005
#endif /* PNG_READ_gAMA_SUPPORTED */

#ifdef PNG_READ_cHRM_SUPPORTED
1006
#ifdef PNG_FIXED_POINT_SUPPORTED
1007
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
1008 1009 1010 1011 1012 1013 1014 1015
      if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
1016 1017
         {
            png_warning(png_ptr,
1018
                "Ignoring incorrect cHRM value when sRGB is also present");
1019
         }
1020
#endif /* PNG_FIXED_POINT_SUPPORTED */
1021
#endif /* PNG_READ_cHRM_SUPPORTED */
1022

1023
   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1024
}
1025 1026
#endif /* PNG_READ_sRGB_SUPPORTED */

1027
#ifdef PNG_READ_iCCP_SUPPORTED
1028
void /* PRIVATE */
1029 1030 1031 1032
png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
   png_byte compression_type;
1033
   png_bytep pC;
1034 1035
   png_charp profile;
   png_uint_32 skip = 0;
1036
   png_uint_32 profile_size, profile_length;
1037
   png_size_t slength, prefix_length, data_length;
1038

1039
   png_debug(1, "in png_handle_iCCP");
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before iCCP");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid iCCP after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place iCCP chunk");

1053
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
   {
      png_warning(png_ptr, "Duplicate iCCP chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

#ifdef PNG_MAX_MALLOC_64K
   if (length > (png_uint_32)65535L)
   {
      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
      skip = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
   }
#endif

1069 1070
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1071
   slength = (png_size_t)length;
1072
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1073 1074 1075

   if (png_crc_finish(png_ptr, skip))
   {
1076 1077
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1078 1079 1080
      return;
   }

1081
   png_ptr->chunkdata[slength] = 0x00;
1082

1083
   for (profile = png_ptr->chunkdata; *profile; profile++)
1084
      /* Empty loop to find end of name */ ;
1085

1086 1087
   ++profile;

1088 1089 1090
   /* There should be at least one zero (the compression type byte)
    * following the separator, and we should be on it
    */
1091
   if ( profile >= png_ptr->chunkdata + slength - 1)
1092
   {
1093 1094
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1095
      png_warning(png_ptr, "Malformed iCCP chunk");
1096
      return;
1097 1098
   }

1099
   /* Compression_type should always be zero */
1100
   compression_type = *profile++;
1101 1102 1103
   if (compression_type)
   {
      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1104
      compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
1105 1106
                                 wrote nonzero) */
   }
1107

1108
   prefix_length = profile - png_ptr->chunkdata;
1109
   png_decompress_chunk(png_ptr, compression_type,
1110
       slength, prefix_length, &data_length);
1111

1112
   profile_length = data_length - prefix_length;
1113

1114
   if ( prefix_length > data_length || profile_length < 4)
1115
   {
1116 1117
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1118 1119 1120 1121
      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
      return;
   }

1122
   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1123
   pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1124 1125 1126 1127
   profile_size = ((*(pC    )) << 24) |
                  ((*(pC + 1)) << 16) |
                  ((*(pC + 2)) <<  8) |
                  ((*(pC + 3))      );
1128

1129
   if (profile_size < profile_length)
1130 1131
      profile_length = profile_size;

1132
   if (profile_size > profile_length)
1133
   {
1134 1135
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1136
      png_warning(png_ptr, "Ignoring truncated iCCP profile");
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
#ifdef PNG_STDIO_SUPPORTED
 {
    char umsg[50];

    png_snprintf(umsg, 50, "declared profile size = %lu",
        (unsigned long)profile_size);
    png_warning(png_ptr, umsg);
    png_snprintf(umsg, 50, "actual profile length = %lu",
        (unsigned long)profile_length);
    png_warning(png_ptr, umsg);
 }
#endif
1149 1150 1151
      return;
   }

1152
   png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1153
       compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1154 1155
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
1156 1157 1158
}
#endif /* PNG_READ_iCCP_SUPPORTED */

1159
#ifdef PNG_READ_sPLT_SUPPORTED
1160
void /* PRIVATE */
1161 1162 1163 1164
png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
   png_bytep entry_start;
1165
   png_sPLT_t new_palette;
1166
#ifdef PNG_POINTER_INDEXING_SUPPORTED
1167 1168
   png_sPLT_entryp pp;
#endif
1169 1170 1171 1172
   int data_length, entry_size, i;
   png_uint_32 skip = 0;
   png_size_t slength;

1173
   png_debug(1, "in png_handle_sPLT");
1174

1175
#ifdef PNG_USER_LIMITS_SUPPORTED
1176

1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
   if (png_ptr->user_chunk_cache_max != 0)
   {
      if (png_ptr->user_chunk_cache_max == 1)
      {
         png_crc_finish(png_ptr, length);
         return;
      }
      if (--png_ptr->user_chunk_cache_max == 1)
      {
         png_warning(png_ptr, "No space in chunk cache for sPLT");
         png_crc_finish(png_ptr, length);
         return;
      }
   }
#endif

1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sPLT");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sPLT after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }

#ifdef PNG_MAX_MALLOC_64K
   if (length > (png_uint_32)65535L)
   {
      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
      skip = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
   }
#endif

1211 1212
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1213
   slength = (png_size_t)length;
1214
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1215 1216 1217

   if (png_crc_finish(png_ptr, skip))
   {
1218 1219
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1220 1221 1222
      return;
   }

1223
   png_ptr->chunkdata[slength] = 0x00;
1224

1225 1226
   for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
       entry_start++)
1227
      /* Empty loop to find end of name */ ;
1228 1229
   ++entry_start;

1230
   /* A sample depth should follow the separator, and we should be on it  */
1231
   if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
1232
   {
1233 1234
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1235 1236
      png_warning(png_ptr, "malformed sPLT chunk");
      return;
1237 1238 1239
   }

   new_palette.depth = *entry_start++;
1240
   entry_size = (new_palette.depth == 8 ? 6 : 10);
1241
   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
1242

1243
   /* Integrity-check the data length */
1244 1245
   if (data_length % entry_size)
   {
1246 1247
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1248 1249
      png_warning(png_ptr, "sPLT chunk has bad length");
      return;
1250 1251
   }

1252
   new_palette.nentries = (png_int_32) ( data_length / entry_size);
1253
   if ((png_uint_32) new_palette.nentries >
1254
       (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
1255 1256 1257 1258 1259
   {
       png_warning(png_ptr, "sPLT chunk too long");
       return;
   }
   new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1260
       png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1261 1262 1263 1264 1265
   if (new_palette.entries == NULL)
   {
       png_warning(png_ptr, "sPLT chunk requires too much memory");
       return;
   }
1266

1267
#ifdef PNG_POINTER_INDEXING_SUPPORTED
1268 1269
   for (i = 0; i < new_palette.nentries; i++)
   {
1270
      pp = new_palette.entries + i;
1271 1272 1273

      if (new_palette.depth == 8)
      {
1274 1275 1276 1277
         pp->red = *entry_start++;
         pp->green = *entry_start++;
         pp->blue = *entry_start++;
         pp->alpha = *entry_start++;
1278 1279 1280
      }
      else
      {
1281 1282 1283 1284
         pp->red   = png_get_uint_16(entry_start); entry_start += 2;
         pp->green = png_get_uint_16(entry_start); entry_start += 2;
         pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
         pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1285 1286 1287
      }
      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
   }
1288 1289 1290 1291 1292 1293 1294
#else
   pp = new_palette.entries;
   for (i = 0; i < new_palette.nentries; i++)
   {

      if (new_palette.depth == 8)
      {
1295 1296 1297 1298
         pp[i].red   = *entry_start++;
         pp[i].green = *entry_start++;
         pp[i].blue  = *entry_start++;
         pp[i].alpha = *entry_start++;
1299 1300 1301
      }
      else
      {
1302 1303 1304 1305
         pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
         pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
         pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
         pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1306 1307 1308 1309
      }
      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
   }
#endif
1310

1311
   /* Discard all chunk data except the name and stash that */
1312
   new_palette.name = png_ptr->chunkdata;
1313

1314
   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1315

1316 1317
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
1318 1319 1320 1321
   png_free(png_ptr, new_palette.entries);
}
#endif /* PNG_READ_sPLT_SUPPORTED */

1322
#ifdef PNG_READ_tRNS_SUPPORTED
1323
void /* PRIVATE */
A
Andreas Dilger 已提交
1324
png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1325
{
1326
   png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1327

1328
   png_debug(1, "in png_handle_tRNS");
A
Andreas Dilger 已提交
1329

G
Guy Schalnat 已提交
1330 1331
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before tRNS");
A
Andreas Dilger 已提交
1332 1333 1334 1335 1336 1337
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid tRNS after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1338
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
A
Andreas Dilger 已提交
1339
   {
1340
      png_warning(png_ptr, "Duplicate tRNS chunk");
A
Andreas Dilger 已提交
1341 1342 1343
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1344

1345
   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
1346
   {
1347 1348 1349
      png_byte buf[2];

      if (length != 2)
G
Guy Schalnat 已提交
1350
      {
G
Guy Schalnat 已提交
1351
         png_warning(png_ptr, "Incorrect tRNS chunk length");
A
Andreas Dilger 已提交
1352
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1353 1354 1355
         return;
      }

1356 1357
      png_crc_read(png_ptr, buf, 2);
      png_ptr->num_trans = 1;
1358
      png_ptr->trans_color.gray = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1359 1360 1361 1362 1363 1364 1365
   }
   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
   {
      png_byte buf[6];

      if (length != 6)
      {
G
Guy Schalnat 已提交
1366
         png_warning(png_ptr, "Incorrect tRNS chunk length");
A
Andreas Dilger 已提交
1367
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1368 1369
         return;
      }
A
Andreas Dilger 已提交
1370
      png_crc_read(png_ptr, buf, (png_size_t)length);
1371
      png_ptr->num_trans = 1;
1372 1373 1374
      png_ptr->trans_color.red = png_get_uint_16(buf);
      png_ptr->trans_color.green = png_get_uint_16(buf + 2);
      png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
G
Guy Schalnat 已提交
1375
   }
1376
   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1377
   {
1378 1379 1380 1381 1382 1383 1384
      if (!(png_ptr->mode & PNG_HAVE_PLTE))
      {
         /* Should be an error, but we can cope with it. */
         png_warning(png_ptr, "Missing PLTE before tRNS");
      }
      if (length > (png_uint_32)png_ptr->num_palette ||
          length > PNG_MAX_PALETTE_LENGTH)
G
Guy Schalnat 已提交
1385
      {
G
Guy Schalnat 已提交
1386
         png_warning(png_ptr, "Incorrect tRNS chunk length");
A
Andreas Dilger 已提交
1387
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1388 1389
         return;
      }
1390 1391 1392 1393 1394 1395 1396 1397
      if (length == 0)
      {
         png_warning(png_ptr, "Zero length tRNS chunk");
         png_crc_finish(png_ptr, length);
         return;
      }
      png_crc_read(png_ptr, readbuf, (png_size_t)length);
      png_ptr->num_trans = (png_uint_16)length;
G
Guy Schalnat 已提交
1398 1399
   }
   else
G
Guy Schalnat 已提交
1400 1401
   {
      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
A
Andreas Dilger 已提交
1402
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1403 1404
      return;
   }
G
Guy Schalnat 已提交
1405

A
Andreas Dilger 已提交
1406
   if (png_crc_finish(png_ptr, 0))
1407 1408
   {
      png_ptr->num_trans = 0;
A
Andreas Dilger 已提交
1409
      return;
1410
   }
A
Andreas Dilger 已提交
1411

1412
   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1413
       &(png_ptr->trans_color));
G
Guy Schalnat 已提交
1414
}
G
Guy Schalnat 已提交
1415
#endif
G
Guy Schalnat 已提交
1416

1417
#ifdef PNG_READ_bKGD_SUPPORTED
1418
void /* PRIVATE */
A
Andreas Dilger 已提交
1419
png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1420
{
A
Andreas Dilger 已提交
1421
   png_size_t truelen;
G
Guy Schalnat 已提交
1422 1423
   png_byte buf[6];

1424
   png_debug(1, "in png_handle_bKGD");
A
Andreas Dilger 已提交
1425

G
Guy Schalnat 已提交
1426 1427
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before bKGD");
A
Andreas Dilger 已提交
1428 1429 1430 1431 1432 1433
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid bKGD after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1434
   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1435
       !(png_ptr->mode & PNG_HAVE_PLTE))
G
Guy Schalnat 已提交
1436 1437
   {
      png_warning(png_ptr, "Missing PLTE before bKGD");
A
Andreas Dilger 已提交
1438 1439 1440
      png_crc_finish(png_ptr, length);
      return;
   }
1441
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
A
Andreas Dilger 已提交
1442 1443 1444
   {
      png_warning(png_ptr, "Duplicate bKGD chunk");
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1445 1446 1447
      return;
   }

G
Guy Schalnat 已提交
1448 1449 1450 1451 1452 1453 1454
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      truelen = 1;
   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
      truelen = 6;
   else
      truelen = 2;

A
Andreas Dilger 已提交
1455
   if (length != truelen)
G
Guy Schalnat 已提交
1456
   {
G
Guy Schalnat 已提交
1457
      png_warning(png_ptr, "Incorrect bKGD chunk length");
A
Andreas Dilger 已提交
1458
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1459 1460 1461
      return;
   }

A
Andreas Dilger 已提交
1462
   png_crc_read(png_ptr, buf, truelen);
A
Andreas Dilger 已提交
1463 1464 1465
   if (png_crc_finish(png_ptr, 0))
      return;

G
Guy Schalnat 已提交
1466 1467 1468
   /* We convert the index value into RGB components so that we can allow
    * arbitrary RGB values for background when we have transparency, and
    * so it is easy to determine the RGB values of the background color
1469 1470
    * from the info_ptr struct.
    */
G
Guy Schalnat 已提交
1471
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1472
   {
G
Guy Schalnat 已提交
1473
      png_ptr->background.index = buf[0];
1474
      if (info_ptr && info_ptr->num_palette)
1475
      {
1476 1477 1478 1479 1480 1481
         if (buf[0] >= info_ptr->num_palette)
         {
            png_warning(png_ptr, "Incorrect bKGD chunk index value");
            return;
         }
         png_ptr->background.red =
1482
             (png_uint_16)png_ptr->palette[buf[0]].red;
1483
         png_ptr->background.green =
1484
             (png_uint_16)png_ptr->palette[buf[0]].green;
1485
         png_ptr->background.blue =
1486 1487
             (png_uint_16)png_ptr->palette[buf[0]].blue;
      }
G
Guy Schalnat 已提交
1488
   }
A
Andreas Dilger 已提交
1489
   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
G
Guy Schalnat 已提交
1490 1491 1492 1493
   {
      png_ptr->background.red =
      png_ptr->background.green =
      png_ptr->background.blue =
G
Guy Schalnat 已提交
1494
      png_ptr->background.gray = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1495
   }
G
Guy Schalnat 已提交
1496 1497 1498 1499 1500 1501 1502
   else
   {
      png_ptr->background.red = png_get_uint_16(buf);
      png_ptr->background.green = png_get_uint_16(buf + 2);
      png_ptr->background.blue = png_get_uint_16(buf + 4);
   }

A
Andreas Dilger 已提交
1503
   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
G
Guy Schalnat 已提交
1504
}
G
Guy Schalnat 已提交
1505
#endif
G
Guy Schalnat 已提交
1506

1507
#ifdef PNG_READ_hIST_SUPPORTED
1508
void /* PRIVATE */
A
Andreas Dilger 已提交
1509
png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1510
{
1511
   unsigned int num, i;
1512
   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
G
Guy Schalnat 已提交
1513

1514
   png_debug(1, "in png_handle_hIST");
A
Andreas Dilger 已提交
1515

G
Guy Schalnat 已提交
1516 1517
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before hIST");
A
Andreas Dilger 已提交
1518 1519 1520 1521 1522 1523
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid hIST after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1524 1525 1526
   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
   {
      png_warning(png_ptr, "Missing PLTE before hIST");
A
Andreas Dilger 已提交
1527 1528 1529
      png_crc_finish(png_ptr, length);
      return;
   }
1530
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
A
Andreas Dilger 已提交
1531 1532 1533
   {
      png_warning(png_ptr, "Duplicate hIST chunk");
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1534 1535 1536
      return;
   }

1537
   num = length / 2 ;
1538
   if (num != (unsigned int) png_ptr->num_palette || num >
1539
       (unsigned int) PNG_MAX_PALETTE_LENGTH)
G
Guy Schalnat 已提交
1540 1541
   {
      png_warning(png_ptr, "Incorrect hIST chunk length");
A
Andreas Dilger 已提交
1542
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1543 1544
      return;
   }
G
Guy Schalnat 已提交
1545

G
Guy Schalnat 已提交
1546
   for (i = 0; i < num; i++)
G
Guy Schalnat 已提交
1547 1548 1549 1550
   {
      png_byte buf[2];

      png_crc_read(png_ptr, buf, 2);
1551
      readbuf[i] = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1552
   }
A
Andreas Dilger 已提交
1553 1554 1555 1556

   if (png_crc_finish(png_ptr, 0))
      return;

1557
   png_set_hIST(png_ptr, info_ptr, readbuf);
G
Guy Schalnat 已提交
1558
}
G
Guy Schalnat 已提交
1559
#endif
G
Guy Schalnat 已提交
1560

1561
#ifdef PNG_READ_pHYs_SUPPORTED
1562
void /* PRIVATE */
A
Andreas Dilger 已提交
1563
png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1564 1565 1566 1567 1568
{
   png_byte buf[9];
   png_uint_32 res_x, res_y;
   int unit_type;

1569
   png_debug(1, "in png_handle_pHYs");
A
Andreas Dilger 已提交
1570

G
Guy Schalnat 已提交
1571
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1572
      png_error(png_ptr, "Missing IHDR before pHYs");
A
Andreas Dilger 已提交
1573 1574
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
1575
      png_warning(png_ptr, "Invalid pHYs after IDAT");
A
Andreas Dilger 已提交
1576 1577 1578
      png_crc_finish(png_ptr, length);
      return;
   }
1579
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
A
Andreas Dilger 已提交
1580
   {
1581
      png_warning(png_ptr, "Duplicate pHYs chunk");
A
Andreas Dilger 已提交
1582 1583 1584
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1585

G
Guy Schalnat 已提交
1586 1587
   if (length != 9)
   {
G
Guy Schalnat 已提交
1588
      png_warning(png_ptr, "Incorrect pHYs chunk length");
A
Andreas Dilger 已提交
1589
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1590
      return;
G
Guy Schalnat 已提交
1591
   }
G
Guy Schalnat 已提交
1592 1593

   png_crc_read(png_ptr, buf, 9);
A
Andreas Dilger 已提交
1594 1595
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
1596 1597 1598 1599

   res_x = png_get_uint_32(buf);
   res_y = png_get_uint_32(buf + 4);
   unit_type = buf[8];
A
Andreas Dilger 已提交
1600
   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
G
Guy Schalnat 已提交
1601
}
G
Guy Schalnat 已提交
1602
#endif
G
Guy Schalnat 已提交
1603

1604
#ifdef PNG_READ_oFFs_SUPPORTED
1605
void /* PRIVATE */
A
Andreas Dilger 已提交
1606
png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1607 1608
{
   png_byte buf[9];
1609
   png_int_32 offset_x, offset_y;
G
Guy Schalnat 已提交
1610 1611
   int unit_type;

1612
   png_debug(1, "in png_handle_oFFs");
A
Andreas Dilger 已提交
1613

G
Guy Schalnat 已提交
1614 1615
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before oFFs");
A
Andreas Dilger 已提交
1616 1617 1618 1619 1620 1621
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid oFFs after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1622
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
A
Andreas Dilger 已提交
1623 1624 1625 1626 1627
   {
      png_warning(png_ptr, "Duplicate oFFs chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1628

G
Guy Schalnat 已提交
1629 1630
   if (length != 9)
   {
G
Guy Schalnat 已提交
1631
      png_warning(png_ptr, "Incorrect oFFs chunk length");
A
Andreas Dilger 已提交
1632
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1633 1634 1635
      return;
   }

G
Guy Schalnat 已提交
1636
   png_crc_read(png_ptr, buf, 9);
A
Andreas Dilger 已提交
1637 1638
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
1639

1640 1641
   offset_x = png_get_int_32(buf);
   offset_y = png_get_int_32(buf + 4);
G
Guy Schalnat 已提交
1642
   unit_type = buf[8];
A
Andreas Dilger 已提交
1643 1644 1645 1646
   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
}
#endif

1647
#ifdef PNG_READ_pCAL_SUPPORTED
1648
/* Read the pCAL chunk (described in the PNG Extensions document) */
1649
void /* PRIVATE */
A
Andreas Dilger 已提交
1650 1651 1652 1653 1654 1655
png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
   png_int_32 X0, X1;
   png_byte type, nparams;
   png_charp buf, units, endptr;
   png_charpp params;
1656
   png_size_t slength;
A
Andreas Dilger 已提交
1657 1658
   int i;

1659
   png_debug(1, "in png_handle_pCAL");
A
Andreas Dilger 已提交
1660 1661 1662 1663 1664 1665 1666 1667 1668

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before pCAL");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid pCAL after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1669
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
A
Andreas Dilger 已提交
1670 1671 1672 1673 1674 1675
   {
      png_warning(png_ptr, "Duplicate pCAL chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

1676
   png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
1677
       length + 1);
1678 1679 1680
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (png_ptr->chunkdata == NULL)
1681 1682 1683 1684
   {
      png_warning(png_ptr, "No memory for pCAL purpose");
      return;
   }
1685
   slength = (png_size_t)length;
1686
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
A
Andreas Dilger 已提交
1687 1688 1689

   if (png_crc_finish(png_ptr, 0))
   {
1690 1691
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
1692 1693 1694
      return;
   }

1695
   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
A
Andreas Dilger 已提交
1696

1697
   png_debug(3, "Finding end of pCAL purpose string");
1698
   for (buf = png_ptr->chunkdata; *buf; buf++)
1699
      /* Empty loop */ ;
A
Andreas Dilger 已提交
1700

1701
   endptr = png_ptr->chunkdata + slength;
A
Andreas Dilger 已提交
1702 1703

   /* We need to have at least 12 bytes after the purpose string
1704 1705
    * in order to get the parameter information.
    */
A
Andreas Dilger 已提交
1706 1707 1708
   if (endptr <= buf + 12)
   {
      png_warning(png_ptr, "Invalid pCAL data");
1709 1710
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
1711 1712 1713
      return;
   }

1714
   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
A
Andreas Dilger 已提交
1715 1716 1717 1718 1719 1720
   X0 = png_get_int_32((png_bytep)buf+1);
   X1 = png_get_int_32((png_bytep)buf+5);
   type = buf[9];
   nparams = buf[10];
   units = buf + 11;

1721
   png_debug(3, "Checking pCAL equation type and number of parameters");
A
Andreas Dilger 已提交
1722
   /* Check that we have the right number of parameters for known
1723 1724
    * equation types.
    */
A
Andreas Dilger 已提交
1725 1726 1727 1728 1729 1730
   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
   {
      png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1731 1732
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
1733 1734 1735 1736 1737 1738 1739
      return;
   }
   else if (type >= PNG_EQUATION_LAST)
   {
      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
   }

1740
   for (buf = units; *buf; buf++)
1741
      /* Empty loop to move past the units string. */ ;
A
Andreas Dilger 已提交
1742

1743
   png_debug(3, "Allocating pCAL parameters array");
1744
   params = (png_charpp)png_malloc_warn(png_ptr,
1745
       (png_size_t)(nparams * png_sizeof(png_charp)));
1746
   if (params == NULL)
1747 1748 1749 1750 1751 1752
   {
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      png_warning(png_ptr, "No memory for pCAL params");
      return;
   }
A
Andreas Dilger 已提交
1753 1754

   /* Get pointers to the start of each parameter string. */
1755
   for (i = 0; i < (int)nparams; i++)
A
Andreas Dilger 已提交
1756 1757 1758
   {
      buf++; /* Skip the null string terminator from previous parameter. */

1759
      png_debug1(3, "Reading pCAL parameter %d", i);
1760
      for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1761
         /* Empty loop to move past each parameter string */ ;
A
Andreas Dilger 已提交
1762 1763 1764 1765 1766

      /* Make sure we haven't run out of data yet */
      if (buf > endptr)
      {
         png_warning(png_ptr, "Invalid pCAL data");
1767 1768
         png_free(png_ptr, png_ptr->chunkdata);
         png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
1769 1770 1771 1772 1773
         png_free(png_ptr, params);
         return;
      }
   }

1774
   png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
A
Andreas Dilger 已提交
1775 1776
      units, params);

1777 1778
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
1779
   png_free(png_ptr, params);
G
Guy Schalnat 已提交
1780
}
G
Guy Schalnat 已提交
1781
#endif
G
Guy Schalnat 已提交
1782

1783
#ifdef PNG_READ_sCAL_SUPPORTED
1784
/* Read the sCAL chunk */
1785
void /* PRIVATE */
1786 1787
png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
1788
   png_charp ep;
1789
#ifdef PNG_FLOATING_POINT_SUPPORTED
1790
   double width, height;
1791
   png_charp vp;
1792 1793 1794 1795
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_charp swidth, sheight;
#endif
1796 1797 1798
#endif
   png_size_t slength;

1799
   png_debug(1, "in png_handle_sCAL");
1800 1801 1802 1803 1804 1805 1806 1807 1808

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sCAL");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sCAL after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1809
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1810 1811 1812 1813 1814 1815
   {
      png_warning(png_ptr, "Duplicate sCAL chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

1816
   png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
1817
      length + 1);
1818 1819
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (png_ptr->chunkdata == NULL)
1820 1821 1822 1823
   {
      png_warning(png_ptr, "Out of memory while processing sCAL chunk");
      return;
   }
1824
   slength = (png_size_t)length;
1825
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1826 1827 1828

   if (png_crc_finish(png_ptr, 0))
   {
1829 1830
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1831 1832 1833
      return;
   }

1834
   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
1835

1836
   ep = png_ptr->chunkdata + 1;        /* Skip unit byte */
1837 1838

#ifdef PNG_FLOATING_POINT_SUPPORTED
1839
   width = png_strtod(png_ptr, ep, &vp);
1840
   if (*vp)
1841
   {
1842 1843
      png_warning(png_ptr, "malformed width string in sCAL chunk");
      return;
1844
   }
1845 1846
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
1847 1848
   swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   if (swidth == NULL)
1849 1850 1851 1852 1853
   {
      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
      return;
   }
   png_memcpy(swidth, ep, png_strlen(ep));
1854 1855
#endif
#endif
1856

1857
   for (ep = png_ptr->chunkdata; *ep; ep++)
1858
      /* Empty loop */ ;
1859 1860
   ep++;

1861
   if (png_ptr->chunkdata + slength < ep)
1862 1863 1864 1865 1866 1867
   {
      png_warning(png_ptr, "Truncated sCAL chunk");
#if defined(PNG_FIXED_POINT_SUPPORTED) && \
    !defined(PNG_FLOATING_POINT_SUPPORTED)
      png_free(png_ptr, swidth);
#endif
1868 1869
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1870 1871 1872
      return;
   }

1873
#ifdef PNG_FLOATING_POINT_SUPPORTED
1874
   height = png_strtod(png_ptr, ep, &vp);
1875
   if (*vp)
1876
   {
1877 1878
      png_warning(png_ptr, "malformed height string in sCAL chunk");
      return;
1879
   }
1880 1881
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
1882
   sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1883
   if (sheight == NULL)
1884 1885 1886 1887 1888
   {
      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
      return;
   }
   png_memcpy(sheight, ep, png_strlen(ep));
1889 1890
#endif
#endif
1891

1892
   if (png_ptr->chunkdata + slength < ep
1893
#ifdef PNG_FLOATING_POINT_SUPPORTED
1894
       || width <= 0. || height <= 0.
1895
#endif
1896
       )
1897 1898
   {
      png_warning(png_ptr, "Invalid sCAL data");
1899 1900
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
1901
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1902 1903
      png_free(png_ptr, swidth);
      png_free(png_ptr, sheight);
1904
#endif
1905 1906 1907 1908 1909
      return;
   }


#ifdef PNG_FLOATING_POINT_SUPPORTED
1910
   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
1911
#else
1912
#ifdef PNG_FIXED_POINT_SUPPORTED
1913
   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
1914
#endif
1915 1916
#endif

1917 1918
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
1919 1920 1921 1922
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
   png_free(png_ptr, swidth);
   png_free(png_ptr, sheight);
#endif
1923 1924 1925
}
#endif

1926
#ifdef PNG_READ_tIME_SUPPORTED
1927
void /* PRIVATE */
A
Andreas Dilger 已提交
1928
png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1929 1930 1931 1932
{
   png_byte buf[7];
   png_time mod_time;

1933
   png_debug(1, "in png_handle_tIME");
A
Andreas Dilger 已提交
1934

G
Guy Schalnat 已提交
1935
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
A
Andreas Dilger 已提交
1936
      png_error(png_ptr, "Out of place tIME chunk");
1937
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
A
Andreas Dilger 已提交
1938 1939 1940 1941 1942 1943 1944 1945
   {
      png_warning(png_ptr, "Duplicate tIME chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
1946

G
Guy Schalnat 已提交
1947 1948
   if (length != 7)
   {
G
Guy Schalnat 已提交
1949
      png_warning(png_ptr, "Incorrect tIME chunk length");
A
Andreas Dilger 已提交
1950
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1951 1952 1953 1954
      return;
   }

   png_crc_read(png_ptr, buf, 7);
A
Andreas Dilger 已提交
1955 1956
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
1957 1958 1959 1960 1961 1962

   mod_time.second = buf[6];
   mod_time.minute = buf[5];
   mod_time.hour = buf[4];
   mod_time.day = buf[3];
   mod_time.month = buf[2];
G
Guy Schalnat 已提交
1963
   mod_time.year = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1964

A
Andreas Dilger 已提交
1965
   png_set_tIME(png_ptr, info_ptr, &mod_time);
G
Guy Schalnat 已提交
1966
}
G
Guy Schalnat 已提交
1967
#endif
G
Guy Schalnat 已提交
1968

1969
#ifdef PNG_READ_tEXt_SUPPORTED
A
Andreas Dilger 已提交
1970
/* Note: this does not properly handle chunks that are > 64K under DOS */
1971
void /* PRIVATE */
A
Andreas Dilger 已提交
1972
png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1973
{
A
Andreas Dilger 已提交
1974
   png_textp text_ptr;
G
Guy Schalnat 已提交
1975
   png_charp key;
G
Guy Schalnat 已提交
1976
   png_charp text;
A
Andreas Dilger 已提交
1977
   png_uint_32 skip = 0;
1978
   png_size_t slength;
1979
   int ret;
A
Andreas Dilger 已提交
1980

1981
   png_debug(1, "in png_handle_tEXt");
G
Guy Schalnat 已提交
1982

1983
#ifdef PNG_USER_LIMITS_SUPPORTED
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
   if (png_ptr->user_chunk_cache_max != 0)
   {
      if (png_ptr->user_chunk_cache_max == 1)
      {
         png_crc_finish(png_ptr, length);
         return;
      }
      if (--png_ptr->user_chunk_cache_max == 1)
      {
         png_warning(png_ptr, "No space in chunk cache for tEXt");
         png_crc_finish(png_ptr, length);
         return;
      }
   }
#endif

G
Guy Schalnat 已提交
2000 2001 2002
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before tEXt");

A
Andreas Dilger 已提交
2003 2004 2005
   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;

A
Andreas Dilger 已提交
2006
#ifdef PNG_MAX_MALLOC_64K
2007
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
2008 2009
   {
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
2010 2011
      skip = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
A
Andreas Dilger 已提交
2012 2013 2014
   }
#endif

2015 2016 2017 2018
   png_free(png_ptr, png_ptr->chunkdata);

   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (png_ptr->chunkdata == NULL)
2019
   {
2020
     png_warning(png_ptr, "No memory to process text chunk");
2021 2022
     return;
   }
2023
   slength = (png_size_t)length;
2024
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
A
Andreas Dilger 已提交
2025 2026

   if (png_crc_finish(png_ptr, skip))
A
Andreas Dilger 已提交
2027
   {
2028 2029
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
2030 2031 2032
      return;
   }

2033 2034
   key = png_ptr->chunkdata;

2035
   key[slength] = 0x00;
G
Guy Schalnat 已提交
2036 2037

   for (text = key; *text; text++)
2038
      /* Empty loop to find end of key */ ;
G
Guy Schalnat 已提交
2039

2040
   if (text != key + slength)
G
Guy Schalnat 已提交
2041 2042
      text++;

2043
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
2044
       png_sizeof(png_text));
2045 2046
   if (text_ptr == NULL)
   {
2047 2048 2049 2050
      png_warning(png_ptr, "Not enough memory to process text chunk");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
2051
   }
A
Andreas Dilger 已提交
2052 2053
   text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
   text_ptr->key = key;
2054 2055
   text_ptr->lang = NULL;
   text_ptr->lang_key = NULL;
2056
   text_ptr->itxt_length = 0;
A
Andreas Dilger 已提交
2057
   text_ptr->text = text;
2058
   text_ptr->text_length = png_strlen(text);
A
Andreas Dilger 已提交
2059

2060
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
A
Andreas Dilger 已提交
2061

2062 2063
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
2064
   png_free(png_ptr, text_ptr);
2065
   if (ret)
2066
      png_warning(png_ptr, "Insufficient memory to process text chunk");
G
Guy Schalnat 已提交
2067
}
G
Guy Schalnat 已提交
2068
#endif
G
Guy Schalnat 已提交
2069

2070
#ifdef PNG_READ_zTXt_SUPPORTED
2071
/* Note: this does not correctly handle chunks that are > 64K under DOS */
2072
void /* PRIVATE */
A
Andreas Dilger 已提交
2073
png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
2074
{
A
Andreas Dilger 已提交
2075
   png_textp text_ptr;
G
Guy Schalnat 已提交
2076
   png_charp text;
2077
   int comp_type;
2078
   int ret;
2079
   png_size_t slength, prefix_len, data_len;
A
Andreas Dilger 已提交
2080

2081
   png_debug(1, "in png_handle_zTXt");
2082

2083
#ifdef PNG_USER_LIMITS_SUPPORTED
2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099
   if (png_ptr->user_chunk_cache_max != 0)
   {
      if (png_ptr->user_chunk_cache_max == 1)
      {
         png_crc_finish(png_ptr, length);
         return;
      }
      if (--png_ptr->user_chunk_cache_max == 1)
      {
         png_warning(png_ptr, "No space in chunk cache for zTXt");
         png_crc_finish(png_ptr, length);
         return;
      }
   }
#endif

G
Guy Schalnat 已提交
2100 2101 2102
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before zTXt");

A
Andreas Dilger 已提交
2103 2104 2105
   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;

A
Andreas Dilger 已提交
2106 2107
#ifdef PNG_MAX_MALLOC_64K
   /* We will no doubt have problems with chunks even half this size, but
2108 2109
    * there is no hard and fast rule to tell us where to stop.
    */
2110
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
2111
   {
2112 2113 2114
      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_crc_finish(png_ptr, length);
      return;
A
Andreas Dilger 已提交
2115 2116 2117
   }
#endif

2118
   png_free(png_ptr, png_ptr->chunkdata);
2119 2120
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (png_ptr->chunkdata == NULL)
2121
   {
2122 2123
      png_warning(png_ptr, "Out of memory processing zTXt chunk");
      return;
2124 2125
   }
   slength = (png_size_t)length;
2126
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
A
Andreas Dilger 已提交
2127 2128
   if (png_crc_finish(png_ptr, 0))
   {
2129 2130
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
A
Andreas Dilger 已提交
2131 2132 2133
      return;
   }

2134
   png_ptr->chunkdata[slength] = 0x00;
G
Guy Schalnat 已提交
2135

2136
   for (text = png_ptr->chunkdata; *text; text++)
2137
      /* Empty loop */ ;
G
Guy Schalnat 已提交
2138

2139
   /* zTXt must have some text after the chunkdataword */
2140
   if (text >= png_ptr->chunkdata + slength - 2)
G
Guy Schalnat 已提交
2141
   {
2142
      png_warning(png_ptr, "Truncated zTXt chunk");
2143 2144
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
2145
      return;
G
Guy Schalnat 已提交
2146
   }
2147
   else
G
Guy Schalnat 已提交
2148
   {
2149
       comp_type = *(++text);
2150 2151 2152 2153 2154
       if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
       {
          png_warning(png_ptr, "Unknown compression type in zTXt chunk");
          comp_type = PNG_TEXT_COMPRESSION_zTXt;
       }
2155
       text++;        /* Skip the compression_method byte */
2156
   }
2157
   prefix_len = text - png_ptr->chunkdata;
G
Guy Schalnat 已提交
2158

2159
   png_decompress_chunk(png_ptr, comp_type,
2160
       (png_size_t)length, prefix_len, &data_len);
G
Guy Schalnat 已提交
2161

2162
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
2163
       png_sizeof(png_text));
2164 2165
   if (text_ptr == NULL)
   {
2166 2167 2168 2169
      png_warning(png_ptr, "Not enough memory to process zTXt chunk");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
2170
   }
2171
   text_ptr->compression = comp_type;
2172
   text_ptr->key = png_ptr->chunkdata;
2173 2174 2175
   text_ptr->lang = NULL;
   text_ptr->lang_key = NULL;
   text_ptr->itxt_length = 0;
2176
   text_ptr->text = png_ptr->chunkdata + prefix_len;
2177
   text_ptr->text_length = data_len;
G
Guy Schalnat 已提交
2178

2179
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
G
Guy Schalnat 已提交
2180

2181
   png_free(png_ptr, text_ptr);
2182 2183
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
2184
   if (ret)
2185
      png_error(png_ptr, "Insufficient memory to store zTXt chunk");
2186 2187
}
#endif
G
Guy Schalnat 已提交
2188

2189
#ifdef PNG_READ_iTXt_SUPPORTED
2190
/* Note: this does not correctly handle chunks that are > 64K under DOS */
2191
void /* PRIVATE */
2192 2193 2194
png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
   png_textp text_ptr;
2195
   png_charp key, lang, text, lang_key;
2196
   int comp_flag;
2197
   int comp_type = 0;
2198
   int ret;
2199
   png_size_t slength, prefix_len, data_len;
G
Guy Schalnat 已提交
2200

2201
   png_debug(1, "in png_handle_iTXt");
G
Guy Schalnat 已提交
2202

2203
#ifdef PNG_USER_LIMITS_SUPPORTED
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219
   if (png_ptr->user_chunk_cache_max != 0)
   {
      if (png_ptr->user_chunk_cache_max == 1)
      {
         png_crc_finish(png_ptr, length);
         return;
      }
      if (--png_ptr->user_chunk_cache_max == 1)
      {
         png_warning(png_ptr, "No space in chunk cache for iTXt");
         png_crc_finish(png_ptr, length);
         return;
      }
   }
#endif

2220 2221
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before iTXt");
G
Guy Schalnat 已提交
2222

2223 2224
   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
2225

2226 2227
#ifdef PNG_MAX_MALLOC_64K
   /* We will no doubt have problems with chunks even half this size, but
2228 2229
    * there is no hard and fast rule to tell us where to stop.
    */
2230 2231
   if (length > (png_uint_32)65535L)
   {
2232 2233 2234
      png_warning(png_ptr, "iTXt chunk too large to fit in memory");
      png_crc_finish(png_ptr, length);
      return;
G
Guy Schalnat 已提交
2235
   }
2236 2237
#endif

2238 2239 2240
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (png_ptr->chunkdata == NULL)
2241
   {
2242 2243
      png_warning(png_ptr, "No memory to process iTXt chunk");
      return;
2244
   }
2245
   slength = (png_size_t)length;
2246
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2247
   if (png_crc_finish(png_ptr, 0))
A
Andreas Dilger 已提交
2248
   {
2249 2250
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
2251 2252
      return;
   }
A
Andreas Dilger 已提交
2253

2254
   png_ptr->chunkdata[slength] = 0x00;
A
Andreas Dilger 已提交
2255

2256
   for (lang = png_ptr->chunkdata; *lang; lang++)
2257 2258
      /* Empty loop */ ;
   lang++;        /* Skip NUL separator */
2259

2260
   /* iTXt must have a language tag (possibly empty), two compression bytes,
2261 2262 2263
    * translated keyword (possibly empty), and possibly some text after the
    * keyword
    */
2264

2265
   if (lang >= png_ptr->chunkdata + slength - 3)
2266
   {
2267
      png_warning(png_ptr, "Truncated iTXt chunk");
2268 2269
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
2270
      return;
A
Andreas Dilger 已提交
2271
   }
2272 2273
   else
   {
2274 2275
      comp_flag = *lang++;
      comp_type = *lang++;
2276 2277
   }

2278
   for (lang_key = lang; *lang_key; lang_key++)
2279 2280
      /* Empty loop */ ;
   lang_key++;        /* Skip NUL separator */
2281

2282
   if (lang_key >= png_ptr->chunkdata + slength)
2283 2284
   {
      png_warning(png_ptr, "Truncated iTXt chunk");
2285 2286
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
2287 2288 2289
      return;
   }

2290
   for (text = lang_key; *text; text++)
2291 2292
      /* Empty loop */ ;
   text++;        /* Skip NUL separator */
2293
   if (text >= png_ptr->chunkdata + slength)
2294 2295
   {
      png_warning(png_ptr, "Malformed iTXt chunk");
2296 2297
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
2298 2299
      return;
   }
2300

2301
   prefix_len = text - png_ptr->chunkdata;
2302

2303
   key=png_ptr->chunkdata;
2304
   if (comp_flag)
2305 2306
      png_decompress_chunk(png_ptr, comp_type,
          (size_t)length, prefix_len, &data_len);
2307
   else
2308
      data_len = png_strlen(png_ptr->chunkdata + prefix_len);
2309
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
2310
       png_sizeof(png_text));
2311 2312
   if (text_ptr == NULL)
   {
2313 2314 2315 2316
      png_warning(png_ptr, "Not enough memory to process iTXt chunk");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
2317
   }
2318
   text_ptr->compression = (int)comp_flag + 1;
2319 2320
   text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
   text_ptr->lang = png_ptr->chunkdata + (lang - key);
2321 2322
   text_ptr->itxt_length = data_len;
   text_ptr->text_length = 0;
2323 2324
   text_ptr->key = png_ptr->chunkdata;
   text_ptr->text = png_ptr->chunkdata + prefix_len;
G
Guy Schalnat 已提交
2325

2326
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
A
Andreas Dilger 已提交
2327

2328
   png_free(png_ptr, text_ptr);
2329 2330
   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
2331
   if (ret)
2332
      png_error(png_ptr, "Insufficient memory to store iTXt chunk");
2333 2334 2335
}
#endif

A
Andreas Dilger 已提交
2336
/* This function is called when we haven't found a handler for a
2337 2338 2339 2340 2341
 * chunk.  If there isn't a problem with the chunk itself (ie bad
 * chunk name, CRC, or a critical chunk), the chunk is silently ignored
 * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
 * case it will be saved away to be written out later.
 */
2342
void /* PRIVATE */
A
Andreas Dilger 已提交
2343 2344
png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
2345 2346
   png_uint_32 skip = 0;

2347
   png_debug(1, "in png_handle_unknown");
A
Andreas Dilger 已提交
2348

2349
#ifdef PNG_USER_LIMITS_SUPPORTED
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365
   if (png_ptr->user_chunk_cache_max != 0)
   {
      if (png_ptr->user_chunk_cache_max == 1)
      {
         png_crc_finish(png_ptr, length);
         return;
      }
      if (--png_ptr->user_chunk_cache_max == 1)
      {
         png_warning(png_ptr, "No space in chunk cache for unknown chunk");
         png_crc_finish(png_ptr, length);
         return;
      }
   }
#endif

2366
   if (png_ptr->mode & PNG_HAVE_IDAT)
2367
   {
2368
      PNG_IDAT;
2369
      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* Not an IDAT */
2370 2371
         png_ptr->mode |= PNG_AFTER_IDAT;
   }
2372

A
Andreas Dilger 已提交
2373 2374
   if (!(png_ptr->chunk_name[0] & 0x20))
   {
2375
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2376
      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2377
          PNG_HANDLE_CHUNK_ALWAYS
2378
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2379
          && png_ptr->read_user_chunk_fn == NULL
2380
#endif
2381
          )
2382
#endif
2383
         png_chunk_error(png_ptr, "unknown critical chunk");
A
Andreas Dilger 已提交
2384 2385
   }

2386
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
2387
   if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2388
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2389 2390
       || (png_ptr->read_user_chunk_fn != NULL)
#endif
2391
       )
2392 2393
   {
#ifdef PNG_MAX_MALLOC_64K
2394 2395 2396 2397 2398 2399
      if (length > (png_uint_32)65535L)
      {
         png_warning(png_ptr, "unknown chunk too large to fit in memory");
         skip = length - (png_uint_32)65535L;
         length = (png_uint_32)65535L;
      }
2400
#endif
2401 2402 2403 2404 2405 2406 2407
      png_memcpy((png_charp)png_ptr->unknown_chunk.name,
          (png_charp)png_ptr->chunk_name,
          png_sizeof(png_ptr->unknown_chunk.name));
      png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
          = '\0';
      png_ptr->unknown_chunk.size = (png_size_t)length;
      if (length == 0)
2408
         png_ptr->unknown_chunk.data = NULL;
2409 2410
      else
      {
2411 2412
         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2413
      }
2414
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425
      if (png_ptr->read_user_chunk_fn != NULL)
      {
         /* Callback to user unknown chunk handler */
         int ret;
         ret = (*(png_ptr->read_user_chunk_fn))
             (png_ptr, &png_ptr->unknown_chunk);
         if (ret < 0)
            png_chunk_error(png_ptr, "error in user chunk");
         if (ret == 0)
         {
            if (!(png_ptr->chunk_name[0] & 0x20))
2426
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2427 2428
               if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
                   PNG_HANDLE_CHUNK_ALWAYS)
2429
#endif
2430 2431 2432 2433 2434 2435
                  png_chunk_error(png_ptr, "unknown critical chunk");
            png_set_unknown_chunks(png_ptr, info_ptr,
                &png_ptr->unknown_chunk, 1);
         }
      }
      else
2436
#endif
2437 2438 2439
         png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
      png_free(png_ptr, png_ptr->unknown_chunk.data);
      png_ptr->unknown_chunk.data = NULL;
2440 2441 2442
   }
   else
#endif
2443
      skip = length;
2444

2445
   png_crc_finish(png_ptr, skip);
2446

2447
#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
2448
   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
2449
#endif
A
Andreas Dilger 已提交
2450 2451 2452
}

/* This function is called to verify that a chunk name is valid.
2453 2454 2455 2456 2457
 * This function can't have the "critical chunk check" incorporated
 * into it, since in the future we will need to be able to call user
 * functions to handle unknown critical chunks after we check that
 * the chunk name itself is valid.
 */
A
Andreas Dilger 已提交
2458

2459
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
A
Andreas Dilger 已提交
2460

2461
void /* PRIVATE */
A
Andreas Dilger 已提交
2462 2463
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
{
2464
   png_debug(1, "in png_check_chunk_name");
A
Andreas Dilger 已提交
2465
   if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2466
       isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
A
Andreas Dilger 已提交
2467
   {
2468
      png_chunk_error(png_ptr, "invalid chunk type");
A
Andreas Dilger 已提交
2469 2470 2471
   }
}

2472
/* Combines the row recently read in with the existing pixels in the
2473 2474 2475 2476 2477 2478 2479 2480 2481 2482
 * row.  This routine takes care of alpha and transparency if requested.
 * This routine also handles the two methods of progressive display
 * of interlaced images, depending on the mask value.
 * The mask value describes which pixels are to be combined with
 * the row.  The pattern always repeats every 8 pixels, so just 8
 * bits are needed.  A one indicates the pixel is to be combined,
 * a zero indicates the pixel is to be skipped.  This is in addition
 * to any alpha or transparency value associated with the pixel.  If
 * you want all pixels to be combined, pass 0xff (255) in mask.
 */
2483

2484
void /* PRIVATE */
2485
png_combine_row(png_structp png_ptr, png_bytep row, int mask)
G
Guy Schalnat 已提交
2486
{
2487
   png_debug(1, "in png_combine_row");
G
Guy Schalnat 已提交
2488 2489
   if (mask == 0xff)
   {
G
Guy Schalnat 已提交
2490
      png_memcpy(row, png_ptr->row_buf + 1,
2491
          PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
G
Guy Schalnat 已提交
2492 2493 2494 2495 2496 2497 2498
   }
   else
   {
      switch (png_ptr->row_info.pixel_depth)
      {
         case 1:
         {
2499 2500
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
2501 2502 2503
            int s_inc, s_start, s_end;
            int m = 0x80;
            int shift;
2504
            png_uint_32 i;
2505
            png_uint_32 row_width = png_ptr->width;
G
Guy Schalnat 已提交
2506

2507
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2508
            if (png_ptr->transformations & PNG_PACKSWAP)
2509 2510 2511 2512 2513 2514
            {
                s_start = 0;
                s_end = 7;
                s_inc = 1;
            }
            else
A
Andreas Dilger 已提交
2515 2516
#endif
            {
2517 2518 2519
                s_start = 7;
                s_end = 0;
                s_inc = -1;
A
Andreas Dilger 已提交
2520
            }
2521 2522 2523 2524

            shift = s_start;

            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2525
            {
2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547
               if (m & mask)
               {
                  int value;

                  value = (*sp >> shift) & 0x01;
                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
                  *dp |= (png_byte)(value << shift);
               }

               if (shift == s_end)
               {
                  shift = s_start;
                  sp++;
                  dp++;
               }
               else
                  shift += s_inc;

               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2548 2549 2550 2551 2552
            }
            break;
         }
         case 2:
         {
2553 2554
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
2555
            int s_start, s_end, s_inc;
2556
            int m = 0x80;
2557 2558 2559 2560
            int shift;
            png_uint_32 i;
            png_uint_32 row_width = png_ptr->width;
            int value;
G
Guy Schalnat 已提交
2561

2562
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2563 2564
            if (png_ptr->transformations & PNG_PACKSWAP)
            {
2565 2566 2567
               s_start = 0;
               s_end = 6;
               s_inc = 2;
A
Andreas Dilger 已提交
2568
            }
2569 2570
            else
#endif
A
Andreas Dilger 已提交
2571
            {
2572 2573 2574
               s_start = 6;
               s_end = 0;
               s_inc = -2;
A
Andreas Dilger 已提交
2575
            }
2576 2577 2578 2579

            shift = s_start;

            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2580
            {
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599
               if (m & mask)
               {
                  value = (*sp >> shift) & 0x03;
                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                  *dp |= (png_byte)(value << shift);
               }

               if (shift == s_end)
               {
                  shift = s_start;
                  sp++;
                  dp++;
               }
               else
                  shift += s_inc;
               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2600 2601 2602 2603 2604
            }
            break;
         }
         case 4:
         {
2605 2606
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
2607
            int s_start, s_end, s_inc;
2608
            int m = 0x80;
2609 2610 2611 2612
            int shift;
            png_uint_32 i;
            png_uint_32 row_width = png_ptr->width;
            int value;
G
Guy Schalnat 已提交
2613

2614
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2615 2616
            if (png_ptr->transformations & PNG_PACKSWAP)
            {
2617 2618 2619
               s_start = 0;
               s_end = 4;
               s_inc = 4;
A
Andreas Dilger 已提交
2620
            }
2621 2622
            else
#endif
A
Andreas Dilger 已提交
2623
            {
2624 2625 2626
               s_start = 4;
               s_end = 0;
               s_inc = -4;
A
Andreas Dilger 已提交
2627
            }
2628 2629 2630
            shift = s_start;

            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2631
            {
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
               if (m & mask)
               {
                  value = (*sp >> shift) & 0xf;
                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                  *dp |= (png_byte)(value << shift);
               }

               if (shift == s_end)
               {
                  shift = s_start;
                  sp++;
                  dp++;
               }
               else
                  shift += s_inc;
               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2651 2652 2653 2654 2655
            }
            break;
         }
         default:
         {
2656 2657 2658 2659
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
            png_uint_32 i;
2660 2661 2662
            png_uint_32 row_width = png_ptr->width;
            png_byte m = 0x80;

2663

2664
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2665
            {
2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677
               if (m & mask)
               {
                  png_memcpy(dp, sp, pixel_bytes);
               }

               sp += pixel_bytes;
               dp += pixel_bytes;

               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2678 2679 2680 2681 2682 2683 2684
            }
            break;
         }
      }
   }
}

2685
#ifdef PNG_READ_INTERLACING_SUPPORTED
2686
void /* PRIVATE */
2687
png_do_read_interlace(png_structp png_ptr)
G
Guy Schalnat 已提交
2688
{
2689 2690 2691 2692
   png_row_infop row_info = &(png_ptr->row_info);
   png_bytep row = png_ptr->row_buf + 1;
   int pass = png_ptr->pass;
   png_uint_32 transformations = png_ptr->transformations;
2693 2694
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   /* Offset to next interlace block */
2695
   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2696

2697
   png_debug(1, "in png_do_read_interlace");
2698
   if (row != NULL && row_info != NULL)
G
Guy Schalnat 已提交
2699
   {
2700 2701 2702
      png_uint_32 final_width;

      final_width = row_info->width * png_pass_inc[pass];
G
Guy Schalnat 已提交
2703 2704 2705 2706 2707

      switch (row_info->pixel_depth)
      {
         case 1:
         {
2708 2709
            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2710 2711 2712 2713
            int sshift, dshift;
            int s_start, s_end, s_inc;
            int jstop = png_pass_inc[pass];
            png_byte v;
G
Guy Schalnat 已提交
2714
            png_uint_32 i;
2715
            int j;
G
Guy Schalnat 已提交
2716

2717
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2718 2719
            if (transformations & PNG_PACKSWAP)
            {
2720 2721 2722 2723 2724
                sshift = (int)((row_info->width + 7) & 0x07);
                dshift = (int)((final_width + 7) & 0x07);
                s_start = 7;
                s_end = 0;
                s_inc = -1;
A
Andreas Dilger 已提交
2725
            }
2726
            else
A
Andreas Dilger 已提交
2727
#endif
G
Guy Schalnat 已提交
2728
            {
2729 2730 2731 2732 2733 2734
                sshift = 7 - (int)((row_info->width + 7) & 0x07);
                dshift = 7 - (int)((final_width + 7) & 0x07);
                s_start = 0;
                s_end = 7;
                s_inc = 1;
            }
2735

2736 2737 2738 2739
            for (i = 0; i < row_info->width; i++)
            {
               v = (png_byte)((*sp >> sshift) & 0x01);
               for (j = 0; j < jstop; j++)
G
Guy Schalnat 已提交
2740
               {
2741 2742 2743 2744 2745 2746 2747 2748 2749
                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
                  *dp |= (png_byte)(v << dshift);
                  if (dshift == s_end)
                  {
                     dshift = s_start;
                     dp--;
                  }
                  else
                     dshift += s_inc;
G
Guy Schalnat 已提交
2750
               }
2751
               if (sshift == s_end)
G
Guy Schalnat 已提交
2752
               {
2753
                  sshift = s_start;
G
Guy Schalnat 已提交
2754 2755
                  sp--;
               }
2756 2757
               else
                  sshift += s_inc;
G
Guy Schalnat 已提交
2758 2759 2760 2761 2762
            }
            break;
         }
         case 2:
         {
2763 2764 2765 2766 2767
            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
            int sshift, dshift;
            int s_start, s_end, s_inc;
            int jstop = png_pass_inc[pass];
A
Andreas Dilger 已提交
2768
            png_uint_32 i;
G
Guy Schalnat 已提交
2769

2770
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2771 2772
            if (transformations & PNG_PACKSWAP)
            {
2773 2774 2775 2776 2777
               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
               dshift = (int)(((final_width + 3) & 0x03) << 1);
               s_start = 6;
               s_end = 0;
               s_inc = -2;
A
Andreas Dilger 已提交
2778
            }
2779
            else
A
Andreas Dilger 已提交
2780
#endif
2781 2782 2783 2784 2785 2786 2787
            {
               sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
               dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
               s_start = 0;
               s_end = 6;
               s_inc = 2;
            }
A
Andreas Dilger 已提交
2788

2789
            for (i = 0; i < row_info->width; i++)
G
Guy Schalnat 已提交
2790
            {
2791 2792
               png_byte v;
               int j;
A
Andreas Dilger 已提交
2793

2794 2795
               v = (png_byte)((*sp >> sshift) & 0x03);
               for (j = 0; j < jstop; j++)
G
Guy Schalnat 已提交
2796
               {
2797 2798 2799 2800 2801 2802 2803 2804 2805
                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
                  *dp |= (png_byte)(v << dshift);
                  if (dshift == s_end)
                  {
                     dshift = s_start;
                     dp--;
                  }
                  else
                     dshift += s_inc;
G
Guy Schalnat 已提交
2806
               }
2807
               if (sshift == s_end)
G
Guy Schalnat 已提交
2808
               {
2809
                  sshift = s_start;
G
Guy Schalnat 已提交
2810 2811
                  sp--;
               }
2812 2813
               else
                  sshift += s_inc;
G
Guy Schalnat 已提交
2814 2815 2816 2817 2818
            }
            break;
         }
         case 4:
         {
2819 2820
            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2821 2822
            int sshift, dshift;
            int s_start, s_end, s_inc;
G
Guy Schalnat 已提交
2823
            png_uint_32 i;
2824
            int jstop = png_pass_inc[pass];
G
Guy Schalnat 已提交
2825

2826
#ifdef PNG_READ_PACKSWAP_SUPPORTED
A
Andreas Dilger 已提交
2827 2828
            if (transformations & PNG_PACKSWAP)
            {
2829 2830 2831 2832 2833
               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
               dshift = (int)(((final_width + 1) & 0x01) << 2);
               s_start = 4;
               s_end = 0;
               s_inc = -4;
A
Andreas Dilger 已提交
2834
            }
2835
            else
A
Andreas Dilger 已提交
2836 2837
#endif
            {
2838 2839 2840 2841 2842 2843
               sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
               dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
               s_start = 0;
               s_end = 4;
               s_inc = 4;
            }
A
Andreas Dilger 已提交
2844

2845 2846 2847 2848
            for (i = 0; i < row_info->width; i++)
            {
               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
               int j;
A
Andreas Dilger 已提交
2849

2850
               for (j = 0; j < jstop; j++)
G
Guy Schalnat 已提交
2851
               {
2852 2853 2854 2855 2856 2857 2858 2859 2860
                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
                  *dp |= (png_byte)(v << dshift);
                  if (dshift == s_end)
                  {
                     dshift = s_start;
                     dp--;
                  }
                  else
                     dshift += s_inc;
G
Guy Schalnat 已提交
2861
               }
2862
               if (sshift == s_end)
G
Guy Schalnat 已提交
2863
               {
2864
                  sshift = s_start;
G
Guy Schalnat 已提交
2865 2866
                  sp--;
               }
2867 2868
               else
                  sshift += s_inc;
G
Guy Schalnat 已提交
2869 2870 2871 2872 2873
            }
            break;
         }
         default:
         {
2874
            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2875 2876
            png_bytep sp = row + (png_size_t)(row_info->width - 1)
                * pixel_bytes;
2877 2878 2879
            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;

            int jstop = png_pass_inc[pass];
A
Andreas Dilger 已提交
2880
            png_uint_32 i;
G
Guy Schalnat 已提交
2881

2882
            for (i = 0; i < row_info->width; i++)
G
Guy Schalnat 已提交
2883
            {
2884 2885 2886 2887 2888 2889 2890 2891 2892 2893
               png_byte v[8];
               int j;

               png_memcpy(v, sp, pixel_bytes);
               for (j = 0; j < jstop; j++)
               {
                  png_memcpy(dp, v, pixel_bytes);
                  dp -= pixel_bytes;
               }
               sp -= pixel_bytes;
G
Guy Schalnat 已提交
2894 2895 2896 2897 2898
            }
            break;
         }
      }
      row_info->width = final_width;
2899
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
G
Guy Schalnat 已提交
2900
   }
2901
#ifndef PNG_READ_PACKSWAP_SUPPORTED
2902
   transformations = transformations; /* Silence compiler warning */
2903
#endif
G
Guy Schalnat 已提交
2904
}
2905
#endif /* PNG_READ_INTERLACING_SUPPORTED */
G
Guy Schalnat 已提交
2906

2907
void /* PRIVATE */
2908
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2909
    png_bytep prev_row, int filter)
2910
{
2911
   png_debug(1, "in png_read_filter_row");
2912
   png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter);
2913 2914 2915 2916 2917 2918
   switch (filter)
   {
      case PNG_FILTER_VALUE_NONE:
         break;
      case PNG_FILTER_VALUE_SUB:
      {
2919 2920
         png_uint_32 i;
         png_uint_32 istop = row_info->rowbytes;
2921
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2922 2923
         png_bytep rp = row + bpp;
         png_bytep lp = row;
2924

2925
         for (i = bpp; i < istop; i++)
2926
         {
2927 2928
            *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
            rp++;
2929 2930 2931 2932 2933
         }
         break;
      }
      case PNG_FILTER_VALUE_UP:
      {
2934 2935 2936 2937
         png_uint_32 i;
         png_uint_32 istop = row_info->rowbytes;
         png_bytep rp = row;
         png_bytep pp = prev_row;
2938

2939
         for (i = 0; i < istop; i++)
2940
         {
2941 2942
            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
            rp++;
2943 2944 2945 2946 2947
         }
         break;
      }
      case PNG_FILTER_VALUE_AVG:
      {
2948 2949 2950 2951
         png_uint_32 i;
         png_bytep rp = row;
         png_bytep pp = prev_row;
         png_bytep lp = row;
2952
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2953
         png_uint_32 istop = row_info->rowbytes - bpp;
2954

2955
         for (i = 0; i < bpp; i++)
2956
         {
2957
            *rp = (png_byte)(((int)(*rp) +
2958
                ((int)(*pp++) / 2 )) & 0xff);
2959
            rp++;
2960
         }
2961

2962
         for (i = 0; i < istop; i++)
2963
         {
2964
            *rp = (png_byte)(((int)(*rp) +
2965
                (int)(*pp++ + *lp++) / 2 ) & 0xff);
2966
            rp++;
2967 2968 2969 2970 2971
         }
         break;
      }
      case PNG_FILTER_VALUE_PAETH:
      {
2972 2973 2974 2975 2976
         png_uint_32 i;
         png_bytep rp = row;
         png_bytep pp = prev_row;
         png_bytep lp = row;
         png_bytep cp = prev_row;
2977
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2978
         png_uint_32 istop=row_info->rowbytes - bpp;
2979 2980

         for (i = 0; i < bpp; i++)
2981
         {
2982 2983
            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
            rp++;
2984 2985
         }

2986
         for (i = 0; i < istop; i++)   /* Use leftover rp,pp */
2987 2988 2989
         {
            int a, b, c, pa, pb, pc, p;

2990 2991 2992 2993 2994 2995
            a = *lp++;
            b = *pp++;
            c = *cp++;

            p = b - c;
            pc = a - c;
2996 2997

#ifdef PNG_USE_ABS
2998 2999 3000
            pa = abs(p);
            pb = abs(pc);
            pc = abs(p + pc);
3001
#else
3002 3003 3004
            pa = p < 0 ? -p : p;
            pb = pc < 0 ? -pc : pc;
            pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015
#endif

            /*
               if (pa <= pb && pa <= pc)
                  p = a;
               else if (pb <= pc)
                  p = b;
               else
                  p = c;
             */

3016
            p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
3017

3018 3019
            *rp = (png_byte)(((int)(*rp) + p) & 0xff);
            rp++;
3020 3021 3022 3023
         }
         break;
      }
      default:
3024
         png_warning(png_ptr, "Ignoring bad adaptive filter type");
3025
         *row = 0;
3026 3027 3028
         break;
   }
}
G
Guy Schalnat 已提交
3029

3030
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
3031
void /* PRIVATE */
G
Guy Schalnat 已提交
3032
png_read_finish_row(png_structp png_ptr)
G
Guy Schalnat 已提交
3033
{
3034
#ifdef PNG_READ_INTERLACING_SUPPORTED
3035
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3036

3037
   /* Start of interlace block */
3038
   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3039

3040
   /* Offset to next interlace block */
3041
   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3042

3043
   /* Start of interlace block in the y direction */
3044
   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3045

3046
   /* Offset to next interlace block in the y direction */
3047 3048
   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif /* PNG_READ_INTERLACING_SUPPORTED */
3049

3050
   png_debug(1, "in png_read_finish_row");
G
Guy Schalnat 已提交
3051 3052 3053 3054
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
      return;

3055
#ifdef PNG_READ_INTERLACING_SUPPORTED
G
Guy Schalnat 已提交
3056 3057 3058
   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
3059
      png_memset(png_ptr->prev_row, 0,
3060
          png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
3061 3062 3063 3064 3065 3066 3067 3068 3069
      do
      {
         png_ptr->pass++;
         if (png_ptr->pass >= 7)
            break;
         png_ptr->iwidth = (png_ptr->width +
            png_pass_inc[png_ptr->pass] - 1 -
            png_pass_start[png_ptr->pass]) /
            png_pass_inc[png_ptr->pass];
3070

G
Guy Schalnat 已提交
3071 3072 3073
         if (!(png_ptr->transformations & PNG_INTERLACE))
         {
            png_ptr->num_rows = (png_ptr->height +
3074 3075 3076
                png_pass_yinc[png_ptr->pass] - 1 -
                png_pass_ystart[png_ptr->pass]) /
                png_pass_yinc[png_ptr->pass];
G
Guy Schalnat 已提交
3077 3078 3079
            if (!(png_ptr->num_rows))
               continue;
         }
3080
         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
G
Guy Schalnat 已提交
3081
            break;
G
Guy Schalnat 已提交
3082 3083 3084 3085 3086
      } while (png_ptr->iwidth == 0);

      if (png_ptr->pass < 7)
         return;
   }
3087
#endif /* PNG_READ_INTERLACING_SUPPORTED */
G
Guy Schalnat 已提交
3088

G
Guy Schalnat 已提交
3089
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
3090
   {
3091
      PNG_IDAT;
G
Guy Schalnat 已提交
3092 3093 3094
      char extra;
      int ret;

A
Andreas Dilger 已提交
3095 3096
      png_ptr->zstream.next_out = (Byte *)&extra;
      png_ptr->zstream.avail_out = (uInt)1;
3097
      for (;;)
G
Guy Schalnat 已提交
3098
      {
A
Andreas Dilger 已提交
3099
         if (!(png_ptr->zstream.avail_in))
G
Guy Schalnat 已提交
3100 3101 3102
         {
            while (!png_ptr->idat_size)
            {
A
Andreas Dilger 已提交
3103
               png_byte chunk_length[4];
G
Guy Schalnat 已提交
3104

A
Andreas Dilger 已提交
3105
               png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
3106

A
Andreas Dilger 已提交
3107
               png_read_data(png_ptr, chunk_length, 4);
3108
               png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
A
Andreas Dilger 已提交
3109 3110
               png_reset_crc(png_ptr);
               png_crc_read(png_ptr, png_ptr->chunk_name, 4);
3111
               if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
3112
                  png_error(png_ptr, "Not enough image data");
G
Guy Schalnat 已提交
3113 3114

            }
A
Andreas Dilger 已提交
3115 3116
            png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
            png_ptr->zstream.next_in = png_ptr->zbuf;
G
Guy Schalnat 已提交
3117
            if (png_ptr->zbuf_size > png_ptr->idat_size)
A
Andreas Dilger 已提交
3118 3119 3120
               png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
            png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
            png_ptr->idat_size -= png_ptr->zstream.avail_in;
G
Guy Schalnat 已提交
3121
         }
A
Andreas Dilger 已提交
3122
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
3123 3124
         if (ret == Z_STREAM_END)
         {
A
Andreas Dilger 已提交
3125
            if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3126
                png_ptr->idat_size)
3127
               png_warning(png_ptr, "Extra compressed data");
A
Andreas Dilger 已提交
3128 3129
            png_ptr->mode |= PNG_AFTER_IDAT;
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
G
Guy Schalnat 已提交
3130 3131 3132
            break;
         }
         if (ret != Z_OK)
3133
            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3134
                "Decompression Error");
G
Guy Schalnat 已提交
3135

A
Andreas Dilger 已提交
3136
         if (!(png_ptr->zstream.avail_out))
3137
         {
3138
            png_warning(png_ptr, "Extra compressed data");
3139 3140 3141 3142
            png_ptr->mode |= PNG_AFTER_IDAT;
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
            break;
         }
G
Guy Schalnat 已提交
3143

3144
      }
A
Andreas Dilger 已提交
3145
      png_ptr->zstream.avail_out = 0;
G
Guy Schalnat 已提交
3146 3147
   }

A
Andreas Dilger 已提交
3148
   if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3149
      png_warning(png_ptr, "Extra compression data");
G
Guy Schalnat 已提交
3150

A
Andreas Dilger 已提交
3151
   inflateReset(&png_ptr->zstream);
G
Guy Schalnat 已提交
3152

A
Andreas Dilger 已提交
3153
   png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
3154
}
3155
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
3156

3157
void /* PRIVATE */
G
Guy Schalnat 已提交
3158
png_read_start_row(png_structp png_ptr)
G
Guy Schalnat 已提交
3159
{
3160
#ifdef PNG_READ_INTERLACING_SUPPORTED
3161
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3162

3163
   /* Start of interlace block */
3164
   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3165

3166
   /* Offset to next interlace block */
3167
   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3168

3169
   /* Start of interlace block in the y direction */
3170
   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3171

3172
   /* Offset to next interlace block in the y direction */
3173
   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3174
#endif
3175

G
Guy Schalnat 已提交
3176
   int max_pixel_depth;
3177
   png_size_t row_bytes;
G
Guy Schalnat 已提交
3178

3179
   png_debug(1, "in png_read_start_row");
A
Andreas Dilger 已提交
3180
   png_ptr->zstream.avail_in = 0;
G
Guy Schalnat 已提交
3181
   png_init_read_transformations(png_ptr);
3182
#ifdef PNG_READ_INTERLACING_SUPPORTED
G
Guy Schalnat 已提交
3183 3184 3185 3186
   if (png_ptr->interlaced)
   {
      if (!(png_ptr->transformations & PNG_INTERLACE))
         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3187
             png_pass_ystart[0]) / png_pass_yinc[0];
G
Guy Schalnat 已提交
3188 3189 3190 3191
      else
         png_ptr->num_rows = png_ptr->height;

      png_ptr->iwidth = (png_ptr->width +
3192 3193 3194
          png_pass_inc[png_ptr->pass] - 1 -
          png_pass_start[png_ptr->pass]) /
          png_pass_inc[png_ptr->pass];
G
Guy Schalnat 已提交
3195 3196
   }
   else
3197
#endif /* PNG_READ_INTERLACING_SUPPORTED */
G
Guy Schalnat 已提交
3198 3199 3200 3201 3202 3203
   {
      png_ptr->num_rows = png_ptr->height;
      png_ptr->iwidth = png_ptr->width;
   }
   max_pixel_depth = png_ptr->pixel_depth;

3204
#ifdef PNG_READ_PACK_SUPPORTED
G
Guy Schalnat 已提交
3205 3206
   if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
      max_pixel_depth = 8;
G
Guy Schalnat 已提交
3207
#endif
G
Guy Schalnat 已提交
3208

3209
#ifdef PNG_READ_EXPAND_SUPPORTED
G
Guy Schalnat 已提交
3210
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234
   {
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         if (png_ptr->num_trans)
            max_pixel_depth = 32;
         else
            max_pixel_depth = 24;
      }
      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (max_pixel_depth < 8)
            max_pixel_depth = 8;
         if (png_ptr->num_trans)
            max_pixel_depth *= 2;
      }
      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
      {
         if (png_ptr->num_trans)
         {
            max_pixel_depth *= 4;
            max_pixel_depth /= 3;
         }
      }
   }
G
Guy Schalnat 已提交
3235
#endif
G
Guy Schalnat 已提交
3236

3237
#ifdef PNG_READ_FILLER_SUPPORTED
G
Guy Schalnat 已提交
3238
   if (png_ptr->transformations & (PNG_FILLER))
G
Guy Schalnat 已提交
3239
   {
3240 3241 3242
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
         max_pixel_depth = 32;
      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255
      {
         if (max_pixel_depth <= 8)
            max_pixel_depth = 16;
         else
            max_pixel_depth = 32;
      }
      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
      {
         if (max_pixel_depth <= 32)
            max_pixel_depth = 32;
         else
            max_pixel_depth = 64;
      }
G
Guy Schalnat 已提交
3256
   }
G
Guy Schalnat 已提交
3257
#endif
G
Guy Schalnat 已提交
3258

3259
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
G
Guy Schalnat 已提交
3260 3261
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
   {
3262
      if (
3263
#ifdef PNG_READ_EXPAND_SUPPORTED
3264
          (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3265
#endif
3266
#ifdef PNG_READ_FILLER_SUPPORTED
3267
          (png_ptr->transformations & (PNG_FILLER)) ||
3268
#endif
3269
          png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
G
Guy Schalnat 已提交
3270 3271 3272
      {
         if (max_pixel_depth <= 16)
            max_pixel_depth = 32;
3273
         else
G
Guy Schalnat 已提交
3274 3275 3276 3277 3278
            max_pixel_depth = 64;
      }
      else
      {
         if (max_pixel_depth <= 8)
3279 3280
         {
            if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3281
               max_pixel_depth = 32;
3282
            else
3283
               max_pixel_depth = 24;
3284
         }
3285 3286
         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            max_pixel_depth = 64;
3287
         else
G
Guy Schalnat 已提交
3288 3289 3290
            max_pixel_depth = 48;
      }
   }
G
Guy Schalnat 已提交
3291
#endif
G
Guy Schalnat 已提交
3292

3293 3294
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3295
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
3296 3297
   {
      int user_pixel_depth = png_ptr->user_transform_depth*
3298
         png_ptr->user_transform_channels;
3299
      if (user_pixel_depth > max_pixel_depth)
3300
         max_pixel_depth=user_pixel_depth;
3301
   }
3302 3303
#endif

3304 3305 3306
   /* Align the width on the next larger 8 pixels.  Mainly used
    * for interlacing
    */
3307
   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3308 3309 3310
   /* Calculate the maximum bytes needed, adding a byte and a pixel
    * for safety's sake
    */
3311
   row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
3312
       1 + ((max_pixel_depth + 7) >> 3);
G
Guy Schalnat 已提交
3313
#ifdef PNG_MAX_MALLOC_64K
3314
   if (row_bytes > (png_uint_32)65536L)
G
Guy Schalnat 已提交
3315
      png_error(png_ptr, "This image requires a row greater than 64KB");
G
Guy Schalnat 已提交
3316
#endif
3317

3318
   if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
3319 3320
   {
     png_free(png_ptr, png_ptr->big_row_buf);
3321
     if (png_ptr->interlaced)
3322 3323 3324 3325 3326
        png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
            row_bytes + 48);
     else
        png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
            row_bytes + 48);
3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337
     png_ptr->old_big_row_buf_size = row_bytes + 48;

#ifdef PNG_ALIGNED_MEMORY_SUPPORTED
     /* Use 16-byte aligned memory for row_buf with at least 16 bytes
      * of padding before and after row_buf.
      */
     png_ptr->row_buf = png_ptr->big_row_buf + 32
         - (((png_alloc_size_t)&(png_ptr->big_row_buf[0]) + 15) % 16);
     png_ptr->old_big_row_buf_size = row_bytes + 48;
#else
     /* Use 32 bytes of padding before and 16 bytes after row_buf. */
3338
     png_ptr->row_buf = png_ptr->big_row_buf + 32;
3339 3340
#endif
     png_ptr->old_big_row_buf_size = row_bytes + 48;
3341
   }
G
Guy Schalnat 已提交
3342 3343

#ifdef PNG_MAX_MALLOC_64K
3344
   if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
G
Guy Schalnat 已提交
3345
      png_error(png_ptr, "This image requires a row greater than 64KB");
G
Guy Schalnat 已提交
3346
#endif
3347
   if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
3348
      png_error(png_ptr, "Row has too many bytes to allocate in memory");
3349

3350
   if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size)
3351
   {
3352 3353
      png_free(png_ptr, png_ptr->prev_row);
      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3354
          png_ptr->rowbytes + 1));
3355
      png_ptr->old_prev_row_size = png_ptr->rowbytes + 1;
3356
   }
A
Andreas Dilger 已提交
3357

3358
   png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
3359

3360 3361 3362 3363 3364 3365
   png_debug1(3, "width = %u,", png_ptr->width);
   png_debug1(3, "height = %u,", png_ptr->height);
   png_debug1(3, "iwidth = %u,", png_ptr->iwidth);
   png_debug1(3, "num_rows = %u,", png_ptr->num_rows);
   png_debug1(3, "rowbytes = %u,", png_ptr->rowbytes);
   png_debug1(3, "irowbytes = %u",
3366
       PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
G
Guy Schalnat 已提交
3367

G
Guy Schalnat 已提交
3368
   png_ptr->flags |= PNG_FLAG_ROW_INIT;
G
Guy Schalnat 已提交
3369
}
3370
#endif /* PNG_READ_SUPPORTED */