media/libpng/pngpread.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1
michael@0 2 /* pngpread.c - read a png file in push mode
michael@0 3 *
michael@0 4 * Last changed in libpng 1.6.10 [March 6, 2014]
michael@0 5 * Copyright (c) 1998-2014 Glenn Randers-Pehrson
michael@0 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
michael@0 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
michael@0 8 *
michael@0 9 * This code is released under the libpng license.
michael@0 10 * For conditions of distribution and use, see the disclaimer
michael@0 11 * and license in png.h
michael@0 12 */
michael@0 13
michael@0 14 #include "pngpriv.h"
michael@0 15
michael@0 16 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
michael@0 17
michael@0 18 /* Push model modes */
michael@0 19 #define PNG_READ_SIG_MODE 0
michael@0 20 #define PNG_READ_CHUNK_MODE 1
michael@0 21 #define PNG_READ_IDAT_MODE 2
michael@0 22 #define PNG_SKIP_MODE 3
michael@0 23 #define PNG_READ_tEXt_MODE 4
michael@0 24 #define PNG_READ_zTXt_MODE 5
michael@0 25 #define PNG_READ_DONE_MODE 6
michael@0 26 #define PNG_READ_iTXt_MODE 7
michael@0 27 #define PNG_ERROR_MODE 8
michael@0 28
michael@0 29 void PNGAPI
michael@0 30 png_process_data(png_structrp png_ptr, png_inforp info_ptr,
michael@0 31 png_bytep buffer, png_size_t buffer_size)
michael@0 32 {
michael@0 33 if (png_ptr == NULL || info_ptr == NULL)
michael@0 34 return;
michael@0 35
michael@0 36 png_push_restore_buffer(png_ptr, buffer, buffer_size);
michael@0 37
michael@0 38 while (png_ptr->buffer_size)
michael@0 39 {
michael@0 40 png_process_some_data(png_ptr, info_ptr);
michael@0 41 }
michael@0 42 }
michael@0 43
michael@0 44 png_size_t PNGAPI
michael@0 45 png_process_data_pause(png_structrp png_ptr, int save)
michael@0 46 {
michael@0 47 if (png_ptr != NULL)
michael@0 48 {
michael@0 49 /* It's easiest for the caller if we do the save, then the caller doesn't
michael@0 50 * have to supply the same data again:
michael@0 51 */
michael@0 52 if (save)
michael@0 53 png_push_save_buffer(png_ptr);
michael@0 54 else
michael@0 55 {
michael@0 56 /* This includes any pending saved bytes: */
michael@0 57 png_size_t remaining = png_ptr->buffer_size;
michael@0 58 png_ptr->buffer_size = 0;
michael@0 59
michael@0 60 /* So subtract the saved buffer size, unless all the data
michael@0 61 * is actually 'saved', in which case we just return 0
michael@0 62 */
michael@0 63 if (png_ptr->save_buffer_size < remaining)
michael@0 64 return remaining - png_ptr->save_buffer_size;
michael@0 65 }
michael@0 66 }
michael@0 67
michael@0 68 return 0;
michael@0 69 }
michael@0 70
michael@0 71 png_uint_32 PNGAPI
michael@0 72 png_process_data_skip(png_structrp png_ptr)
michael@0 73 {
michael@0 74 png_uint_32 remaining = 0;
michael@0 75
michael@0 76 if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE &&
michael@0 77 png_ptr->skip_length > 0)
michael@0 78 {
michael@0 79 /* At the end of png_process_data the buffer size must be 0 (see the loop
michael@0 80 * above) so we can detect a broken call here:
michael@0 81 */
michael@0 82 if (png_ptr->buffer_size != 0)
michael@0 83 png_error(png_ptr,
michael@0 84 "png_process_data_skip called inside png_process_data");
michael@0 85
michael@0 86 /* If is impossible for there to be a saved buffer at this point -
michael@0 87 * otherwise we could not be in SKIP mode. This will also happen if
michael@0 88 * png_process_skip is called inside png_process_data (but only very
michael@0 89 * rarely.)
michael@0 90 */
michael@0 91 if (png_ptr->save_buffer_size != 0)
michael@0 92 png_error(png_ptr, "png_process_data_skip called with saved data");
michael@0 93
michael@0 94 remaining = png_ptr->skip_length;
michael@0 95 png_ptr->skip_length = 0;
michael@0 96 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
michael@0 97 }
michael@0 98
michael@0 99 return remaining;
michael@0 100 }
michael@0 101
michael@0 102 /* What we do with the incoming data depends on what we were previously
michael@0 103 * doing before we ran out of data...
michael@0 104 */
michael@0 105 void /* PRIVATE */
michael@0 106 png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
michael@0 107 {
michael@0 108 if (png_ptr == NULL)
michael@0 109 return;
michael@0 110
michael@0 111 switch (png_ptr->process_mode)
michael@0 112 {
michael@0 113 case PNG_READ_SIG_MODE:
michael@0 114 {
michael@0 115 png_push_read_sig(png_ptr, info_ptr);
michael@0 116 break;
michael@0 117 }
michael@0 118
michael@0 119 case PNG_READ_CHUNK_MODE:
michael@0 120 {
michael@0 121 png_push_read_chunk(png_ptr, info_ptr);
michael@0 122 break;
michael@0 123 }
michael@0 124
michael@0 125 case PNG_READ_IDAT_MODE:
michael@0 126 {
michael@0 127 png_push_read_IDAT(png_ptr);
michael@0 128 break;
michael@0 129 }
michael@0 130
michael@0 131 case PNG_SKIP_MODE:
michael@0 132 {
michael@0 133 png_push_crc_finish(png_ptr);
michael@0 134 break;
michael@0 135 }
michael@0 136
michael@0 137 default:
michael@0 138 {
michael@0 139 png_ptr->buffer_size = 0;
michael@0 140 break;
michael@0 141 }
michael@0 142 }
michael@0 143 }
michael@0 144
michael@0 145 /* Read any remaining signature bytes from the stream and compare them with
michael@0 146 * the correct PNG signature. It is possible that this routine is called
michael@0 147 * with bytes already read from the signature, either because they have been
michael@0 148 * checked by the calling application, or because of multiple calls to this
michael@0 149 * routine.
michael@0 150 */
michael@0 151 void /* PRIVATE */
michael@0 152 png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
michael@0 153 {
michael@0 154 png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
michael@0 155 num_to_check = 8 - num_checked;
michael@0 156
michael@0 157 if (png_ptr->buffer_size < num_to_check)
michael@0 158 {
michael@0 159 num_to_check = png_ptr->buffer_size;
michael@0 160 }
michael@0 161
michael@0 162 png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
michael@0 163 num_to_check);
michael@0 164 png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
michael@0 165
michael@0 166 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
michael@0 167 {
michael@0 168 if (num_checked < 4 &&
michael@0 169 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
michael@0 170 png_error(png_ptr, "Not a PNG file");
michael@0 171
michael@0 172 else
michael@0 173 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
michael@0 174 }
michael@0 175 else
michael@0 176 {
michael@0 177 if (png_ptr->sig_bytes >= 8)
michael@0 178 {
michael@0 179 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
michael@0 180 }
michael@0 181 }
michael@0 182 }
michael@0 183
michael@0 184 void /* PRIVATE */
michael@0 185 png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
michael@0 186 {
michael@0 187 png_uint_32 chunk_name;
michael@0 188 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
michael@0 189 int keep; /* unknown handling method */
michael@0 190 #endif
michael@0 191
michael@0 192 /* First we make sure we have enough data for the 4 byte chunk name
michael@0 193 * and the 4 byte chunk length before proceeding with decoding the
michael@0 194 * chunk data. To fully decode each of these chunks, we also make
michael@0 195 * sure we have enough data in the buffer for the 4 byte CRC at the
michael@0 196 * end of every chunk (except IDAT, which is handled separately).
michael@0 197 */
michael@0 198 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
michael@0 199 {
michael@0 200 png_byte chunk_length[4];
michael@0 201 png_byte chunk_tag[4];
michael@0 202
michael@0 203 if (png_ptr->buffer_size < 8)
michael@0 204 {
michael@0 205 png_push_save_buffer(png_ptr);
michael@0 206 return;
michael@0 207 }
michael@0 208
michael@0 209 png_push_fill_buffer(png_ptr, chunk_length, 4);
michael@0 210 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
michael@0 211 png_reset_crc(png_ptr);
michael@0 212 png_crc_read(png_ptr, chunk_tag, 4);
michael@0 213 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
michael@0 214 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
michael@0 215 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
michael@0 216 }
michael@0 217
michael@0 218 chunk_name = png_ptr->chunk_name;
michael@0 219
michael@0 220 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 221 if (png_ptr->num_frames_read > 0 &&
michael@0 222 png_ptr->num_frames_read < info_ptr->num_frames)
michael@0 223 {
michael@0 224 if (chunk_name == png_IDAT)
michael@0 225 {
michael@0 226 /* Discard trailing IDATs for the first frame */
michael@0 227 if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
michael@0 228 png_error(png_ptr, "out of place IDAT");
michael@0 229
michael@0 230 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 231 {
michael@0 232 png_push_save_buffer(png_ptr);
michael@0 233 return;
michael@0 234 }
michael@0 235
michael@0 236 png_push_crc_skip(png_ptr, png_ptr->push_length);
michael@0 237 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 238 return;
michael@0 239 }
michael@0 240 else if (chunk_name == png_fdAT)
michael@0 241 {
michael@0 242 if (png_ptr->buffer_size < 4)
michael@0 243 {
michael@0 244 png_push_save_buffer(png_ptr);
michael@0 245 return;
michael@0 246 }
michael@0 247
michael@0 248 png_ensure_sequence_number(png_ptr, 4);
michael@0 249
michael@0 250 if (!(png_ptr->mode & PNG_HAVE_fcTL))
michael@0 251 {
michael@0 252 /* Discard trailing fdATs for frames other than the first */
michael@0 253 if (png_ptr->num_frames_read < 2)
michael@0 254 png_error(png_ptr, "out of place fdAT");
michael@0 255
michael@0 256 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 257 {
michael@0 258 png_push_save_buffer(png_ptr);
michael@0 259 return;
michael@0 260 }
michael@0 261
michael@0 262 png_push_crc_skip(png_ptr, png_ptr->push_length);
michael@0 263 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 264 return;
michael@0 265 }
michael@0 266
michael@0 267 else
michael@0 268 {
michael@0 269 /* frame data follows */
michael@0 270 png_ptr->idat_size = png_ptr->push_length - 4;
michael@0 271 png_ptr->mode |= PNG_HAVE_IDAT;
michael@0 272 png_ptr->process_mode = PNG_READ_IDAT_MODE;
michael@0 273
michael@0 274 return;
michael@0 275 }
michael@0 276 }
michael@0 277
michael@0 278 else if (chunk_name == png_fcTL)
michael@0 279 {
michael@0 280 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 281 {
michael@0 282 png_push_save_buffer(png_ptr);
michael@0 283 return;
michael@0 284 }
michael@0 285
michael@0 286 png_read_reset(png_ptr);
michael@0 287 png_ptr->mode &= ~PNG_HAVE_fcTL;
michael@0 288
michael@0 289 png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
michael@0 290
michael@0 291 if (!(png_ptr->mode & PNG_HAVE_fcTL))
michael@0 292 png_error(png_ptr, "missing required fcTL chunk");
michael@0 293
michael@0 294 png_read_reinit(png_ptr, info_ptr);
michael@0 295 png_progressive_read_reset(png_ptr);
michael@0 296
michael@0 297 if (png_ptr->frame_info_fn != NULL)
michael@0 298 (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
michael@0 299
michael@0 300 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 301
michael@0 302 return;
michael@0 303 }
michael@0 304
michael@0 305 else
michael@0 306 {
michael@0 307 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 308 {
michael@0 309 png_push_save_buffer(png_ptr);
michael@0 310 return;
michael@0 311 }
michael@0 312 png_warning(png_ptr, "Skipped (ignored) a chunk "
michael@0 313 "between APNG chunks");
michael@0 314 png_push_crc_skip(png_ptr, png_ptr->push_length);
michael@0 315 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 316 return;
michael@0 317 }
michael@0 318
michael@0 319 return;
michael@0 320 }
michael@0 321 #endif /* PNG_READ_APNG_SUPPORTED */
michael@0 322
michael@0 323 if (chunk_name == png_IDAT)
michael@0 324 {
michael@0 325 if (png_ptr->mode & PNG_AFTER_IDAT)
michael@0 326 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
michael@0 327
michael@0 328 /* If we reach an IDAT chunk, this means we have read all of the
michael@0 329 * header chunks, and we can start reading the image (or if this
michael@0 330 * is called after the image has been read - we have an error).
michael@0 331 */
michael@0 332 if (!(png_ptr->mode & PNG_HAVE_IHDR))
michael@0 333 png_error(png_ptr, "Missing IHDR before IDAT");
michael@0 334
michael@0 335 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
michael@0 336 !(png_ptr->mode & PNG_HAVE_PLTE))
michael@0 337 png_error(png_ptr, "Missing PLTE before IDAT");
michael@0 338
michael@0 339 png_ptr->mode |= PNG_HAVE_IDAT;
michael@0 340 png_ptr->process_mode = PNG_READ_IDAT_MODE;
michael@0 341
michael@0 342 if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
michael@0 343 if (png_ptr->push_length == 0)
michael@0 344 return;
michael@0 345
michael@0 346 if (png_ptr->mode & PNG_AFTER_IDAT)
michael@0 347 png_benign_error(png_ptr, "Too many IDATs found");
michael@0 348 }
michael@0 349
michael@0 350 if (chunk_name == png_IHDR)
michael@0 351 {
michael@0 352 if (png_ptr->push_length != 13)
michael@0 353 png_error(png_ptr, "Invalid IHDR length");
michael@0 354
michael@0 355 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 356 {
michael@0 357 png_push_save_buffer(png_ptr);
michael@0 358 return;
michael@0 359 }
michael@0 360
michael@0 361 png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
michael@0 362 }
michael@0 363
michael@0 364 else if (chunk_name == png_IEND)
michael@0 365 {
michael@0 366 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 367 {
michael@0 368 png_push_save_buffer(png_ptr);
michael@0 369 return;
michael@0 370 }
michael@0 371
michael@0 372 png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
michael@0 373
michael@0 374 png_ptr->process_mode = PNG_READ_DONE_MODE;
michael@0 375 png_push_have_end(png_ptr, info_ptr);
michael@0 376 }
michael@0 377
michael@0 378 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
michael@0 379 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
michael@0 380 {
michael@0 381 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 382 {
michael@0 383 png_push_save_buffer(png_ptr);
michael@0 384 return;
michael@0 385 }
michael@0 386
michael@0 387 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
michael@0 388
michael@0 389 if (chunk_name == png_PLTE)
michael@0 390 png_ptr->mode |= PNG_HAVE_PLTE;
michael@0 391 }
michael@0 392 #endif
michael@0 393
michael@0 394 else if (chunk_name == png_PLTE)
michael@0 395 {
michael@0 396 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 397 {
michael@0 398 png_push_save_buffer(png_ptr);
michael@0 399 return;
michael@0 400 }
michael@0 401 png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
michael@0 402 }
michael@0 403
michael@0 404 else if (chunk_name == png_IDAT)
michael@0 405 {
michael@0 406 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 407 png_have_info(png_ptr, info_ptr);
michael@0 408 #endif
michael@0 409 png_ptr->idat_size = png_ptr->push_length;
michael@0 410 png_ptr->process_mode = PNG_READ_IDAT_MODE;
michael@0 411 png_push_have_info(png_ptr, info_ptr);
michael@0 412 png_ptr->zstream.avail_out =
michael@0 413 (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
michael@0 414 png_ptr->iwidth) + 1;
michael@0 415 png_ptr->zstream.next_out = png_ptr->row_buf;
michael@0 416 return;
michael@0 417 }
michael@0 418
michael@0 419 #ifdef PNG_READ_gAMA_SUPPORTED
michael@0 420 else if (png_ptr->chunk_name == png_gAMA)
michael@0 421 {
michael@0 422 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 423 {
michael@0 424 png_push_save_buffer(png_ptr);
michael@0 425 return;
michael@0 426 }
michael@0 427
michael@0 428 png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
michael@0 429 }
michael@0 430
michael@0 431 #endif
michael@0 432 #ifdef PNG_READ_sBIT_SUPPORTED
michael@0 433 else if (png_ptr->chunk_name == png_sBIT)
michael@0 434 {
michael@0 435 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 436 {
michael@0 437 png_push_save_buffer(png_ptr);
michael@0 438 return;
michael@0 439 }
michael@0 440
michael@0 441 png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
michael@0 442 }
michael@0 443
michael@0 444 #endif
michael@0 445 #ifdef PNG_READ_cHRM_SUPPORTED
michael@0 446 else if (png_ptr->chunk_name == png_cHRM)
michael@0 447 {
michael@0 448 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 449 {
michael@0 450 png_push_save_buffer(png_ptr);
michael@0 451 return;
michael@0 452 }
michael@0 453
michael@0 454 png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
michael@0 455 }
michael@0 456
michael@0 457 #endif
michael@0 458 #ifdef PNG_READ_sRGB_SUPPORTED
michael@0 459 else if (chunk_name == png_sRGB)
michael@0 460 {
michael@0 461 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 462 {
michael@0 463 png_push_save_buffer(png_ptr);
michael@0 464 return;
michael@0 465 }
michael@0 466
michael@0 467 png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
michael@0 468 }
michael@0 469
michael@0 470 #endif
michael@0 471 #ifdef PNG_READ_iCCP_SUPPORTED
michael@0 472 else if (png_ptr->chunk_name == png_iCCP)
michael@0 473 {
michael@0 474 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 475 {
michael@0 476 png_push_save_buffer(png_ptr);
michael@0 477 return;
michael@0 478 }
michael@0 479
michael@0 480 png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
michael@0 481 }
michael@0 482
michael@0 483 #endif
michael@0 484 #ifdef PNG_READ_sPLT_SUPPORTED
michael@0 485 else if (chunk_name == png_sPLT)
michael@0 486 {
michael@0 487 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 488 {
michael@0 489 png_push_save_buffer(png_ptr);
michael@0 490 return;
michael@0 491 }
michael@0 492
michael@0 493 png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
michael@0 494 }
michael@0 495
michael@0 496 #endif
michael@0 497 #ifdef PNG_READ_tRNS_SUPPORTED
michael@0 498 else if (chunk_name == png_tRNS)
michael@0 499 {
michael@0 500 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 501 {
michael@0 502 png_push_save_buffer(png_ptr);
michael@0 503 return;
michael@0 504 }
michael@0 505
michael@0 506 png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
michael@0 507 }
michael@0 508
michael@0 509 #endif
michael@0 510 #ifdef PNG_READ_bKGD_SUPPORTED
michael@0 511 else if (chunk_name == png_bKGD)
michael@0 512 {
michael@0 513 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 514 {
michael@0 515 png_push_save_buffer(png_ptr);
michael@0 516 return;
michael@0 517 }
michael@0 518
michael@0 519 png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
michael@0 520 }
michael@0 521
michael@0 522 #endif
michael@0 523 #ifdef PNG_READ_hIST_SUPPORTED
michael@0 524 else if (chunk_name == png_hIST)
michael@0 525 {
michael@0 526 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 527 {
michael@0 528 png_push_save_buffer(png_ptr);
michael@0 529 return;
michael@0 530 }
michael@0 531
michael@0 532 png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
michael@0 533 }
michael@0 534
michael@0 535 #endif
michael@0 536 #ifdef PNG_READ_pHYs_SUPPORTED
michael@0 537 else if (chunk_name == png_pHYs)
michael@0 538 {
michael@0 539 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 540 {
michael@0 541 png_push_save_buffer(png_ptr);
michael@0 542 return;
michael@0 543 }
michael@0 544
michael@0 545 png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
michael@0 546 }
michael@0 547
michael@0 548 #endif
michael@0 549 #ifdef PNG_READ_oFFs_SUPPORTED
michael@0 550 else if (chunk_name == png_oFFs)
michael@0 551 {
michael@0 552 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 553 {
michael@0 554 png_push_save_buffer(png_ptr);
michael@0 555 return;
michael@0 556 }
michael@0 557
michael@0 558 png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
michael@0 559 }
michael@0 560 #endif
michael@0 561
michael@0 562 #ifdef PNG_READ_pCAL_SUPPORTED
michael@0 563 else if (chunk_name == png_pCAL)
michael@0 564 {
michael@0 565 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 566 {
michael@0 567 png_push_save_buffer(png_ptr);
michael@0 568 return;
michael@0 569 }
michael@0 570
michael@0 571 png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
michael@0 572 }
michael@0 573
michael@0 574 #endif
michael@0 575 #ifdef PNG_READ_sCAL_SUPPORTED
michael@0 576 else if (chunk_name == png_sCAL)
michael@0 577 {
michael@0 578 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 579 {
michael@0 580 png_push_save_buffer(png_ptr);
michael@0 581 return;
michael@0 582 }
michael@0 583
michael@0 584 png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
michael@0 585 }
michael@0 586
michael@0 587 #endif
michael@0 588 #ifdef PNG_READ_tIME_SUPPORTED
michael@0 589 else if (chunk_name == png_tIME)
michael@0 590 {
michael@0 591 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 592 {
michael@0 593 png_push_save_buffer(png_ptr);
michael@0 594 return;
michael@0 595 }
michael@0 596
michael@0 597 png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
michael@0 598 }
michael@0 599
michael@0 600 #endif
michael@0 601 #ifdef PNG_READ_tEXt_SUPPORTED
michael@0 602 else if (chunk_name == png_tEXt)
michael@0 603 {
michael@0 604 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 605 {
michael@0 606 png_push_save_buffer(png_ptr);
michael@0 607 return;
michael@0 608 }
michael@0 609
michael@0 610 png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
michael@0 611 }
michael@0 612
michael@0 613 #endif
michael@0 614 #ifdef PNG_READ_zTXt_SUPPORTED
michael@0 615 else if (chunk_name == png_zTXt)
michael@0 616 {
michael@0 617 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 618 {
michael@0 619 png_push_save_buffer(png_ptr);
michael@0 620 return;
michael@0 621 }
michael@0 622
michael@0 623 png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
michael@0 624 }
michael@0 625
michael@0 626 #endif
michael@0 627 #ifdef PNG_READ_iTXt_SUPPORTED
michael@0 628 else if (chunk_name == png_iTXt)
michael@0 629 {
michael@0 630 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 631 {
michael@0 632 png_push_save_buffer(png_ptr);
michael@0 633 return;
michael@0 634 }
michael@0 635
michael@0 636 png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
michael@0 637 }
michael@0 638 #endif
michael@0 639
michael@0 640 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 641 else if (chunk_name == png_acTL)
michael@0 642 {
michael@0 643 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 644 {
michael@0 645 png_push_save_buffer(png_ptr);
michael@0 646 return;
michael@0 647 }
michael@0 648
michael@0 649 png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
michael@0 650 }
michael@0 651
michael@0 652 else if (chunk_name == png_fcTL)
michael@0 653 {
michael@0 654 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 655 {
michael@0 656 png_push_save_buffer(png_ptr);
michael@0 657 return;
michael@0 658 }
michael@0 659
michael@0 660 png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
michael@0 661 }
michael@0 662
michael@0 663 #endif /* PNG_READ_APNG_SUPPORTED */
michael@0 664 else
michael@0 665 {
michael@0 666 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 667 {
michael@0 668 png_push_save_buffer(png_ptr);
michael@0 669 return;
michael@0 670 }
michael@0 671 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
michael@0 672 PNG_HANDLE_CHUNK_AS_DEFAULT);
michael@0 673 }
michael@0 674
michael@0 675 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 676 }
michael@0 677
michael@0 678 void /* PRIVATE */
michael@0 679 png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip)
michael@0 680 {
michael@0 681 png_ptr->process_mode = PNG_SKIP_MODE;
michael@0 682 png_ptr->skip_length = skip;
michael@0 683 }
michael@0 684
michael@0 685 void /* PRIVATE */
michael@0 686 png_push_crc_finish(png_structrp png_ptr)
michael@0 687 {
michael@0 688 if (png_ptr->skip_length && png_ptr->save_buffer_size)
michael@0 689 {
michael@0 690 png_size_t save_size = png_ptr->save_buffer_size;
michael@0 691 png_uint_32 skip_length = png_ptr->skip_length;
michael@0 692
michael@0 693 /* We want the smaller of 'skip_length' and 'save_buffer_size', but
michael@0 694 * they are of different types and we don't know which variable has the
michael@0 695 * fewest bits. Carefully select the smaller and cast it to the type of
michael@0 696 * the larger - this cannot overflow. Do not cast in the following test
michael@0 697 * - it will break on either 16 or 64 bit platforms.
michael@0 698 */
michael@0 699 if (skip_length < save_size)
michael@0 700 save_size = (png_size_t)skip_length;
michael@0 701
michael@0 702 else
michael@0 703 skip_length = (png_uint_32)save_size;
michael@0 704
michael@0 705 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
michael@0 706
michael@0 707 png_ptr->skip_length -= skip_length;
michael@0 708 png_ptr->buffer_size -= save_size;
michael@0 709 png_ptr->save_buffer_size -= save_size;
michael@0 710 png_ptr->save_buffer_ptr += save_size;
michael@0 711 }
michael@0 712 if (png_ptr->skip_length && png_ptr->current_buffer_size)
michael@0 713 {
michael@0 714 png_size_t save_size = png_ptr->current_buffer_size;
michael@0 715 png_uint_32 skip_length = png_ptr->skip_length;
michael@0 716
michael@0 717 /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
michael@0 718 * the same problem exists as above and the same solution.
michael@0 719 */
michael@0 720 if (skip_length < save_size)
michael@0 721 save_size = (png_size_t)skip_length;
michael@0 722
michael@0 723 else
michael@0 724 skip_length = (png_uint_32)save_size;
michael@0 725
michael@0 726 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
michael@0 727
michael@0 728 png_ptr->skip_length -= skip_length;
michael@0 729 png_ptr->buffer_size -= save_size;
michael@0 730 png_ptr->current_buffer_size -= save_size;
michael@0 731 png_ptr->current_buffer_ptr += save_size;
michael@0 732 }
michael@0 733 if (!png_ptr->skip_length)
michael@0 734 {
michael@0 735 if (png_ptr->buffer_size < 4)
michael@0 736 {
michael@0 737 png_push_save_buffer(png_ptr);
michael@0 738 return;
michael@0 739 }
michael@0 740
michael@0 741 png_crc_finish(png_ptr, 0);
michael@0 742 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
michael@0 743 }
michael@0 744 }
michael@0 745
michael@0 746 void PNGCBAPI
michael@0 747 png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
michael@0 748 {
michael@0 749 png_bytep ptr;
michael@0 750
michael@0 751 if (png_ptr == NULL)
michael@0 752 return;
michael@0 753
michael@0 754 ptr = buffer;
michael@0 755 if (png_ptr->save_buffer_size)
michael@0 756 {
michael@0 757 png_size_t save_size;
michael@0 758
michael@0 759 if (length < png_ptr->save_buffer_size)
michael@0 760 save_size = length;
michael@0 761
michael@0 762 else
michael@0 763 save_size = png_ptr->save_buffer_size;
michael@0 764
michael@0 765 memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
michael@0 766 length -= save_size;
michael@0 767 ptr += save_size;
michael@0 768 png_ptr->buffer_size -= save_size;
michael@0 769 png_ptr->save_buffer_size -= save_size;
michael@0 770 png_ptr->save_buffer_ptr += save_size;
michael@0 771 }
michael@0 772 if (length && png_ptr->current_buffer_size)
michael@0 773 {
michael@0 774 png_size_t save_size;
michael@0 775
michael@0 776 if (length < png_ptr->current_buffer_size)
michael@0 777 save_size = length;
michael@0 778
michael@0 779 else
michael@0 780 save_size = png_ptr->current_buffer_size;
michael@0 781
michael@0 782 memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
michael@0 783 png_ptr->buffer_size -= save_size;
michael@0 784 png_ptr->current_buffer_size -= save_size;
michael@0 785 png_ptr->current_buffer_ptr += save_size;
michael@0 786 }
michael@0 787 }
michael@0 788
michael@0 789 void /* PRIVATE */
michael@0 790 png_push_save_buffer(png_structrp png_ptr)
michael@0 791 {
michael@0 792 if (png_ptr->save_buffer_size)
michael@0 793 {
michael@0 794 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
michael@0 795 {
michael@0 796 png_size_t i, istop;
michael@0 797 png_bytep sp;
michael@0 798 png_bytep dp;
michael@0 799
michael@0 800 istop = png_ptr->save_buffer_size;
michael@0 801 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
michael@0 802 i < istop; i++, sp++, dp++)
michael@0 803 {
michael@0 804 *dp = *sp;
michael@0 805 }
michael@0 806 }
michael@0 807 }
michael@0 808 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
michael@0 809 png_ptr->save_buffer_max)
michael@0 810 {
michael@0 811 png_size_t new_max;
michael@0 812 png_bytep old_buffer;
michael@0 813
michael@0 814 if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
michael@0 815 (png_ptr->current_buffer_size + 256))
michael@0 816 {
michael@0 817 png_error(png_ptr, "Potential overflow of save_buffer");
michael@0 818 }
michael@0 819
michael@0 820 new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
michael@0 821 old_buffer = png_ptr->save_buffer;
michael@0 822 png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
michael@0 823 (png_size_t)new_max);
michael@0 824
michael@0 825 if (png_ptr->save_buffer == NULL)
michael@0 826 {
michael@0 827 png_free(png_ptr, old_buffer);
michael@0 828 png_error(png_ptr, "Insufficient memory for save_buffer");
michael@0 829 }
michael@0 830
michael@0 831 memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
michael@0 832 png_free(png_ptr, old_buffer);
michael@0 833 png_ptr->save_buffer_max = new_max;
michael@0 834 }
michael@0 835 if (png_ptr->current_buffer_size)
michael@0 836 {
michael@0 837 memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
michael@0 838 png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
michael@0 839 png_ptr->save_buffer_size += png_ptr->current_buffer_size;
michael@0 840 png_ptr->current_buffer_size = 0;
michael@0 841 }
michael@0 842 png_ptr->save_buffer_ptr = png_ptr->save_buffer;
michael@0 843 png_ptr->buffer_size = 0;
michael@0 844 }
michael@0 845
michael@0 846 void /* PRIVATE */
michael@0 847 png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
michael@0 848 png_size_t buffer_length)
michael@0 849 {
michael@0 850 png_ptr->current_buffer = buffer;
michael@0 851 png_ptr->current_buffer_size = buffer_length;
michael@0 852 png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
michael@0 853 png_ptr->current_buffer_ptr = png_ptr->current_buffer;
michael@0 854 }
michael@0 855
michael@0 856 void /* PRIVATE */
michael@0 857 png_push_read_IDAT(png_structrp png_ptr)
michael@0 858 {
michael@0 859 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
michael@0 860 {
michael@0 861 png_byte chunk_length[4];
michael@0 862 png_byte chunk_tag[4];
michael@0 863
michael@0 864 /* TODO: this code can be commoned up with the same code in push_read */
michael@0 865 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 866 if (png_ptr->buffer_size < 12)
michael@0 867 #else
michael@0 868 if (png_ptr->buffer_size < 8)
michael@0 869 #endif
michael@0 870 {
michael@0 871 png_push_save_buffer(png_ptr);
michael@0 872 return;
michael@0 873 }
michael@0 874
michael@0 875 png_push_fill_buffer(png_ptr, chunk_length, 4);
michael@0 876 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
michael@0 877 png_reset_crc(png_ptr);
michael@0 878 png_crc_read(png_ptr, chunk_tag, 4);
michael@0 879 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
michael@0 880 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
michael@0 881
michael@0 882 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 883 if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
michael@0 884 {
michael@0 885 if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
michael@0 886 {
michael@0 887 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
michael@0 888 if (png_ptr->frame_end_fn != NULL)
michael@0 889 (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
michael@0 890 png_ptr->num_frames_read++;
michael@0 891 return;
michael@0 892 }
michael@0 893 else
michael@0 894 {
michael@0 895 if (png_ptr->chunk_name == png_IEND)
michael@0 896 png_error(png_ptr, "Not enough image data");
michael@0 897 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
michael@0 898 {
michael@0 899 png_push_save_buffer(png_ptr);
michael@0 900 return;
michael@0 901 }
michael@0 902 png_warning(png_ptr, "Skipping (ignoring) a chunk between "
michael@0 903 "APNG chunks");
michael@0 904 png_crc_finish(png_ptr, png_ptr->push_length);
michael@0 905 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 906 return;
michael@0 907 }
michael@0 908 }
michael@0 909 else
michael@0 910 #endif
michael@0 911 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 912 if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
michael@0 913 #else
michael@0 914 if (png_ptr->chunk_name != png_IDAT)
michael@0 915 #endif
michael@0 916 {
michael@0 917 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
michael@0 918
michael@0 919 if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
michael@0 920 png_error(png_ptr, "Not enough compressed data");
michael@0 921
michael@0 922 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 923 if (png_ptr->frame_end_fn != NULL)
michael@0 924 (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
michael@0 925 png_ptr->num_frames_read++;
michael@0 926 #endif
michael@0 927
michael@0 928 return;
michael@0 929 }
michael@0 930
michael@0 931 png_ptr->idat_size = png_ptr->push_length;
michael@0 932
michael@0 933 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 934 if (png_ptr->num_frames_read > 0)
michael@0 935 {
michael@0 936 png_ensure_sequence_number(png_ptr, 4);
michael@0 937 png_ptr->idat_size -= 4;
michael@0 938 }
michael@0 939 #endif
michael@0 940 }
michael@0 941
michael@0 942 if (png_ptr->idat_size && png_ptr->save_buffer_size)
michael@0 943 {
michael@0 944 png_size_t save_size = png_ptr->save_buffer_size;
michael@0 945 png_uint_32 idat_size = png_ptr->idat_size;
michael@0 946
michael@0 947 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
michael@0 948 * are of different types and we don't know which variable has the fewest
michael@0 949 * bits. Carefully select the smaller and cast it to the type of the
michael@0 950 * larger - this cannot overflow. Do not cast in the following test - it
michael@0 951 * will break on either 16 or 64 bit platforms.
michael@0 952 */
michael@0 953 if (idat_size < save_size)
michael@0 954 save_size = (png_size_t)idat_size;
michael@0 955
michael@0 956 else
michael@0 957 idat_size = (png_uint_32)save_size;
michael@0 958
michael@0 959 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
michael@0 960
michael@0 961 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
michael@0 962
michael@0 963 png_ptr->idat_size -= idat_size;
michael@0 964 png_ptr->buffer_size -= save_size;
michael@0 965 png_ptr->save_buffer_size -= save_size;
michael@0 966 png_ptr->save_buffer_ptr += save_size;
michael@0 967 }
michael@0 968
michael@0 969 if (png_ptr->idat_size && png_ptr->current_buffer_size)
michael@0 970 {
michael@0 971 png_size_t save_size = png_ptr->current_buffer_size;
michael@0 972 png_uint_32 idat_size = png_ptr->idat_size;
michael@0 973
michael@0 974 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
michael@0 975 * are of different types and we don't know which variable has the fewest
michael@0 976 * bits. Carefully select the smaller and cast it to the type of the
michael@0 977 * larger - this cannot overflow.
michael@0 978 */
michael@0 979 if (idat_size < save_size)
michael@0 980 save_size = (png_size_t)idat_size;
michael@0 981
michael@0 982 else
michael@0 983 idat_size = (png_uint_32)save_size;
michael@0 984
michael@0 985 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
michael@0 986
michael@0 987 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
michael@0 988
michael@0 989 png_ptr->idat_size -= idat_size;
michael@0 990 png_ptr->buffer_size -= save_size;
michael@0 991 png_ptr->current_buffer_size -= save_size;
michael@0 992 png_ptr->current_buffer_ptr += save_size;
michael@0 993 }
michael@0 994 if (!png_ptr->idat_size)
michael@0 995 {
michael@0 996 if (png_ptr->buffer_size < 4)
michael@0 997 {
michael@0 998 png_push_save_buffer(png_ptr);
michael@0 999 return;
michael@0 1000 }
michael@0 1001
michael@0 1002 png_crc_finish(png_ptr, 0);
michael@0 1003 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
michael@0 1004 png_ptr->mode |= PNG_AFTER_IDAT;
michael@0 1005 png_ptr->zowner = 0;
michael@0 1006 }
michael@0 1007 }
michael@0 1008
michael@0 1009 void /* PRIVATE */
michael@0 1010 png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
michael@0 1011 png_size_t buffer_length)
michael@0 1012 {
michael@0 1013 /* The caller checks for a non-zero buffer length. */
michael@0 1014 if (!(buffer_length > 0) || buffer == NULL)
michael@0 1015 png_error(png_ptr, "No IDAT data (internal error)");
michael@0 1016
michael@0 1017 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 1018 /* If the app is not APNG-aware, decode only the first frame */
michael@0 1019 if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
michael@0 1020 {
michael@0 1021 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
michael@0 1022 return;
michael@0 1023 }
michael@0 1024 #endif
michael@0 1025
michael@0 1026 /* This routine must process all the data it has been given
michael@0 1027 * before returning, calling the row callback as required to
michael@0 1028 * handle the uncompressed results.
michael@0 1029 */
michael@0 1030 png_ptr->zstream.next_in = buffer;
michael@0 1031 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
michael@0 1032 png_ptr->zstream.avail_in = (uInt)buffer_length;
michael@0 1033
michael@0 1034 /* Keep going until the decompressed data is all processed
michael@0 1035 * or the stream marked as finished.
michael@0 1036 */
michael@0 1037 while (png_ptr->zstream.avail_in > 0 &&
michael@0 1038 !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
michael@0 1039 {
michael@0 1040 int ret;
michael@0 1041
michael@0 1042 /* We have data for zlib, but we must check that zlib
michael@0 1043 * has someplace to put the results. It doesn't matter
michael@0 1044 * if we don't expect any results -- it may be the input
michael@0 1045 * data is just the LZ end code.
michael@0 1046 */
michael@0 1047 if (!(png_ptr->zstream.avail_out > 0))
michael@0 1048 {
michael@0 1049 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
michael@0 1050 png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
michael@0 1051 png_ptr->iwidth) + 1);
michael@0 1052
michael@0 1053 png_ptr->zstream.next_out = png_ptr->row_buf;
michael@0 1054 }
michael@0 1055
michael@0 1056 /* Using Z_SYNC_FLUSH here means that an unterminated
michael@0 1057 * LZ stream (a stream with a missing end code) can still
michael@0 1058 * be handled, otherwise (Z_NO_FLUSH) a future zlib
michael@0 1059 * implementation might defer output and therefore
michael@0 1060 * change the current behavior (see comments in inflate.c
michael@0 1061 * for why this doesn't happen at present with zlib 1.2.5).
michael@0 1062 */
michael@0 1063 ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
michael@0 1064
michael@0 1065 /* Check for any failure before proceeding. */
michael@0 1066 if (ret != Z_OK && ret != Z_STREAM_END)
michael@0 1067 {
michael@0 1068 /* Terminate the decompression. */
michael@0 1069 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
michael@0 1070 png_ptr->zowner = 0;
michael@0 1071
michael@0 1072 /* This may be a truncated stream (missing or
michael@0 1073 * damaged end code). Treat that as a warning.
michael@0 1074 */
michael@0 1075 if (png_ptr->row_number >= png_ptr->num_rows ||
michael@0 1076 png_ptr->pass > 6)
michael@0 1077 png_warning(png_ptr, "Truncated compressed data in IDAT");
michael@0 1078
michael@0 1079 else
michael@0 1080 png_error(png_ptr, "Decompression error in IDAT");
michael@0 1081
michael@0 1082 /* Skip the check on unprocessed input */
michael@0 1083 return;
michael@0 1084 }
michael@0 1085
michael@0 1086 /* Did inflate output any data? */
michael@0 1087 if (png_ptr->zstream.next_out != png_ptr->row_buf)
michael@0 1088 {
michael@0 1089 /* Is this unexpected data after the last row?
michael@0 1090 * If it is, artificially terminate the LZ output
michael@0 1091 * here.
michael@0 1092 */
michael@0 1093 if (png_ptr->row_number >= png_ptr->num_rows ||
michael@0 1094 png_ptr->pass > 6)
michael@0 1095 {
michael@0 1096 /* Extra data. */
michael@0 1097 png_warning(png_ptr, "Extra compressed data in IDAT");
michael@0 1098 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
michael@0 1099 png_ptr->zowner = 0;
michael@0 1100
michael@0 1101 /* Do no more processing; skip the unprocessed
michael@0 1102 * input check below.
michael@0 1103 */
michael@0 1104 return;
michael@0 1105 }
michael@0 1106
michael@0 1107 /* Do we have a complete row? */
michael@0 1108 if (png_ptr->zstream.avail_out == 0)
michael@0 1109 png_push_process_row(png_ptr);
michael@0 1110 }
michael@0 1111
michael@0 1112 /* And check for the end of the stream. */
michael@0 1113 if (ret == Z_STREAM_END)
michael@0 1114 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
michael@0 1115 }
michael@0 1116
michael@0 1117 /* All the data should have been processed, if anything
michael@0 1118 * is left at this point we have bytes of IDAT data
michael@0 1119 * after the zlib end code.
michael@0 1120 */
michael@0 1121 if (png_ptr->zstream.avail_in > 0)
michael@0 1122 png_warning(png_ptr, "Extra compression data in IDAT");
michael@0 1123 }
michael@0 1124
michael@0 1125 void /* PRIVATE */
michael@0 1126 png_push_process_row(png_structrp png_ptr)
michael@0 1127 {
michael@0 1128 /* 1.5.6: row_info moved out of png_struct to a local here. */
michael@0 1129 png_row_info row_info;
michael@0 1130
michael@0 1131 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
michael@0 1132 row_info.color_type = png_ptr->color_type;
michael@0 1133 row_info.bit_depth = png_ptr->bit_depth;
michael@0 1134 row_info.channels = png_ptr->channels;
michael@0 1135 row_info.pixel_depth = png_ptr->pixel_depth;
michael@0 1136 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
michael@0 1137
michael@0 1138 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
michael@0 1139 {
michael@0 1140 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
michael@0 1141 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
michael@0 1142 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
michael@0 1143 else
michael@0 1144 png_error(png_ptr, "bad adaptive filter value");
michael@0 1145 }
michael@0 1146
michael@0 1147 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
michael@0 1148 * 1.5.6, while the buffer really is this big in current versions of libpng
michael@0 1149 * it may not be in the future, so this was changed just to copy the
michael@0 1150 * interlaced row count:
michael@0 1151 */
michael@0 1152 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
michael@0 1153
michael@0 1154 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
michael@0 1155 if (png_ptr->transformations)
michael@0 1156 png_do_read_transformations(png_ptr, &row_info);
michael@0 1157 #endif
michael@0 1158
michael@0 1159 /* The transformed pixel depth should match the depth now in row_info. */
michael@0 1160 if (png_ptr->transformed_pixel_depth == 0)
michael@0 1161 {
michael@0 1162 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
michael@0 1163 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
michael@0 1164 png_error(png_ptr, "progressive row overflow");
michael@0 1165 }
michael@0 1166
michael@0 1167 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
michael@0 1168 png_error(png_ptr, "internal progressive row size calculation error");
michael@0 1169
michael@0 1170
michael@0 1171 #ifdef PNG_READ_INTERLACING_SUPPORTED
michael@0 1172 /* Blow up interlaced rows to full size */
michael@0 1173 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
michael@0 1174 {
michael@0 1175 if (png_ptr->pass < 6)
michael@0 1176 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
michael@0 1177 png_ptr->transformations);
michael@0 1178
michael@0 1179 switch (png_ptr->pass)
michael@0 1180 {
michael@0 1181 case 0:
michael@0 1182 {
michael@0 1183 int i;
michael@0 1184 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
michael@0 1185 {
michael@0 1186 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1187 png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
michael@0 1188 }
michael@0 1189
michael@0 1190 if (png_ptr->pass == 2) /* Pass 1 might be empty */
michael@0 1191 {
michael@0 1192 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
michael@0 1193 {
michael@0 1194 png_push_have_row(png_ptr, NULL);
michael@0 1195 png_read_push_finish_row(png_ptr);
michael@0 1196 }
michael@0 1197 }
michael@0 1198
michael@0 1199 if (png_ptr->pass == 4 && png_ptr->height <= 4)
michael@0 1200 {
michael@0 1201 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
michael@0 1202 {
michael@0 1203 png_push_have_row(png_ptr, NULL);
michael@0 1204 png_read_push_finish_row(png_ptr);
michael@0 1205 }
michael@0 1206 }
michael@0 1207
michael@0 1208 if (png_ptr->pass == 6 && png_ptr->height <= 4)
michael@0 1209 {
michael@0 1210 png_push_have_row(png_ptr, NULL);
michael@0 1211 png_read_push_finish_row(png_ptr);
michael@0 1212 }
michael@0 1213
michael@0 1214 break;
michael@0 1215 }
michael@0 1216
michael@0 1217 case 1:
michael@0 1218 {
michael@0 1219 int i;
michael@0 1220 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
michael@0 1221 {
michael@0 1222 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1223 png_read_push_finish_row(png_ptr);
michael@0 1224 }
michael@0 1225
michael@0 1226 if (png_ptr->pass == 2) /* Skip top 4 generated rows */
michael@0 1227 {
michael@0 1228 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
michael@0 1229 {
michael@0 1230 png_push_have_row(png_ptr, NULL);
michael@0 1231 png_read_push_finish_row(png_ptr);
michael@0 1232 }
michael@0 1233 }
michael@0 1234
michael@0 1235 break;
michael@0 1236 }
michael@0 1237
michael@0 1238 case 2:
michael@0 1239 {
michael@0 1240 int i;
michael@0 1241
michael@0 1242 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
michael@0 1243 {
michael@0 1244 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1245 png_read_push_finish_row(png_ptr);
michael@0 1246 }
michael@0 1247
michael@0 1248 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
michael@0 1249 {
michael@0 1250 png_push_have_row(png_ptr, NULL);
michael@0 1251 png_read_push_finish_row(png_ptr);
michael@0 1252 }
michael@0 1253
michael@0 1254 if (png_ptr->pass == 4) /* Pass 3 might be empty */
michael@0 1255 {
michael@0 1256 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
michael@0 1257 {
michael@0 1258 png_push_have_row(png_ptr, NULL);
michael@0 1259 png_read_push_finish_row(png_ptr);
michael@0 1260 }
michael@0 1261 }
michael@0 1262
michael@0 1263 break;
michael@0 1264 }
michael@0 1265
michael@0 1266 case 3:
michael@0 1267 {
michael@0 1268 int i;
michael@0 1269
michael@0 1270 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
michael@0 1271 {
michael@0 1272 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1273 png_read_push_finish_row(png_ptr);
michael@0 1274 }
michael@0 1275
michael@0 1276 if (png_ptr->pass == 4) /* Skip top two generated rows */
michael@0 1277 {
michael@0 1278 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
michael@0 1279 {
michael@0 1280 png_push_have_row(png_ptr, NULL);
michael@0 1281 png_read_push_finish_row(png_ptr);
michael@0 1282 }
michael@0 1283 }
michael@0 1284
michael@0 1285 break;
michael@0 1286 }
michael@0 1287
michael@0 1288 case 4:
michael@0 1289 {
michael@0 1290 int i;
michael@0 1291
michael@0 1292 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
michael@0 1293 {
michael@0 1294 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1295 png_read_push_finish_row(png_ptr);
michael@0 1296 }
michael@0 1297
michael@0 1298 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
michael@0 1299 {
michael@0 1300 png_push_have_row(png_ptr, NULL);
michael@0 1301 png_read_push_finish_row(png_ptr);
michael@0 1302 }
michael@0 1303
michael@0 1304 if (png_ptr->pass == 6) /* Pass 5 might be empty */
michael@0 1305 {
michael@0 1306 png_push_have_row(png_ptr, NULL);
michael@0 1307 png_read_push_finish_row(png_ptr);
michael@0 1308 }
michael@0 1309
michael@0 1310 break;
michael@0 1311 }
michael@0 1312
michael@0 1313 case 5:
michael@0 1314 {
michael@0 1315 int i;
michael@0 1316
michael@0 1317 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
michael@0 1318 {
michael@0 1319 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1320 png_read_push_finish_row(png_ptr);
michael@0 1321 }
michael@0 1322
michael@0 1323 if (png_ptr->pass == 6) /* Skip top generated row */
michael@0 1324 {
michael@0 1325 png_push_have_row(png_ptr, NULL);
michael@0 1326 png_read_push_finish_row(png_ptr);
michael@0 1327 }
michael@0 1328
michael@0 1329 break;
michael@0 1330 }
michael@0 1331
michael@0 1332 default:
michael@0 1333 case 6:
michael@0 1334 {
michael@0 1335 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1336 png_read_push_finish_row(png_ptr);
michael@0 1337
michael@0 1338 if (png_ptr->pass != 6)
michael@0 1339 break;
michael@0 1340
michael@0 1341 png_push_have_row(png_ptr, NULL);
michael@0 1342 png_read_push_finish_row(png_ptr);
michael@0 1343 }
michael@0 1344 }
michael@0 1345 }
michael@0 1346 else
michael@0 1347 #endif
michael@0 1348 {
michael@0 1349 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
michael@0 1350 png_read_push_finish_row(png_ptr);
michael@0 1351 }
michael@0 1352 }
michael@0 1353
michael@0 1354 void /* PRIVATE */
michael@0 1355 png_read_push_finish_row(png_structrp png_ptr)
michael@0 1356 {
michael@0 1357 #ifdef PNG_READ_INTERLACING_SUPPORTED
michael@0 1358 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
michael@0 1359
michael@0 1360 /* Start of interlace block */
michael@0 1361 static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
michael@0 1362
michael@0 1363 /* Offset to next interlace block */
michael@0 1364 static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
michael@0 1365
michael@0 1366 /* Start of interlace block in the y direction */
michael@0 1367 static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
michael@0 1368
michael@0 1369 /* Offset to next interlace block in the y direction */
michael@0 1370 static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
michael@0 1371
michael@0 1372 /* Height of interlace block. This is not currently used - if you need
michael@0 1373 * it, uncomment it here and in png.h
michael@0 1374 static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
michael@0 1375 */
michael@0 1376 #endif
michael@0 1377
michael@0 1378 png_ptr->row_number++;
michael@0 1379 if (png_ptr->row_number < png_ptr->num_rows)
michael@0 1380 return;
michael@0 1381
michael@0 1382 #ifdef PNG_READ_INTERLACING_SUPPORTED
michael@0 1383 if (png_ptr->interlaced)
michael@0 1384 {
michael@0 1385 png_ptr->row_number = 0;
michael@0 1386 memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
michael@0 1387
michael@0 1388 do
michael@0 1389 {
michael@0 1390 png_ptr->pass++;
michael@0 1391 if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
michael@0 1392 (png_ptr->pass == 3 && png_ptr->width < 3) ||
michael@0 1393 (png_ptr->pass == 5 && png_ptr->width < 2))
michael@0 1394 png_ptr->pass++;
michael@0 1395
michael@0 1396 if (png_ptr->pass > 7)
michael@0 1397 png_ptr->pass--;
michael@0 1398
michael@0 1399 if (png_ptr->pass >= 7)
michael@0 1400 break;
michael@0 1401
michael@0 1402 png_ptr->iwidth = (png_ptr->width +
michael@0 1403 png_pass_inc[png_ptr->pass] - 1 -
michael@0 1404 png_pass_start[png_ptr->pass]) /
michael@0 1405 png_pass_inc[png_ptr->pass];
michael@0 1406
michael@0 1407 if (png_ptr->transformations & PNG_INTERLACE)
michael@0 1408 break;
michael@0 1409
michael@0 1410 png_ptr->num_rows = (png_ptr->height +
michael@0 1411 png_pass_yinc[png_ptr->pass] - 1 -
michael@0 1412 png_pass_ystart[png_ptr->pass]) /
michael@0 1413 png_pass_yinc[png_ptr->pass];
michael@0 1414
michael@0 1415 } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
michael@0 1416 }
michael@0 1417 #endif /* PNG_READ_INTERLACING_SUPPORTED */
michael@0 1418 }
michael@0 1419
michael@0 1420 void /* PRIVATE */
michael@0 1421 png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
michael@0 1422 {
michael@0 1423 if (png_ptr->info_fn != NULL)
michael@0 1424 (*(png_ptr->info_fn))(png_ptr, info_ptr);
michael@0 1425 }
michael@0 1426
michael@0 1427 void /* PRIVATE */
michael@0 1428 png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
michael@0 1429 {
michael@0 1430 if (png_ptr->end_fn != NULL)
michael@0 1431 (*(png_ptr->end_fn))(png_ptr, info_ptr);
michael@0 1432 }
michael@0 1433
michael@0 1434 void /* PRIVATE */
michael@0 1435 png_push_have_row(png_structrp png_ptr, png_bytep row)
michael@0 1436 {
michael@0 1437 if (png_ptr->row_fn != NULL)
michael@0 1438 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
michael@0 1439 (int)png_ptr->pass);
michael@0 1440 }
michael@0 1441
michael@0 1442 #ifdef PNG_READ_INTERLACING_SUPPORTED
michael@0 1443 void PNGAPI
michael@0 1444 png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
michael@0 1445 png_const_bytep new_row)
michael@0 1446 {
michael@0 1447 if (png_ptr == NULL)
michael@0 1448 return;
michael@0 1449
michael@0 1450 /* new_row is a flag here - if it is NULL then the app callback was called
michael@0 1451 * from an empty row (see the calls to png_struct::row_fn below), otherwise
michael@0 1452 * it must be png_ptr->row_buf+1
michael@0 1453 */
michael@0 1454 if (new_row != NULL)
michael@0 1455 png_combine_row(png_ptr, old_row, 1/*display*/);
michael@0 1456 }
michael@0 1457 #endif /* PNG_READ_INTERLACING_SUPPORTED */
michael@0 1458
michael@0 1459 void PNGAPI
michael@0 1460 png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
michael@0 1461 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
michael@0 1462 png_progressive_end_ptr end_fn)
michael@0 1463 {
michael@0 1464 if (png_ptr == NULL)
michael@0 1465 return;
michael@0 1466
michael@0 1467 png_ptr->info_fn = info_fn;
michael@0 1468 png_ptr->row_fn = row_fn;
michael@0 1469 png_ptr->end_fn = end_fn;
michael@0 1470
michael@0 1471 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
michael@0 1472 }
michael@0 1473
michael@0 1474 #ifdef PNG_READ_APNG_SUPPORTED
michael@0 1475 void PNGAPI
michael@0 1476 png_set_progressive_frame_fn(png_structp png_ptr,
michael@0 1477 png_progressive_frame_ptr frame_info_fn,
michael@0 1478 png_progressive_frame_ptr frame_end_fn)
michael@0 1479 {
michael@0 1480 png_ptr->frame_info_fn = frame_info_fn;
michael@0 1481 png_ptr->frame_end_fn = frame_end_fn;
michael@0 1482 png_ptr->apng_flags |= PNG_APNG_APP;
michael@0 1483 }
michael@0 1484 #endif
michael@0 1485
michael@0 1486 png_voidp PNGAPI
michael@0 1487 png_get_progressive_ptr(png_const_structrp png_ptr)
michael@0 1488 {
michael@0 1489 if (png_ptr == NULL)
michael@0 1490 return (NULL);
michael@0 1491
michael@0 1492 return png_ptr->io_ptr;
michael@0 1493 }
michael@0 1494 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */

mercurial