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