pngpread.c 45.7 KB
Newer Older
G
Guy Schalnat 已提交
1 2

/* pngpread.c - read a png file in push mode
3
 *
4
 * Last changed in libpng 1.5.0 [April 24, 2010]
5
 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 */
G
Guy Schalnat 已提交
13

14
#include "pngpriv.h"
G
Guy Schalnat 已提交
15

16 17
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED

18
/* Push model modes */
19 20 21 22 23 24 25 26 27 28
#define PNG_READ_SIG_MODE   0
#define PNG_READ_CHUNK_MODE 1
#define PNG_READ_IDAT_MODE  2
#define PNG_SKIP_MODE       3
#define PNG_READ_tEXt_MODE  4
#define PNG_READ_zTXt_MODE  5
#define PNG_READ_DONE_MODE  6
#define PNG_READ_iTXt_MODE  7
#define PNG_ERROR_MODE      8

29
void PNGAPI
A
Andreas Dilger 已提交
30
png_process_data(png_structp png_ptr, png_infop info_ptr,
31
    png_bytep buffer, png_size_t buffer_size)
G
Guy Schalnat 已提交
32
{
33 34 35
   if (png_ptr == NULL || info_ptr == NULL)
      return;

G
Guy Schalnat 已提交
36
   png_push_restore_buffer(png_ptr, buffer, buffer_size);
G
Guy Schalnat 已提交
37

G
Guy Schalnat 已提交
38 39
   while (png_ptr->buffer_size)
   {
A
Andreas Dilger 已提交
40
      png_process_some_data(png_ptr, info_ptr);
G
Guy Schalnat 已提交
41
   }
G
Guy Schalnat 已提交
42 43
}

A
Andreas Dilger 已提交
44 45 46
/* What we do with the incoming data depends on what we were previously
 * doing before we ran out of data...
 */
47
void /* PRIVATE */
A
Andreas Dilger 已提交
48
png_process_some_data(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
49
{
50 51 52
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
53 54 55 56
   switch (png_ptr->process_mode)
   {
      case PNG_READ_SIG_MODE:
      {
A
Andreas Dilger 已提交
57
         png_push_read_sig(png_ptr, info_ptr);
G
Guy Schalnat 已提交
58 59
         break;
      }
60

G
Guy Schalnat 已提交
61 62
      case PNG_READ_CHUNK_MODE:
      {
A
Andreas Dilger 已提交
63
         png_push_read_chunk(png_ptr, info_ptr);
G
Guy Schalnat 已提交
64 65
         break;
      }
66

G
Guy Schalnat 已提交
67 68
      case PNG_READ_IDAT_MODE:
      {
G
Guy Schalnat 已提交
69
         png_push_read_IDAT(png_ptr);
G
Guy Schalnat 已提交
70 71
         break;
      }
72

73
#ifdef PNG_READ_tEXt_SUPPORTED
G
Guy Schalnat 已提交
74 75
      case PNG_READ_tEXt_MODE:
      {
A
Andreas Dilger 已提交
76
         png_push_read_tEXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
77 78
         break;
      }
79

G
Guy Schalnat 已提交
80
#endif
81
#ifdef PNG_READ_zTXt_SUPPORTED
G
Guy Schalnat 已提交
82 83
      case PNG_READ_zTXt_MODE:
      {
A
Andreas Dilger 已提交
84
         png_push_read_zTXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
85 86
         break;
      }
87

88
#endif
89
#ifdef PNG_READ_iTXt_SUPPORTED
90 91 92 93 94
      case PNG_READ_iTXt_MODE:
      {
         png_push_read_iTXt(png_ptr, info_ptr);
         break;
      }
95

G
Guy Schalnat 已提交
96 97 98
#endif
      case PNG_SKIP_MODE:
      {
A
Andreas Dilger 已提交
99
         png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
100 101
         break;
      }
102

G
Guy Schalnat 已提交
103 104 105 106 107 108
      default:
      {
         png_ptr->buffer_size = 0;
         break;
      }
   }
G
Guy Schalnat 已提交
109 110
}

A
Andreas Dilger 已提交
111 112
/* Read any remaining signature bytes from the stream and compare them with
 * the correct PNG signature.  It is possible that this routine is called
113 114 115
 * with bytes already read from the signature, either because they have been
 * checked by the calling application, or because of multiple calls to this
 * routine.
A
Andreas Dilger 已提交
116
 */
117
void /* PRIVATE */
A
Andreas Dilger 已提交
118
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
119
{
A
Andreas Dilger 已提交
120 121
   png_size_t num_checked = png_ptr->sig_bytes,
             num_to_check = 8 - num_checked;
G
Guy Schalnat 已提交
122

A
Andreas Dilger 已提交
123
   if (png_ptr->buffer_size < num_to_check)
G
Guy Schalnat 已提交
124
   {
A
Andreas Dilger 已提交
125
      num_to_check = png_ptr->buffer_size;
G
Guy Schalnat 已提交
126 127
   }

128
   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
129
       num_to_check);
130
   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
G
Guy Schalnat 已提交
131

A
Andreas Dilger 已提交
132
   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
G
Guy Schalnat 已提交
133
   {
A
Andreas Dilger 已提交
134 135 136 137 138
      if (num_checked < 4 &&
          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
         png_error(png_ptr, "Not a PNG file");
      else
         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
G
Guy Schalnat 已提交
139 140 141
   }
   else
   {
A
Andreas Dilger 已提交
142 143 144 145
      if (png_ptr->sig_bytes >= 8)
      {
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
      }
G
Guy Schalnat 已提交
146
   }
G
Guy Schalnat 已提交
147 148
}

149
void /* PRIVATE */
A
Andreas Dilger 已提交
150
png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
151
{
152 153 154 155
      PNG_IHDR;
      PNG_IDAT;
      PNG_IEND;
      PNG_PLTE;
156
#ifdef PNG_READ_bKGD_SUPPORTED
157
      PNG_bKGD;
158
#endif
159
#ifdef PNG_READ_cHRM_SUPPORTED
160
      PNG_cHRM;
161
#endif
162
#ifdef PNG_READ_gAMA_SUPPORTED
163
      PNG_gAMA;
164
#endif
165
#ifdef PNG_READ_hIST_SUPPORTED
166
      PNG_hIST;
167
#endif
168
#ifdef PNG_READ_iCCP_SUPPORTED
169
      PNG_iCCP;
170
#endif
171
#ifdef PNG_READ_iTXt_SUPPORTED
172
      PNG_iTXt;
173
#endif
174
#ifdef PNG_READ_oFFs_SUPPORTED
175
      PNG_oFFs;
176
#endif
177
#ifdef PNG_READ_pCAL_SUPPORTED
178
      PNG_pCAL;
179
#endif
180
#ifdef PNG_READ_pHYs_SUPPORTED
181
      PNG_pHYs;
182
#endif
183
#ifdef PNG_READ_sBIT_SUPPORTED
184
      PNG_sBIT;
185
#endif
186
#ifdef PNG_READ_sCAL_SUPPORTED
187
      PNG_sCAL;
188
#endif
189
#ifdef PNG_READ_sRGB_SUPPORTED
190
      PNG_sRGB;
191
#endif
192
#ifdef PNG_READ_sPLT_SUPPORTED
193
      PNG_sPLT;
194
#endif
195
#ifdef PNG_READ_tEXt_SUPPORTED
196
      PNG_tEXt;
197
#endif
198
#ifdef PNG_READ_tIME_SUPPORTED
199
      PNG_tIME;
200
#endif
201
#ifdef PNG_READ_tRNS_SUPPORTED
202
      PNG_tRNS;
203
#endif
204
#ifdef PNG_READ_zTXt_SUPPORTED
205
      PNG_zTXt;
206
#endif
207

A
Andreas Dilger 已提交
208
   /* First we make sure we have enough data for the 4 byte chunk name
209 210 211 212 213
    * and the 4 byte chunk length before proceeding with decoding the
    * chunk data.  To fully decode each of these chunks, we also make
    * sure we have enough data in the buffer for the 4 byte CRC at the
    * end of every chunk (except IDAT, which is handled separately).
    */
214
   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
215
   {
A
Andreas Dilger 已提交
216
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
217 218 219 220 221 222 223

      if (png_ptr->buffer_size < 8)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
224
      png_push_fill_buffer(png_ptr, chunk_length, 4);
225
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
226
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
227
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
228
      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
229
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
230 231
   }

232
   if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
233 234
      if (png_ptr->mode & PNG_AFTER_IDAT)
         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
235

A
Andreas Dilger 已提交
236
   if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
G
Guy Schalnat 已提交
237
   {
238 239
      if (png_ptr->push_length != 13)
         png_error(png_ptr, "Invalid IHDR length");
240

241 242 243
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
244
         return;
245
      }
246

A
Andreas Dilger 已提交
247
      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
248
   }
249

250 251
   else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
   {
252 253 254
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
255
         return;
256
      }
257

258 259 260 261 262
      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);

      png_ptr->process_mode = PNG_READ_DONE_MODE;
      png_push_have_end(png_ptr, info_ptr);
   }
263

264 265 266
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
   {
267 268 269
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
270
         return;
271
      }
272

273 274
      if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
         png_ptr->mode |= PNG_HAVE_IDAT;
275

276
      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
277

278 279
      if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
         png_ptr->mode |= PNG_HAVE_PLTE;
280

281 282 283 284
      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
      {
         if (!(png_ptr->mode & PNG_HAVE_IHDR))
            png_error(png_ptr, "Missing IHDR before IDAT");
285

286
         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
287
             !(png_ptr->mode & PNG_HAVE_PLTE))
288 289 290
            png_error(png_ptr, "Missing PLTE before IDAT");
      }
   }
291

292
#endif
A
Andreas Dilger 已提交
293
   else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
G
Guy Schalnat 已提交
294
   {
295 296 297
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
A
Andreas Dilger 已提交
298
         return;
299
      }
A
Andreas Dilger 已提交
300
      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
301
   }
302

303
   else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
304
   {
A
Andreas Dilger 已提交
305
      /* If we reach an IDAT chunk, this means we have read all of the
306 307 308
       * header chunks, and we can start reading the image (or if this
       * is called after the image has been read - we have an error).
       */
309 310 311 312 313 314 315

      if (!(png_ptr->mode & PNG_HAVE_IHDR))
         png_error(png_ptr, "Missing IHDR before IDAT");

      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
          !(png_ptr->mode & PNG_HAVE_PLTE))
         png_error(png_ptr, "Missing PLTE before IDAT");
316

A
Andreas Dilger 已提交
317 318
      if (png_ptr->mode & PNG_HAVE_IDAT)
      {
319
         if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
320 321
            if (png_ptr->push_length == 0)
               return;
A
Andreas Dilger 已提交
322 323

         if (png_ptr->mode & PNG_AFTER_IDAT)
324
            png_benign_error(png_ptr, "Too many IDATs found");
A
Andreas Dilger 已提交
325 326
      }

G
Guy Schalnat 已提交
327
      png_ptr->idat_size = png_ptr->push_length;
A
Andreas Dilger 已提交
328
      png_ptr->mode |= PNG_HAVE_IDAT;
G
Guy Schalnat 已提交
329
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
A
Andreas Dilger 已提交
330
      png_push_have_info(png_ptr, info_ptr);
331 332 333
      png_ptr->zstream.avail_out =
          (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
          png_ptr->iwidth) + 1;
A
Andreas Dilger 已提交
334
      png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
335 336
      return;
   }
337

338
#ifdef PNG_READ_gAMA_SUPPORTED
A
Andreas Dilger 已提交
339
   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
G
Guy Schalnat 已提交
340
   {
341 342 343
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
344
         return;
345
      }
346

A
Andreas Dilger 已提交
347
      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
348
   }
349

G
Guy Schalnat 已提交
350
#endif
351
#ifdef PNG_READ_sBIT_SUPPORTED
A
Andreas Dilger 已提交
352
   else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
G
Guy Schalnat 已提交
353
   {
354 355 356
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
357
         return;
358
      }
359

A
Andreas Dilger 已提交
360
      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
361
   }
362

G
Guy Schalnat 已提交
363
#endif
364
#ifdef PNG_READ_cHRM_SUPPORTED
A
Andreas Dilger 已提交
365
   else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
G
Guy Schalnat 已提交
366
   {
367 368 369
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
370
         return;
371
      }
372

A
Andreas Dilger 已提交
373
      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
374
   }
375

G
Guy Schalnat 已提交
376
#endif
377
#ifdef PNG_READ_sRGB_SUPPORTED
378 379
   else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
   {
380 381 382
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
383
         return;
384
      }
385

386 387
      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
   }
388

389
#endif
390
#ifdef PNG_READ_iCCP_SUPPORTED
391 392
   else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
   {
393 394 395
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
396
         return;
397
      }
398

399 400
      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
   }
401

402
#endif
403
#ifdef PNG_READ_sPLT_SUPPORTED
404 405
   else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
   {
406 407 408
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
409
         return;
410
      }
411

412 413
      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
   }
414

415
#endif
416
#ifdef PNG_READ_tRNS_SUPPORTED
A
Andreas Dilger 已提交
417
   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
G
Guy Schalnat 已提交
418
   {
419 420 421
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
422
         return;
423
      }
424

A
Andreas Dilger 已提交
425
      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
426
   }
427

G
Guy Schalnat 已提交
428
#endif
429
#ifdef PNG_READ_bKGD_SUPPORTED
A
Andreas Dilger 已提交
430
   else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
G
Guy Schalnat 已提交
431
   {
432 433 434
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
435
         return;
436
      }
437

A
Andreas Dilger 已提交
438
      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
439
   }
440

G
Guy Schalnat 已提交
441
#endif
442
#ifdef PNG_READ_hIST_SUPPORTED
A
Andreas Dilger 已提交
443
   else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
G
Guy Schalnat 已提交
444
   {
445 446 447
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
448
         return;
449
      }
450

A
Andreas Dilger 已提交
451
      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
452
   }
453

G
Guy Schalnat 已提交
454
#endif
455
#ifdef PNG_READ_pHYs_SUPPORTED
A
Andreas Dilger 已提交
456
   else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
G
Guy Schalnat 已提交
457 458 459 460 461 462
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
463

A
Andreas Dilger 已提交
464
      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
465
   }
466

G
Guy Schalnat 已提交
467
#endif
468
#ifdef PNG_READ_oFFs_SUPPORTED
A
Andreas Dilger 已提交
469
   else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
G
Guy Schalnat 已提交
470
   {
471 472 473
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
474
         return;
475
      }
476

A
Andreas Dilger 已提交
477
      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
478
   }
G
Guy Schalnat 已提交
479
#endif
480

481
#ifdef PNG_READ_pCAL_SUPPORTED
A
Andreas Dilger 已提交
482 483
   else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
   {
484 485 486
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
A
Andreas Dilger 已提交
487
         return;
488
      }
489

A
Andreas Dilger 已提交
490 491
      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
492

A
Andreas Dilger 已提交
493
#endif
494
#ifdef PNG_READ_sCAL_SUPPORTED
495 496
   else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
   {
497 498 499
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
500
         return;
501
      }
502

503 504
      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
505

506
#endif
507
#ifdef PNG_READ_tIME_SUPPORTED
A
Andreas Dilger 已提交
508
   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
G
Guy Schalnat 已提交
509
   {
510 511 512
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
513
         return;
514
      }
515

A
Andreas Dilger 已提交
516
      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
517
   }
518

G
Guy Schalnat 已提交
519
#endif
520
#ifdef PNG_READ_tEXt_SUPPORTED
A
Andreas Dilger 已提交
521
   else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
G
Guy Schalnat 已提交
522
   {
523 524 525
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
526
         return;
527
      }
528

A
Andreas Dilger 已提交
529
      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
530
   }
531

G
Guy Schalnat 已提交
532
#endif
533
#ifdef PNG_READ_zTXt_SUPPORTED
A
Andreas Dilger 已提交
534
   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
G
Guy Schalnat 已提交
535
   {
536 537 538
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
539
         return;
540
      }
541

A
Andreas Dilger 已提交
542
      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
543
   }
544

545
#endif
546
#ifdef PNG_READ_iTXt_SUPPORTED
547
   else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
548
   {
549 550 551
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
552
         return;
553
      }
554

555 556
      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
   }
557

G
Guy Schalnat 已提交
558
#endif
G
Guy Schalnat 已提交
559 560
   else
   {
561 562 563
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
564
         return;
565
      }
A
Andreas Dilger 已提交
566
      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
567
   }
G
Guy Schalnat 已提交
568

569
   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
570 571
}

572
void /* PRIVATE */
A
Andreas Dilger 已提交
573
png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
G
Guy Schalnat 已提交
574
{
G
Guy Schalnat 已提交
575
   png_ptr->process_mode = PNG_SKIP_MODE;
A
Andreas Dilger 已提交
576
   png_ptr->skip_length = skip;
G
Guy Schalnat 已提交
577 578
}

579
void /* PRIVATE */
A
Andreas Dilger 已提交
580
png_push_crc_finish(png_structp png_ptr)
G
Guy Schalnat 已提交
581
{
G
Guy Schalnat 已提交
582 583
   if (png_ptr->skip_length && png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
584
      png_size_t save_size;
G
Guy Schalnat 已提交
585

A
Andreas Dilger 已提交
586 587
      if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
         save_size = (png_size_t)png_ptr->skip_length;
G
Guy Schalnat 已提交
588 589 590 591 592 593 594 595
      else
         save_size = png_ptr->save_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);

      png_ptr->skip_length -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
596
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
597 598 599
   }
   if (png_ptr->skip_length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
600
      png_size_t save_size;
G
Guy Schalnat 已提交
601

A
Andreas Dilger 已提交
602 603
      if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
         save_size = (png_size_t)png_ptr->skip_length;
G
Guy Schalnat 已提交
604 605 606 607 608 609 610 611
      else
         save_size = png_ptr->current_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);

      png_ptr->skip_length -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
612
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
613 614 615 616 617 618 619 620
   }
   if (!png_ptr->skip_length)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
A
Andreas Dilger 已提交
621 622

      png_crc_finish(png_ptr, 0);
A
Andreas Dilger 已提交
623
      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
624
   }
G
Guy Schalnat 已提交
625 626
}

627
void PNGCBAPI
A
Andreas Dilger 已提交
628
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
G
Guy Schalnat 已提交
629
{
G
Guy Schalnat 已提交
630 631
   png_bytep ptr;

632 633 634
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
635 636 637
   ptr = buffer;
   if (png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
638
      png_size_t save_size;
G
Guy Schalnat 已提交
639 640 641 642 643 644

      if (length < png_ptr->save_buffer_size)
         save_size = length;
      else
         save_size = png_ptr->save_buffer_size;

A
Andreas Dilger 已提交
645
      png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
G
Guy Schalnat 已提交
646
      length -= save_size;
A
Andreas Dilger 已提交
647
      ptr += save_size;
G
Guy Schalnat 已提交
648 649
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
650
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
651 652 653
   }
   if (length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
654
      png_size_t save_size;
G
Guy Schalnat 已提交
655 656 657

      if (length < png_ptr->current_buffer_size)
         save_size = length;
658

G
Guy Schalnat 已提交
659 660 661
      else
         save_size = png_ptr->current_buffer_size;

A
Andreas Dilger 已提交
662
      png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
663 664
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
665
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
666
   }
G
Guy Schalnat 已提交
667 668
}

669
void /* PRIVATE */
G
Guy Schalnat 已提交
670 671
png_push_save_buffer(png_structp png_ptr)
{
G
Guy Schalnat 已提交
672 673 674 675
   if (png_ptr->save_buffer_size)
   {
      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
      {
676
         png_size_t i, istop;
G
Guy Schalnat 已提交
677 678 679
         png_bytep sp;
         png_bytep dp;

680
         istop = png_ptr->save_buffer_size;
G
Guy Schalnat 已提交
681
         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
682
             i < istop; i++, sp++, dp++)
G
Guy Schalnat 已提交
683 684 685 686 687
         {
            *dp = *sp;
         }
      }
   }
688
   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
689
       png_ptr->save_buffer_max)
G
Guy Schalnat 已提交
690
   {
A
Andreas Dilger 已提交
691
      png_size_t new_max;
G
Guy Schalnat 已提交
692 693
      png_bytep old_buffer;

694
      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
695
          (png_ptr->current_buffer_size + 256))
696
      {
697
         png_error(png_ptr, "Potential overflow of save_buffer");
698
      }
699

700
      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
G
Guy Schalnat 已提交
701
      old_buffer = png_ptr->save_buffer;
702
      png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
703
          (png_size_t)new_max);
704 705
      if (png_ptr->save_buffer == NULL)
      {
706 707
         png_free(png_ptr, old_buffer);
         png_error(png_ptr, "Insufficient memory for save_buffer");
708
      }
709 710 711
      png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
      png_free(png_ptr, old_buffer);
      png_ptr->save_buffer_max = new_max;
G
Guy Schalnat 已提交
712 713 714
   }
   if (png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
715 716
      png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
G
Guy Schalnat 已提交
717 718 719 720 721
      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
      png_ptr->current_buffer_size = 0;
   }
   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
   png_ptr->buffer_size = 0;
G
Guy Schalnat 已提交
722 723
}

724
void /* PRIVATE */
G
Guy Schalnat 已提交
725
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
726
   png_size_t buffer_length)
G
Guy Schalnat 已提交
727
{
G
Guy Schalnat 已提交
728 729 730 731
   png_ptr->current_buffer = buffer;
   png_ptr->current_buffer_size = buffer_length;
   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
G
Guy Schalnat 已提交
732 733
}

734
void /* PRIVATE */
G
Guy Schalnat 已提交
735
png_push_read_IDAT(png_structp png_ptr)
G
Guy Schalnat 已提交
736
{
737
   PNG_IDAT;
738
   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
739
   {
A
Andreas Dilger 已提交
740
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
741 742 743 744 745 746 747

      if (png_ptr->buffer_size < 8)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
748
      png_push_fill_buffer(png_ptr, chunk_length, 4);
749
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
750
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
751
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
752
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
A
Andreas Dilger 已提交
753

754
      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
755
      {
A
Andreas Dilger 已提交
756
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
757
         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
758 759 760 761 762 763 764 765
            png_error(png_ptr, "Not enough compressed data");
         return;
      }

      png_ptr->idat_size = png_ptr->push_length;
   }
   if (png_ptr->idat_size && png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
766
      png_size_t save_size;
G
Guy Schalnat 已提交
767

A
Andreas Dilger 已提交
768
      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
769 770
      {
         save_size = (png_size_t)png_ptr->idat_size;
771

772
         /* Check for overflow */
773
         if ((png_uint_32)save_size != png_ptr->idat_size)
774 775
            png_error(png_ptr, "save_size overflowed in pngpread");
      }
G
Guy Schalnat 已提交
776 777 778 779
      else
         save_size = png_ptr->save_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
780

781 782
      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
         png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
783

G
Guy Schalnat 已提交
784 785 786
      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
787
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
788 789 790
   }
   if (png_ptr->idat_size && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
791
      png_size_t save_size;
G
Guy Schalnat 已提交
792

A
Andreas Dilger 已提交
793
      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
794 795
      {
         save_size = (png_size_t)png_ptr->idat_size;
796

797
         /* Check for overflow */
798
         if ((png_uint_32)save_size != png_ptr->idat_size)
799 800
            png_error(png_ptr, "save_size overflowed in pngpread");
      }
G
Guy Schalnat 已提交
801 802 803 804
      else
         save_size = png_ptr->current_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
805
      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
806
         png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
807 808 809 810

      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
811
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
812 813 814 815 816 817 818 819 820
   }
   if (!png_ptr->idat_size)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
821
      png_crc_finish(png_ptr, 0);
822
      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
823
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
824
   }
G
Guy Schalnat 已提交
825 826
}

827
void /* PRIVATE */
G
Guy Schalnat 已提交
828
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
829
   png_size_t buffer_length)
G
Guy Schalnat 已提交
830
{
G
Guy Schalnat 已提交
831 832
   int ret;

G
Guy Schalnat 已提交
833
   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
834
      png_benign_error(png_ptr, "Extra compression data");
G
Guy Schalnat 已提交
835

A
Andreas Dilger 已提交
836 837
   png_ptr->zstream.next_in = buffer;
   png_ptr->zstream.avail_in = (uInt)buffer_length;
838
   for (;;)
G
Guy Schalnat 已提交
839
   {
A
Andreas Dilger 已提交
840
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
841
      if (ret != Z_OK)
G
Guy Schalnat 已提交
842
      {
843
         if (ret == Z_STREAM_END)
G
Guy Schalnat 已提交
844
         {
845
            if (png_ptr->zstream.avail_in)
846
               png_benign_error(png_ptr, "Extra compressed data");
847

848 849 850 851 852 853 854 855
            if (!(png_ptr->zstream.avail_out))
            {
               png_push_process_row(png_ptr);
            }

            png_ptr->mode |= PNG_AFTER_IDAT;
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
            break;
G
Guy Schalnat 已提交
856
         }
857 858
         else if (ret == Z_BUF_ERROR)
            break;
859

860 861
         else
            png_error(png_ptr, "Decompression Error");
G
Guy Schalnat 已提交
862
      }
A
Andreas Dilger 已提交
863
      if (!(png_ptr->zstream.avail_out))
G
Guy Schalnat 已提交
864
      {
865
         if ((
866
#ifdef PNG_READ_INTERLACING_SUPPORTED
867 868 869
             png_ptr->interlaced && png_ptr->pass > 6) ||
             (!png_ptr->interlaced &&
#endif
870
             png_ptr->row_number == png_ptr->num_rows))
871
         {
872 873 874 875
            if (png_ptr->zstream.avail_in)
               png_warning(png_ptr, "Too much data in IDAT chunks");
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
            break;
876
         }
G
Guy Schalnat 已提交
877
         png_push_process_row(png_ptr);
878 879 880
         png_ptr->zstream.avail_out =
             (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
             png_ptr->iwidth) + 1;
A
Andreas Dilger 已提交
881
         png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
882
      }
883

A
Andreas Dilger 已提交
884 885 886
      else
         break;
   }
G
Guy Schalnat 已提交
887 888
}

889
void /* PRIVATE */
G
Guy Schalnat 已提交
890 891
png_push_process_row(png_structp png_ptr)
{
G
Guy Schalnat 已提交
892
   png_ptr->row_info.color_type = png_ptr->color_type;
G
Guy Schalnat 已提交
893 894 895 896
   png_ptr->row_info.width = png_ptr->iwidth;
   png_ptr->row_info.channels = png_ptr->channels;
   png_ptr->row_info.bit_depth = png_ptr->bit_depth;
   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
897

898 899
   png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
       png_ptr->row_info.width);
G
Guy Schalnat 已提交
900

G
Guy Schalnat 已提交
901 902 903
   png_read_filter_row(png_ptr, &(png_ptr->row_info),
      png_ptr->row_buf + 1, png_ptr->prev_row + 1,
      (int)(png_ptr->row_buf[0]));
G
Guy Schalnat 已提交
904

905
   png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
906

907
   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
G
Guy Schalnat 已提交
908 909
      png_do_read_transformations(png_ptr);

910
#ifdef PNG_READ_INTERLACING_SUPPORTED
911
   /* Blow up interlaced rows to full size */
A
Andreas Dilger 已提交
912
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
G
Guy Schalnat 已提交
913 914
   {
      if (png_ptr->pass < 6)
915
/*       old interface (pre-1.0.9):
G
Guy Schalnat 已提交
916
         png_do_read_interlace(&(png_ptr->row_info),
917
             png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
918 919
 */
         png_do_read_interlace(png_ptr);
G
Guy Schalnat 已提交
920

921 922
    switch (png_ptr->pass)
    {
G
Guy Schalnat 已提交
923 924 925 926 927 928
         case 0:
         {
            int i;
            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
929
               png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
G
Guy Schalnat 已提交
930
            }
931

932
            if (png_ptr->pass == 2) /* Pass 1 might be empty */
933 934 935
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
936
                  png_push_have_row(png_ptr, NULL);
937 938 939
                  png_read_push_finish_row(png_ptr);
               }
            }
940

941 942 943 944
            if (png_ptr->pass == 4 && png_ptr->height <= 4)
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
945
                  png_push_have_row(png_ptr, NULL);
946 947
                  png_read_push_finish_row(png_ptr);
               }
948
            }
949

950 951
            if (png_ptr->pass == 6 && png_ptr->height <= 4)
            {
952
                png_push_have_row(png_ptr, NULL);
953 954
                png_read_push_finish_row(png_ptr);
            }
955

G
Guy Schalnat 已提交
956 957
            break;
         }
958

G
Guy Schalnat 已提交
959 960 961 962 963 964 965 966
         case 1:
         {
            int i;
            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
967

968
            if (png_ptr->pass == 2) /* Skip top 4 generated rows */
G
Guy Schalnat 已提交
969 970 971
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
972
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
973 974 975
                  png_read_push_finish_row(png_ptr);
               }
            }
976

G
Guy Schalnat 已提交
977 978
            break;
         }
979

G
Guy Schalnat 已提交
980 981 982
         case 2:
         {
            int i;
983

G
Guy Schalnat 已提交
984 985 986 987 988
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
989

G
Guy Schalnat 已提交
990 991
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
992
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
993 994
               png_read_push_finish_row(png_ptr);
            }
995

996
            if (png_ptr->pass == 4) /* Pass 3 might be empty */
997 998 999
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
1000
                  png_push_have_row(png_ptr, NULL);
1001 1002 1003
                  png_read_push_finish_row(png_ptr);
               }
            }
1004

G
Guy Schalnat 已提交
1005 1006
            break;
         }
1007

G
Guy Schalnat 已提交
1008 1009 1010
         case 3:
         {
            int i;
1011

G
Guy Schalnat 已提交
1012 1013 1014 1015 1016
            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
1017

1018
            if (png_ptr->pass == 4) /* Skip top two generated rows */
G
Guy Schalnat 已提交
1019 1020 1021
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
1022
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1023 1024 1025
                  png_read_push_finish_row(png_ptr);
               }
            }
1026

G
Guy Schalnat 已提交
1027 1028
            break;
         }
1029

G
Guy Schalnat 已提交
1030 1031 1032
         case 4:
         {
            int i;
1033

G
Guy Schalnat 已提交
1034 1035 1036 1037 1038
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
1039

G
Guy Schalnat 已提交
1040 1041
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
1042
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1043 1044
               png_read_push_finish_row(png_ptr);
            }
1045

1046
            if (png_ptr->pass == 6) /* Pass 5 might be empty */
1047
            {
1048
               png_push_have_row(png_ptr, NULL);
1049 1050
               png_read_push_finish_row(png_ptr);
            }
1051

G
Guy Schalnat 已提交
1052 1053
            break;
         }
1054

G
Guy Schalnat 已提交
1055 1056 1057
         case 5:
         {
            int i;
1058

G
Guy Schalnat 已提交
1059 1060 1061 1062 1063
            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
1064

1065
            if (png_ptr->pass == 6) /* Skip top generated row */
G
Guy Schalnat 已提交
1066
            {
1067
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1068 1069
               png_read_push_finish_row(png_ptr);
            }
1070

G
Guy Schalnat 已提交
1071 1072 1073 1074 1075 1076
            break;
         }
         case 6:
         {
            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
            png_read_push_finish_row(png_ptr);
1077

G
Guy Schalnat 已提交
1078 1079
            if (png_ptr->pass != 6)
               break;
1080

1081
            png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1082 1083 1084 1085 1086
            png_read_push_finish_row(png_ptr);
         }
      }
   }
   else
G
Guy Schalnat 已提交
1087
#endif
G
Guy Schalnat 已提交
1088 1089 1090 1091
   {
      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
      png_read_push_finish_row(png_ptr);
   }
G
Guy Schalnat 已提交
1092 1093
}

1094
void /* PRIVATE */
G
Guy Schalnat 已提交
1095 1096
png_read_push_finish_row(png_structp png_ptr)
{
1097
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1098

1099
   /* Start of interlace block */
1100
   PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
1101

1102
   /* Offset to next interlace block */
1103
   PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
1104

1105
   /* Start of interlace block in the y direction */
1106
   PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
1107

1108
   /* Offset to next interlace block in the y direction */
1109
   PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
1110

1111 1112
   /* Height of interlace block.  This is not currently used - if you need
    * it, uncomment it here and in png.h
1113
   PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
1114
   */
1115

G
Guy Schalnat 已提交
1116 1117
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
1118
      return;
G
Guy Schalnat 已提交
1119

1120
#ifdef PNG_READ_INTERLACING_SUPPORTED
G
Guy Schalnat 已提交
1121 1122 1123
   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
1124 1125
      png_memset(png_ptr->prev_row, 0,
         png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
1126 1127 1128
      do
      {
         png_ptr->pass++;
1129 1130 1131
         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
             (png_ptr->pass == 3 && png_ptr->width < 3) ||
             (png_ptr->pass == 5 && png_ptr->width < 2))
1132
            png_ptr->pass++;
1133

1134 1135
         if (png_ptr->pass > 7)
            png_ptr->pass--;
1136

G
Guy Schalnat 已提交
1137 1138
         if (png_ptr->pass >= 7)
            break;
1139

G
Guy Schalnat 已提交
1140 1141 1142 1143
         png_ptr->iwidth = (png_ptr->width +
            png_pass_inc[png_ptr->pass] - 1 -
            png_pass_start[png_ptr->pass]) /
            png_pass_inc[png_ptr->pass];
1144

G
Guy Schalnat 已提交
1145 1146
         if (png_ptr->transformations & PNG_INTERLACE)
            break;
1147 1148 1149 1150 1151 1152 1153

         png_ptr->num_rows = (png_ptr->height +
            png_pass_yinc[png_ptr->pass] - 1 -
            png_pass_ystart[png_ptr->pass]) /
            png_pass_yinc[png_ptr->pass];

      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
G
Guy Schalnat 已提交
1154
   }
1155
#endif /* PNG_READ_INTERLACING_SUPPORTED */
G
Guy Schalnat 已提交
1156 1157
}

1158
#ifdef PNG_READ_tEXt_SUPPORTED
1159
void /* PRIVATE */
1160
png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
1161
    length)
G
Guy Schalnat 已提交
1162
{
1163
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1164 1165
      {
         png_error(png_ptr, "Out of place tEXt");
1166
         info_ptr = info_ptr; /* To quiet some compiler warnings */
1167
      }
A
Andreas Dilger 已提交
1168

A
Andreas Dilger 已提交
1169 1170 1171
#ifdef PNG_MAX_MALLOC_64K
   png_ptr->skip_length = 0;  /* This may not be necessary */

1172
   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
A
Andreas Dilger 已提交
1173 1174
   {
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1175 1176
      png_ptr->skip_length = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
A
Andreas Dilger 已提交
1177 1178 1179
   }
#endif

1180
   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
1181
       (png_size_t)(length + 1));
A
Andreas Dilger 已提交
1182
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
1183
   png_ptr->current_text_ptr = png_ptr->current_text;
1184 1185
   png_ptr->current_text_size = (png_size_t)length;
   png_ptr->current_text_left = (png_size_t)length;
G
Guy Schalnat 已提交
1186
   png_ptr->process_mode = PNG_READ_tEXt_MODE;
G
Guy Schalnat 已提交
1187 1188
}

1189
void /* PRIVATE */
A
Andreas Dilger 已提交
1190
png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1191
{
G
Guy Schalnat 已提交
1192 1193
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
1194
      png_size_t text_size;
G
Guy Schalnat 已提交
1195 1196 1197

      if (png_ptr->buffer_size < png_ptr->current_text_left)
         text_size = png_ptr->buffer_size;
1198

G
Guy Schalnat 已提交
1199 1200
      else
         text_size = png_ptr->current_text_left;
1201

A
Andreas Dilger 已提交
1202
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
1203
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
1204
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
1205 1206 1207
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
1208
      png_textp text_ptr;
G
Guy Schalnat 已提交
1209 1210
      png_charp text;
      png_charp key;
1211
      int ret;
G
Guy Schalnat 已提交
1212 1213 1214 1215 1216 1217 1218

      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
1219 1220
      png_push_crc_finish(png_ptr);

1221
#ifdef PNG_MAX_MALLOC_64K
A
Andreas Dilger 已提交
1222 1223 1224
      if (png_ptr->skip_length)
         return;
#endif
G
Guy Schalnat 已提交
1225 1226 1227 1228

      key = png_ptr->current_text;

      for (text = key; *text; text++)
1229
         /* Empty loop */ ;
G
Guy Schalnat 已提交
1230

1231
      if (text < key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
1232 1233
         text++;

1234
      text_ptr = (png_textp)png_malloc(png_ptr,
1235
          png_sizeof(png_text));
A
Andreas Dilger 已提交
1236 1237
      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
      text_ptr->key = key;
1238
      text_ptr->itxt_length = 0;
1239 1240
      text_ptr->lang = NULL;
      text_ptr->lang_key = NULL;
A
Andreas Dilger 已提交
1241
      text_ptr->text = text;
G
Guy Schalnat 已提交
1242

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

1245
      png_free(png_ptr, key);
A
Andreas Dilger 已提交
1246
      png_free(png_ptr, text_ptr);
1247
      png_ptr->current_text = NULL;
1248 1249

      if (ret)
1250
         png_warning(png_ptr, "Insufficient memory to store text chunk");
G
Guy Schalnat 已提交
1251
   }
G
Guy Schalnat 已提交
1252 1253 1254
}
#endif

1255
#ifdef PNG_READ_zTXt_SUPPORTED
1256
void /* PRIVATE */
1257 1258
png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
G
Guy Schalnat 已提交
1259
{
1260
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1261 1262
      {
         png_error(png_ptr, "Out of place zTXt");
1263
         info_ptr = info_ptr; /* To quiet some compiler warnings */
1264
      }
A
Andreas Dilger 已提交
1265

A
Andreas Dilger 已提交
1266 1267 1268 1269 1270
#ifdef PNG_MAX_MALLOC_64K
   /* We can't handle zTXt chunks > 64K, since we don't have enough space
    * to be able to store the uncompressed data.  Actually, the threshold
    * is probably around 32K, but it isn't as definite as 64K is.
    */
1271
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
1272 1273 1274 1275 1276 1277 1278
   {
      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_push_crc_skip(png_ptr, length);
      return;
   }
#endif

1279
   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
1280
       (png_size_t)(length + 1));
A
Andreas Dilger 已提交
1281
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
1282
   png_ptr->current_text_ptr = png_ptr->current_text;
1283 1284
   png_ptr->current_text_size = (png_size_t)length;
   png_ptr->current_text_left = (png_size_t)length;
G
Guy Schalnat 已提交
1285
   png_ptr->process_mode = PNG_READ_zTXt_MODE;
G
Guy Schalnat 已提交
1286 1287
}

1288
void /* PRIVATE */
A
Andreas Dilger 已提交
1289
png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1290
{
G
Guy Schalnat 已提交
1291 1292
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
1293
      png_size_t text_size;
G
Guy Schalnat 已提交
1294

A
Andreas Dilger 已提交
1295
      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
G
Guy Schalnat 已提交
1296
         text_size = png_ptr->buffer_size;
1297

G
Guy Schalnat 已提交
1298 1299
      else
         text_size = png_ptr->current_text_left;
1300

A
Andreas Dilger 已提交
1301
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
1302
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
1303
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
1304 1305 1306
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
1307
      png_textp text_ptr;
G
Guy Schalnat 已提交
1308 1309 1310
      png_charp text;
      png_charp key;
      int ret;
A
Andreas Dilger 已提交
1311
      png_size_t text_size, key_size;
G
Guy Schalnat 已提交
1312 1313 1314 1315 1316 1317 1318

      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
1319
      png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
1320 1321 1322 1323

      key = png_ptr->current_text;

      for (text = key; *text; text++)
1324
         /* Empty loop */ ;
G
Guy Schalnat 已提交
1325 1326

      /* zTXt can't have zero text */
1327
      if (text >= key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
1328
      {
1329
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1330
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
1331 1332 1333 1334 1335
         return;
      }

      text++;

1336
      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */
G
Guy Schalnat 已提交
1337
      {
1338
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1339
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
1340 1341 1342 1343 1344
         return;
      }

      text++;

A
Andreas Dilger 已提交
1345 1346
      png_ptr->zstream.next_in = (png_bytep )text;
      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
1347
          (text - key));
A
Andreas Dilger 已提交
1348
      png_ptr->zstream.next_out = png_ptr->zbuf;
1349
      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
1350 1351 1352 1353 1354 1355

      key_size = text - key;
      text_size = 0;
      text = NULL;
      ret = Z_STREAM_END;

A
Andreas Dilger 已提交
1356
      while (png_ptr->zstream.avail_in)
G
Guy Schalnat 已提交
1357
      {
A
Andreas Dilger 已提交
1358
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
1359 1360
         if (ret != Z_OK && ret != Z_STREAM_END)
         {
A
Andreas Dilger 已提交
1361 1362
            inflateReset(&png_ptr->zstream);
            png_ptr->zstream.avail_in = 0;
1363
            png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1364 1365
            png_free(png_ptr, key);
            png_free(png_ptr, text);
G
Guy Schalnat 已提交
1366 1367
            return;
         }
A
Andreas Dilger 已提交
1368
         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
G
Guy Schalnat 已提交
1369
         {
A
Andreas Dilger 已提交
1370
            if (text == NULL)
G
Guy Schalnat 已提交
1371
            {
A
Andreas Dilger 已提交
1372
               text = (png_charp)png_malloc(png_ptr,
1373 1374
                   (png_ptr->zbuf_size
                   - png_ptr->zstream.avail_out + key_size + 1));
1375

1376
               png_memcpy(text + key_size, png_ptr->zbuf,
1377
                   png_ptr->zbuf_size - png_ptr->zstream.avail_out);
1378

1379
               png_memcpy(text, key, key_size);
1380

1381
               text_size = key_size + png_ptr->zbuf_size -
1382
                   png_ptr->zstream.avail_out;
1383

1384
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
1385 1386 1387 1388 1389 1390
            }
            else
            {
               png_charp tmp;

               tmp = text;
1391
               text = (png_charp)png_malloc(png_ptr, text_size +
1392 1393
                   (png_ptr->zbuf_size 
                   - png_ptr->zstream.avail_out + 1));
1394

1395 1396
               png_memcpy(text, tmp, text_size);
               png_free(png_ptr, tmp);
1397

1398
               png_memcpy(text + text_size, png_ptr->zbuf,
1399
                   png_ptr->zbuf_size - png_ptr->zstream.avail_out);
1400

1401 1402
               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
1403 1404 1405
            }
            if (ret != Z_STREAM_END)
            {
A
Andreas Dilger 已提交
1406 1407
               png_ptr->zstream.next_out = png_ptr->zbuf;
               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
            }
         }
         else
         {
            break;
         }

         if (ret == Z_STREAM_END)
            break;
      }

A
Andreas Dilger 已提交
1419 1420
      inflateReset(&png_ptr->zstream);
      png_ptr->zstream.avail_in = 0;
G
Guy Schalnat 已提交
1421 1422 1423

      if (ret != Z_STREAM_END)
      {
1424
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1425 1426
         png_free(png_ptr, key);
         png_free(png_ptr, text);
G
Guy Schalnat 已提交
1427 1428 1429
         return;
      }

1430
      png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1431
      png_free(png_ptr, key);
G
Guy Schalnat 已提交
1432
      key = text;
A
Andreas Dilger 已提交
1433
      text += key_size;
G
Guy Schalnat 已提交
1434

1435 1436
      text_ptr = (png_textp)png_malloc(png_ptr,
          png_sizeof(png_text));
1437 1438
      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
      text_ptr->key = key;
1439
      text_ptr->itxt_length = 0;
1440 1441
      text_ptr->lang = NULL;
      text_ptr->lang_key = NULL;
1442
      text_ptr->text = text;
1443

1444
      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1445

1446
      png_free(png_ptr, key);
1447
      png_free(png_ptr, text_ptr);
1448 1449

      if (ret)
1450
         png_warning(png_ptr, "Insufficient memory to store text chunk");
1451 1452 1453 1454
   }
}
#endif

1455
#ifdef PNG_READ_iTXt_SUPPORTED
1456
void /* PRIVATE */
1457
png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
1458
    length)
1459
{
1460
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1461 1462
      {
         png_error(png_ptr, "Out of place iTXt");
1463
         info_ptr = info_ptr; /* To quiet some compiler warnings */
1464 1465 1466 1467 1468
      }

#ifdef PNG_MAX_MALLOC_64K
   png_ptr->skip_length = 0;  /* This may not be necessary */

1469
   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
1470 1471 1472 1473 1474 1475 1476 1477
   {
      png_warning(png_ptr, "iTXt chunk too large to fit in memory");
      png_ptr->skip_length = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
   }
#endif

   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
1478
       (png_size_t)(length + 1));
1479 1480 1481 1482 1483
   png_ptr->current_text[length] = '\0';
   png_ptr->current_text_ptr = png_ptr->current_text;
   png_ptr->current_text_size = (png_size_t)length;
   png_ptr->current_text_left = (png_size_t)length;
   png_ptr->process_mode = PNG_READ_iTXt_MODE;
1484 1485
}

1486
void /* PRIVATE */
1487 1488
png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
{
1489

1490 1491 1492 1493 1494 1495
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
      png_size_t text_size;

      if (png_ptr->buffer_size < png_ptr->current_text_left)
         text_size = png_ptr->buffer_size;
1496

1497 1498
      else
         text_size = png_ptr->current_text_left;
1499

1500 1501 1502 1503 1504 1505 1506 1507
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
      png_ptr->current_text_left -= text_size;
      png_ptr->current_text_ptr += text_size;
   }
   if (!(png_ptr->current_text_left))
   {
      png_textp text_ptr;
      png_charp key;
1508
      int comp_flag;
1509 1510 1511
      png_charp lang;
      png_charp lang_key;
      png_charp text;
1512
      int ret;
1513 1514 1515 1516 1517 1518 1519 1520 1521

      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

      png_push_crc_finish(png_ptr);

1522
#ifdef PNG_MAX_MALLOC_64K
1523 1524 1525 1526
      if (png_ptr->skip_length)
         return;
#endif

1527
      key = png_ptr->current_text;
1528

1529
      for (lang = key; *lang; lang++)
1530
         /* Empty loop */ ;
1531

1532
      if (lang < key + png_ptr->current_text_size - 3)
1533
         lang++;
1534

1535
      comp_flag = *lang++;
1536
      lang++;     /* Skip comp_type, always zero */
1537 1538

      for (lang_key = lang; *lang_key; lang_key++)
1539
         /* Empty loop */ ;
1540

1541
      lang_key++;        /* Skip NUL separator */
1542

1543
      text=lang_key;
1544

1545 1546
      if (lang_key < key + png_ptr->current_text_size - 1)
      {
1547 1548
         for (; *text; text++)
            /* Empty loop */ ;
1549
      }
1550

1551
      if (text < key + png_ptr->current_text_size)
1552 1553
         text++;

1554
      text_ptr = (png_textp)png_malloc(png_ptr,
1555
          png_sizeof(png_text));
1556

1557
      text_ptr->compression = comp_flag + 2;
A
Andreas Dilger 已提交
1558
      text_ptr->key = key;
1559 1560
      text_ptr->lang = lang;
      text_ptr->lang_key = lang_key;
A
Andreas Dilger 已提交
1561
      text_ptr->text = text;
1562 1563
      text_ptr->text_length = 0;
      text_ptr->itxt_length = png_strlen(text);
A
Andreas Dilger 已提交
1564

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

1567 1568
      png_ptr->current_text = NULL;

A
Andreas Dilger 已提交
1569
      png_free(png_ptr, text_ptr);
1570
      if (ret)
1571
         png_warning(png_ptr, "Insufficient memory to store iTXt chunk");
G
Guy Schalnat 已提交
1572
   }
G
Guy Schalnat 已提交
1573 1574 1575
}
#endif

A
Andreas Dilger 已提交
1576
/* This function is called when we haven't found a handler for this
1577 1578
 * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk
 * name or a critical chunk), the chunk is (currently) silently ignored.
1579
 */
1580
void /* PRIVATE */
1581
png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
1582
    length)
A
Andreas Dilger 已提交
1583
{
1584
   png_uint_32 skip = 0;
A
Andreas Dilger 已提交
1585 1586 1587

   if (!(png_ptr->chunk_name[0] & 0x20))
   {
1588
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
1589
      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
1590
          PNG_HANDLE_CHUNK_ALWAYS
1591
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1592
          && png_ptr->read_user_chunk_fn == NULL
1593
#endif
1594
          )
1595
#endif
1596 1597
         png_chunk_error(png_ptr, "unknown critical chunk");

1598
      info_ptr = info_ptr; /* To quiet some compiler warnings */
A
Andreas Dilger 已提交
1599 1600
   }

1601
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
1602 1603 1604
   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
   {
#ifdef PNG_MAX_MALLOC_64K
1605 1606
      if (length > (png_uint_32)65535L)
      {
1607 1608 1609
         png_warning(png_ptr, "unknown chunk too large to fit in memory");
         skip = length - (png_uint_32)65535L;
         length = (png_uint_32)65535L;
1610
      }
1611
#endif
1612
      png_memcpy((png_charp)png_ptr->unknown_chunk.name,
1613 1614
          (png_charp)png_ptr->chunk_name, 
          png_sizeof(png_ptr->unknown_chunk.name));
1615
      png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1]
1616
          = '\0';
1617 1618

      png_ptr->unknown_chunk.size = (png_size_t)length;
1619

1620 1621
      if (length == 0)
         png_ptr->unknown_chunk.data = NULL;
1622

1623 1624 1625
      else
      {
         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
1626
             (png_size_t)length);
1627 1628
         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
      }
1629

1630
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1631 1632
      if (png_ptr->read_user_chunk_fn != NULL)
      {
1633
         /* Callback to user unknown chunk handler */
1634 1635
         int ret;
         ret = (*(png_ptr->read_user_chunk_fn))
1636
             (png_ptr, &png_ptr->unknown_chunk);
1637

1638 1639
         if (ret < 0)
            png_chunk_error(png_ptr, "error in user chunk");
1640

1641 1642 1643 1644
         if (ret == 0)
         {
            if (!(png_ptr->chunk_name[0] & 0x20))
               if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
1645
                   PNG_HANDLE_CHUNK_ALWAYS)
1646 1647
                  png_chunk_error(png_ptr, "unknown critical chunk");
            png_set_unknown_chunks(png_ptr, info_ptr,
1648
                &png_ptr->unknown_chunk, 1);
1649 1650
         }
      }
1651

1652
      else
1653
#endif
1654
         png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
1655 1656
      png_free(png_ptr, png_ptr->unknown_chunk.data);
      png_ptr->unknown_chunk.data = NULL;
1657
   }
1658

1659 1660 1661 1662
   else
#endif
      skip=length;
   png_push_crc_skip(png_ptr, skip);
A
Andreas Dilger 已提交
1663 1664
}

1665
void /* PRIVATE */
A
Andreas Dilger 已提交
1666
png_push_have_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1667
{
A
Andreas Dilger 已提交
1668
   if (png_ptr->info_fn != NULL)
A
Andreas Dilger 已提交
1669
      (*(png_ptr->info_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1670 1671
}

1672
void /* PRIVATE */
A
Andreas Dilger 已提交
1673
png_push_have_end(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1674
{
A
Andreas Dilger 已提交
1675
   if (png_ptr->end_fn != NULL)
A
Andreas Dilger 已提交
1676
      (*(png_ptr->end_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1677 1678
}

1679
void /* PRIVATE */
G
Guy Schalnat 已提交
1680 1681
png_push_have_row(png_structp png_ptr, png_bytep row)
{
A
Andreas Dilger 已提交
1682
   if (png_ptr->row_fn != NULL)
G
Guy Schalnat 已提交
1683 1684
      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
         (int)png_ptr->pass);
G
Guy Schalnat 已提交
1685 1686
}

1687
void PNGAPI
A
Andreas Dilger 已提交
1688
png_progressive_combine_row (png_structp png_ptr,
1689
    png_bytep old_row, png_bytep new_row)
G
Guy Schalnat 已提交
1690
{
1691
   PNG_CONST int FARDATA png_pass_dsp_mask[7] =
1692
      {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
1693

1694 1695 1696
   if (png_ptr == NULL)
      return;

1697
   if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
A
Andreas Dilger 已提交
1698
      png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
G
Guy Schalnat 已提交
1699 1700
}

1701
void PNGAPI
G
Guy Schalnat 已提交
1702
png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
1703 1704
    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
    png_progressive_end_ptr end_fn)
G
Guy Schalnat 已提交
1705
{
1706 1707 1708
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
1709 1710
   png_ptr->info_fn = info_fn;
   png_ptr->row_fn = row_fn;
G
Guy Schalnat 已提交
1711
   png_ptr->end_fn = end_fn;
G
Guy Schalnat 已提交
1712

1713
   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
G
Guy Schalnat 已提交
1714 1715
}

1716
png_voidp PNGAPI
A
Andreas Dilger 已提交
1717
png_get_progressive_ptr(png_structp png_ptr)
G
Guy Schalnat 已提交
1718
{
1719 1720 1721
   if (png_ptr == NULL)
      return (NULL);

A
Andreas Dilger 已提交
1722
   return png_ptr->io_ptr;
G
Guy Schalnat 已提交
1723
}
G
Guy Schalnat 已提交
1724
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */