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

/* pngpread.c - read a png file in push mode
3
 *
4
 * Last changed in libpng 1.4.0 [May 16, 2009]
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2009 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9
 */
G
Guy Schalnat 已提交
10 11

#include "png.h"
G
Guy Schalnat 已提交
12
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
13
#include "pngpriv.h"
G
Guy Schalnat 已提交
14

15 16 17 18 19 20 21 22 23 24 25
/* push model modes */
#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

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

G
Guy Schalnat 已提交
33
   png_push_restore_buffer(png_ptr, buffer, buffer_size);
G
Guy Schalnat 已提交
34

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

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

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

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

G
Guy Schalnat 已提交
64 65
      case PNG_READ_IDAT_MODE:
      {
G
Guy Schalnat 已提交
66
         png_push_read_IDAT(png_ptr);
G
Guy Schalnat 已提交
67 68
         break;
      }
69

G
Guy Schalnat 已提交
70
#if defined(PNG_READ_tEXt_SUPPORTED)
G
Guy Schalnat 已提交
71 72
      case PNG_READ_tEXt_MODE:
      {
A
Andreas Dilger 已提交
73
         png_push_read_tEXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
74 75
         break;
      }
76

G
Guy Schalnat 已提交
77
#endif
G
Guy Schalnat 已提交
78 79 80
#if defined(PNG_READ_zTXt_SUPPORTED)
      case PNG_READ_zTXt_MODE:
      {
A
Andreas Dilger 已提交
81
         png_push_read_zTXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
82 83
         break;
      }
84

85 86 87 88 89 90 91
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
      case PNG_READ_iTXt_MODE:
      {
         png_push_read_iTXt(png_ptr, info_ptr);
         break;
      }
92

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

G
Guy Schalnat 已提交
100 101 102 103 104 105
      default:
      {
         png_ptr->buffer_size = 0;
         break;
      }
   }
G
Guy Schalnat 已提交
106 107
}

A
Andreas Dilger 已提交
108 109
/* Read any remaining signature bytes from the stream and compare them with
 * the correct PNG signature.  It is possible that this routine is called
110 111 112
 * 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 已提交
113
 */
114
void /* PRIVATE */
A
Andreas Dilger 已提交
115
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
116
{
A
Andreas Dilger 已提交
117 118
   png_size_t num_checked = png_ptr->sig_bytes,
             num_to_check = 8 - num_checked;
G
Guy Schalnat 已提交
119

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

125
   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
A
Andreas Dilger 已提交
126
      num_to_check);
127
   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
G
Guy Schalnat 已提交
128

A
Andreas Dilger 已提交
129
   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
G
Guy Schalnat 已提交
130
   {
A
Andreas Dilger 已提交
131 132 133 134 135
      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 已提交
136 137 138
   }
   else
   {
A
Andreas Dilger 已提交
139 140 141 142
      if (png_ptr->sig_bytes >= 8)
      {
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
      }
G
Guy Schalnat 已提交
143
   }
G
Guy Schalnat 已提交
144 145
}

146
void /* PRIVATE */
A
Andreas Dilger 已提交
147
png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
148
{
149
#ifdef PNG_USE_LOCAL_ARRAYS
150 151 152 153
      PNG_CONST PNG_IHDR;
      PNG_CONST PNG_IDAT;
      PNG_CONST PNG_IEND;
      PNG_CONST PNG_PLTE;
154
#if defined(PNG_READ_bKGD_SUPPORTED)
155
      PNG_CONST PNG_bKGD;
156 157
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
158
      PNG_CONST PNG_cHRM;
159 160
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
161
      PNG_CONST PNG_gAMA;
162 163
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
164
      PNG_CONST PNG_hIST;
165
#endif
166
#if defined(PNG_READ_iCCP_SUPPORTED)
167
      PNG_CONST PNG_iCCP;
168 169
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
170
      PNG_CONST PNG_iTXt;
171
#endif
172
#if defined(PNG_READ_oFFs_SUPPORTED)
173
      PNG_CONST PNG_oFFs;
174 175
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
176
      PNG_CONST PNG_pCAL;
177 178
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
179
      PNG_CONST PNG_pHYs;
180 181
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
182
      PNG_CONST PNG_sBIT;
183
#endif
184
#if defined(PNG_READ_sCAL_SUPPORTED)
185
      PNG_CONST PNG_sCAL;
186
#endif
187
#if defined(PNG_READ_sRGB_SUPPORTED)
188
      PNG_CONST PNG_sRGB;
189
#endif
190
#if defined(PNG_READ_sPLT_SUPPORTED)
191
      PNG_CONST PNG_sPLT;
192
#endif
193
#if defined(PNG_READ_tEXt_SUPPORTED)
194
      PNG_CONST PNG_tEXt;
195 196
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
197
      PNG_CONST PNG_tIME;
198 199
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
200
      PNG_CONST PNG_tRNS;
201 202
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
203
      PNG_CONST PNG_zTXt;
204 205
#endif
#endif /* PNG_USE_LOCAL_ARRAYS */
A
Andreas Dilger 已提交
206
   /* First we make sure we have enough data for the 4 byte chunk name
207 208 209 210 211
    * 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).
    */
212
   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
213
   {
A
Andreas Dilger 已提交
214
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
215 216 217 218 219 220 221

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

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

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

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

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

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

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

256 257 258 259 260
      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);
   }
261

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

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

274
      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
275

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

279 280 281 282
      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");
283

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

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

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

      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");
314

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

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

G
Guy Schalnat 已提交
325
      png_ptr->idat_size = png_ptr->push_length;
A
Andreas Dilger 已提交
326
      png_ptr->mode |= PNG_HAVE_IDAT;
G
Guy Schalnat 已提交
327
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
A
Andreas Dilger 已提交
328 329 330
      png_push_have_info(png_ptr, info_ptr);
      png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
      png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
331 332
      return;
   }
333

G
Guy Schalnat 已提交
334
#if defined(PNG_READ_gAMA_SUPPORTED)
A
Andreas Dilger 已提交
335
   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
G
Guy Schalnat 已提交
336
   {
337 338 339
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
340
         return;
341
      }
342

A
Andreas Dilger 已提交
343
      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
344
   }
345

G
Guy Schalnat 已提交
346 347
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
A
Andreas Dilger 已提交
348
   else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
G
Guy Schalnat 已提交
349
   {
350 351 352
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
353
         return;
354
      }
355

A
Andreas Dilger 已提交
356
      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
357
   }
358

G
Guy Schalnat 已提交
359 360
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
A
Andreas Dilger 已提交
361
   else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
G
Guy Schalnat 已提交
362
   {
363 364 365
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
366
         return;
367
      }
368

A
Andreas Dilger 已提交
369
      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
370
   }
371

G
Guy Schalnat 已提交
372
#endif
373 374 375
#if defined(PNG_READ_sRGB_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
   {
376 377 378
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
379
         return;
380
      }
381

382 383
      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
   }
384

385
#endif
386 387 388
#if defined(PNG_READ_iCCP_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
   {
389 390 391
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
392
         return;
393
      }
394

395 396
      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
   }
397

398 399 400 401
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
   {
402 403 404
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
405
         return;
406
      }
407

408 409
      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
   }
410

411
#endif
G
Guy Schalnat 已提交
412
#if defined(PNG_READ_tRNS_SUPPORTED)
A
Andreas Dilger 已提交
413
   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
G
Guy Schalnat 已提交
414
   {
415 416 417
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
418
         return;
419
      }
420

A
Andreas Dilger 已提交
421
      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
422
   }
423

G
Guy Schalnat 已提交
424 425
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
A
Andreas Dilger 已提交
426
   else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
G
Guy Schalnat 已提交
427
   {
428 429 430
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
431
         return;
432
      }
433

A
Andreas Dilger 已提交
434
      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
435
   }
436

G
Guy Schalnat 已提交
437 438
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
A
Andreas Dilger 已提交
439
   else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
G
Guy Schalnat 已提交
440
   {
441 442 443
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
444
         return;
445
      }
446

A
Andreas Dilger 已提交
447
      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
448
   }
449

G
Guy Schalnat 已提交
450 451
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
A
Andreas Dilger 已提交
452
   else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
G
Guy Schalnat 已提交
453 454 455 456 457 458
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
459

A
Andreas Dilger 已提交
460
      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
461
   }
462

G
Guy Schalnat 已提交
463 464
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
A
Andreas Dilger 已提交
465
   else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
G
Guy Schalnat 已提交
466
   {
467 468 469
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
470
         return;
471
      }
472

A
Andreas Dilger 已提交
473
      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
474
   }
G
Guy Schalnat 已提交
475
#endif
476

A
Andreas Dilger 已提交
477 478 479
#if defined(PNG_READ_pCAL_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
   {
480 481 482
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
A
Andreas Dilger 已提交
483
         return;
484
      }
485

A
Andreas Dilger 已提交
486 487
      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
488

A
Andreas Dilger 已提交
489
#endif
490 491 492
#if defined(PNG_READ_sCAL_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
   {
493 494 495
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
496
         return;
497
      }
498

499 500
      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
501

502
#endif
G
Guy Schalnat 已提交
503
#if defined(PNG_READ_tIME_SUPPORTED)
A
Andreas Dilger 已提交
504
   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
G
Guy Schalnat 已提交
505
   {
506 507 508
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
509
         return;
510
      }
511

A
Andreas Dilger 已提交
512
      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
513
   }
514

G
Guy Schalnat 已提交
515 516
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
A
Andreas Dilger 已提交
517
   else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
G
Guy Schalnat 已提交
518
   {
519 520 521
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
522
         return;
523
      }
524

A
Andreas Dilger 已提交
525
      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
526
   }
527

G
Guy Schalnat 已提交
528 529
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
A
Andreas Dilger 已提交
530
   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
G
Guy Schalnat 已提交
531
   {
532 533 534
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
535
         return;
536
      }
537

A
Andreas Dilger 已提交
538
      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
539
   }
540

541 542
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
543
   else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
544
   {
545 546 547
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
548
         return;
549
      }
550

551 552
      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
   }
553

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

565
   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
566 567
}

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

575
void /* PRIVATE */
A
Andreas Dilger 已提交
576
png_push_crc_finish(png_structp png_ptr)
G
Guy Schalnat 已提交
577
{
G
Guy Schalnat 已提交
578 579
   if (png_ptr->skip_length && png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
580
      png_size_t save_size;
G
Guy Schalnat 已提交
581

A
Andreas Dilger 已提交
582 583
      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 已提交
584 585 586 587 588 589 590 591
      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 已提交
592
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
593 594 595
   }
   if (png_ptr->skip_length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
596
      png_size_t save_size;
G
Guy Schalnat 已提交
597

A
Andreas Dilger 已提交
598 599
      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 已提交
600 601 602 603 604 605 606 607
      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 已提交
608
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
609 610 611 612 613 614 615 616
   }
   if (!png_ptr->skip_length)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
A
Andreas Dilger 已提交
617 618

      png_crc_finish(png_ptr, 0);
A
Andreas Dilger 已提交
619
      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
620
   }
G
Guy Schalnat 已提交
621 622
}

623
void PNGAPI
A
Andreas Dilger 已提交
624
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
G
Guy Schalnat 已提交
625
{
G
Guy Schalnat 已提交
626 627
   png_bytep ptr;

628 629 630
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
631 632 633
   ptr = buffer;
   if (png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
634
      png_size_t save_size;
G
Guy Schalnat 已提交
635 636 637 638 639 640

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

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

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

G
Guy Schalnat 已提交
655 656 657
      else
         save_size = png_ptr->current_buffer_size;

A
Andreas Dilger 已提交
658
      png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
659 660
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
661
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
662
   }
G
Guy Schalnat 已提交
663 664
}

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

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

690
      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
691 692 693 694
         (png_ptr->current_buffer_size + 256))
      {
        png_error(png_ptr, "Potential overflow of save_buffer");
      }
695

A
Andreas Dilger 已提交
696
      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
G
Guy Schalnat 已提交
697
      old_buffer = png_ptr->save_buffer;
698 699
      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
         (png_size_t)new_max);
700 701 702
      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 已提交
703 704 705
   }
   if (png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
706 707
      png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
G
Guy Schalnat 已提交
708 709 710 711 712
      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 已提交
713 714
}

715
void /* PRIVATE */
G
Guy Schalnat 已提交
716
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
717
   png_size_t buffer_length)
G
Guy Schalnat 已提交
718
{
G
Guy Schalnat 已提交
719 720 721 722
   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 已提交
723 724
}

725
void /* PRIVATE */
G
Guy Schalnat 已提交
726
png_push_read_IDAT(png_structp png_ptr)
G
Guy Schalnat 已提交
727
{
728
#ifdef PNG_USE_LOCAL_ARRAYS
729
   PNG_CONST PNG_IDAT;
730
#endif
731
   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
732
   {
A
Andreas Dilger 已提交
733
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
734 735 736 737 738 739 740

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

A
Andreas Dilger 已提交
741
      png_push_fill_buffer(png_ptr, chunk_length, 4);
742
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
743
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
744
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
745
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
A
Andreas Dilger 已提交
746

747
      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
748
      {
A
Andreas Dilger 已提交
749
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
750
         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
751 752 753 754 755 756 757 758
            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 已提交
759
      png_size_t save_size;
G
Guy Schalnat 已提交
760

A
Andreas Dilger 已提交
761
      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
762 763
      {
         save_size = (png_size_t)png_ptr->idat_size;
764

765
         /* check for overflow */
766
         if ((png_uint_32)save_size != png_ptr->idat_size)
767 768
            png_error(png_ptr, "save_size overflowed in pngpread");
      }
G
Guy Schalnat 已提交
769 770 771 772
      else
         save_size = png_ptr->save_buffer_size;

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

774 775
      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
         png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
776

G
Guy Schalnat 已提交
777 778 779
      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
780
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
781 782 783
   }
   if (png_ptr->idat_size && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
784
      png_size_t save_size;
G
Guy Schalnat 已提交
785

A
Andreas Dilger 已提交
786
      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
787 788
      {
         save_size = (png_size_t)png_ptr->idat_size;
789

790
         /* check for overflow */
791
         if ((png_uint_32)save_size != png_ptr->idat_size)
792 793
            png_error(png_ptr, "save_size overflowed in pngpread");
      }
G
Guy Schalnat 已提交
794 795 796 797
      else
         save_size = png_ptr->current_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
798 799
      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
        png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
800 801 802 803

      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
804
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
805 806 807 808 809 810 811 812 813
   }
   if (!png_ptr->idat_size)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
814
      png_crc_finish(png_ptr, 0);
815
      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
816
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
817
   }
G
Guy Schalnat 已提交
818 819
}

820
void /* PRIVATE */
G
Guy Schalnat 已提交
821
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
822
   png_size_t buffer_length)
G
Guy Schalnat 已提交
823
{
G
Guy Schalnat 已提交
824 825
   int ret;

G
Guy Schalnat 已提交
826
   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
827
      png_benign_error(png_ptr, "Extra compression data");
G
Guy Schalnat 已提交
828

A
Andreas Dilger 已提交
829 830
   png_ptr->zstream.next_in = buffer;
   png_ptr->zstream.avail_in = (uInt)buffer_length;
831
   for (;;)
G
Guy Schalnat 已提交
832
   {
A
Andreas Dilger 已提交
833
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
834
      if (ret != Z_OK)
G
Guy Schalnat 已提交
835
      {
836
         if (ret == Z_STREAM_END)
G
Guy Schalnat 已提交
837
         {
838
            if (png_ptr->zstream.avail_in)
839
               png_benign_error(png_ptr, "Extra compressed data");
840

841 842 843 844 845 846 847 848
            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 已提交
849
         }
850 851
         else if (ret == Z_BUF_ERROR)
            break;
852

853 854
         else
            png_error(png_ptr, "Decompression Error");
G
Guy Schalnat 已提交
855
      }
A
Andreas Dilger 已提交
856
      if (!(png_ptr->zstream.avail_out))
G
Guy Schalnat 已提交
857
      {
858 859 860 861 862
         if ((
#if defined(PNG_READ_INTERLACING_SUPPORTED)
             png_ptr->interlaced && png_ptr->pass > 6) ||
             (!png_ptr->interlaced &&
#endif
863
             png_ptr->row_number == png_ptr->num_rows))
864
         {
865 866
           if (png_ptr->zstream.avail_in)
             png_warning(png_ptr, "Too much data in IDAT chunks");
867 868 869
           png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
           break;
         }
G
Guy Schalnat 已提交
870
         png_push_process_row(png_ptr);
A
Andreas Dilger 已提交
871 872
         png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
         png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
873
      }
874

A
Andreas Dilger 已提交
875 876 877
      else
         break;
   }
G
Guy Schalnat 已提交
878 879
}

880
void /* PRIVATE */
G
Guy Schalnat 已提交
881 882
png_push_process_row(png_structp png_ptr)
{
G
Guy Schalnat 已提交
883
   png_ptr->row_info.color_type = png_ptr->color_type;
G
Guy Schalnat 已提交
884 885 886 887
   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;
888

889 890
   png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
       png_ptr->row_info.width);
G
Guy Schalnat 已提交
891

G
Guy Schalnat 已提交
892 893 894
   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 已提交
895

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

898
   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
G
Guy Schalnat 已提交
899 900 901
      png_do_read_transformations(png_ptr);

#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
902
   /* blow up interlaced rows to full size */
A
Andreas Dilger 已提交
903
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
G
Guy Schalnat 已提交
904 905
   {
      if (png_ptr->pass < 6)
906
/*       old interface (pre-1.0.9):
G
Guy Schalnat 已提交
907
         png_do_read_interlace(&(png_ptr->row_info),
A
Andreas Dilger 已提交
908
            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
909 910
 */
         png_do_read_interlace(png_ptr);
G
Guy Schalnat 已提交
911

912 913
    switch (png_ptr->pass)
    {
G
Guy Schalnat 已提交
914 915 916 917 918 919
         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);
920
               png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */
G
Guy Schalnat 已提交
921
            }
922

923
            if (png_ptr->pass == 2) /* pass 1 might be empty */
924 925 926
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
927
                  png_push_have_row(png_ptr, NULL);
928 929 930
                  png_read_push_finish_row(png_ptr);
               }
            }
931

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

941 942
            if (png_ptr->pass == 6 && png_ptr->height <= 4)
            {
943
                png_push_have_row(png_ptr, NULL);
944 945
                png_read_push_finish_row(png_ptr);
            }
946

G
Guy Schalnat 已提交
947 948
            break;
         }
949

G
Guy Schalnat 已提交
950 951 952 953 954 955 956 957
         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);
            }
958

959
            if (png_ptr->pass == 2) /* skip top 4 generated rows */
G
Guy Schalnat 已提交
960 961 962
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
963
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
964 965 966
                  png_read_push_finish_row(png_ptr);
               }
            }
967

G
Guy Schalnat 已提交
968 969
            break;
         }
970

G
Guy Schalnat 已提交
971 972 973
         case 2:
         {
            int i;
974

G
Guy Schalnat 已提交
975 976 977 978 979
            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);
            }
980

G
Guy Schalnat 已提交
981 982
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
983
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
984 985
               png_read_push_finish_row(png_ptr);
            }
986

987
            if (png_ptr->pass == 4) /* pass 3 might be empty */
988 989 990
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
991
                  png_push_have_row(png_ptr, NULL);
992 993 994
                  png_read_push_finish_row(png_ptr);
               }
            }
995

G
Guy Schalnat 已提交
996 997
            break;
         }
998

G
Guy Schalnat 已提交
999 1000 1001
         case 3:
         {
            int i;
1002

G
Guy Schalnat 已提交
1003 1004 1005 1006 1007
            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);
            }
1008

1009
            if (png_ptr->pass == 4) /* skip top two generated rows */
G
Guy Schalnat 已提交
1010 1011 1012
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
1013
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1014 1015 1016
                  png_read_push_finish_row(png_ptr);
               }
            }
1017

G
Guy Schalnat 已提交
1018 1019
            break;
         }
1020

G
Guy Schalnat 已提交
1021 1022 1023
         case 4:
         {
            int i;
1024

G
Guy Schalnat 已提交
1025 1026 1027 1028 1029
            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);
            }
1030

G
Guy Schalnat 已提交
1031 1032
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
1033
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1034 1035
               png_read_push_finish_row(png_ptr);
            }
1036

1037
            if (png_ptr->pass == 6) /* pass 5 might be empty */
1038
            {
1039
               png_push_have_row(png_ptr, NULL);
1040 1041
               png_read_push_finish_row(png_ptr);
            }
1042

G
Guy Schalnat 已提交
1043 1044
            break;
         }
1045

G
Guy Schalnat 已提交
1046 1047 1048
         case 5:
         {
            int i;
1049

G
Guy Schalnat 已提交
1050 1051 1052 1053 1054
            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);
            }
1055

1056
            if (png_ptr->pass == 6) /* skip top generated row */
G
Guy Schalnat 已提交
1057
            {
1058
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1059 1060
               png_read_push_finish_row(png_ptr);
            }
1061

G
Guy Schalnat 已提交
1062 1063 1064 1065 1066 1067
            break;
         }
         case 6:
         {
            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
            png_read_push_finish_row(png_ptr);
1068

G
Guy Schalnat 已提交
1069 1070
            if (png_ptr->pass != 6)
               break;
1071

1072
            png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
1073 1074 1075 1076 1077
            png_read_push_finish_row(png_ptr);
         }
      }
   }
   else
G
Guy Schalnat 已提交
1078
#endif
G
Guy Schalnat 已提交
1079 1080 1081 1082
   {
      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
      png_read_push_finish_row(png_ptr);
   }
G
Guy Schalnat 已提交
1083 1084
}

1085
void /* PRIVATE */
G
Guy Schalnat 已提交
1086 1087
png_read_push_finish_row(png_structp png_ptr)
{
1088
#ifdef PNG_USE_LOCAL_ARRAYS
1089
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1090

1091
   /* Start of interlace block */
1092
   PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
1093

1094
   /* Offset to next interlace block */
1095
   PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
1096

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

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

1103 1104
   /* Height of interlace block.  This is not currently used - if you need
    * it, uncomment it here and in png.h
1105
   PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
1106
   */
1107
#endif
1108

G
Guy Schalnat 已提交
1109 1110
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
1111
      return;
G
Guy Schalnat 已提交
1112 1113 1114 1115

   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
1116 1117
      png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);

G
Guy Schalnat 已提交
1118 1119 1120
      do
      {
         png_ptr->pass++;
1121 1122 1123 1124 1125
         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))
           png_ptr->pass++;

1126 1127
         if (png_ptr->pass > 7)
            png_ptr->pass--;
1128

G
Guy Schalnat 已提交
1129 1130
         if (png_ptr->pass >= 7)
            break;
1131

G
Guy Schalnat 已提交
1132 1133 1134 1135
         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];
1136

1137
         png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
1138
            png_ptr->iwidth) + 1;
1139

G
Guy Schalnat 已提交
1140 1141
         if (png_ptr->transformations & PNG_INTERLACE)
            break;
1142 1143 1144 1145 1146 1147 1148

         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 已提交
1149 1150 1151 1152
   }
}

#if defined(PNG_READ_tEXt_SUPPORTED)
1153
void /* PRIVATE */
1154 1155
png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
G
Guy Schalnat 已提交
1156
{
1157
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1158 1159
      {
         png_error(png_ptr, "Out of place tEXt");
1160
         info_ptr = info_ptr; /* to quiet some compiler warnings */
1161
      }
A
Andreas Dilger 已提交
1162

A
Andreas Dilger 已提交
1163 1164 1165
#ifdef PNG_MAX_MALLOC_64K
   png_ptr->skip_length = 0;  /* This may not be necessary */

1166
   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
A
Andreas Dilger 已提交
1167 1168
   {
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1169 1170
      png_ptr->skip_length = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
A
Andreas Dilger 已提交
1171 1172 1173
   }
#endif

1174
   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
1175
      (png_size_t)(length + 1));
A
Andreas Dilger 已提交
1176
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
1177
   png_ptr->current_text_ptr = png_ptr->current_text;
1178 1179
   png_ptr->current_text_size = (png_size_t)length;
   png_ptr->current_text_left = (png_size_t)length;
G
Guy Schalnat 已提交
1180
   png_ptr->process_mode = PNG_READ_tEXt_MODE;
G
Guy Schalnat 已提交
1181 1182
}

1183
void /* PRIVATE */
A
Andreas Dilger 已提交
1184
png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1185
{
G
Guy Schalnat 已提交
1186 1187
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
1188
      png_size_t text_size;
G
Guy Schalnat 已提交
1189 1190 1191

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

G
Guy Schalnat 已提交
1193 1194
      else
         text_size = png_ptr->current_text_left;
1195

A
Andreas Dilger 已提交
1196
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
1197
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
1198
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
1199 1200 1201
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
1202
      png_textp text_ptr;
G
Guy Schalnat 已提交
1203 1204
      png_charp text;
      png_charp key;
1205
      int ret;
G
Guy Schalnat 已提交
1206 1207 1208 1209 1210 1211 1212

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

A
Andreas Dilger 已提交
1213 1214 1215 1216 1217 1218
      png_push_crc_finish(png_ptr);

#if defined(PNG_MAX_MALLOC_64K)
      if (png_ptr->skip_length)
         return;
#endif
G
Guy Schalnat 已提交
1219 1220 1221 1222 1223 1224

      key = png_ptr->current_text;

      for (text = key; *text; text++)
         /* empty loop */ ;

1225
      if (text < key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
1226 1227
         text++;

1228 1229
      text_ptr = (png_textp)png_malloc(png_ptr,
         png_sizeof(png_text));
A
Andreas Dilger 已提交
1230 1231
      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
      text_ptr->key = key;
1232
#ifdef PNG_iTXt_SUPPORTED
1233 1234
      text_ptr->lang = NULL;
      text_ptr->lang_key = NULL;
1235
#endif
A
Andreas Dilger 已提交
1236
      text_ptr->text = text;
G
Guy Schalnat 已提交
1237

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

1240
      png_free(png_ptr, key);
A
Andreas Dilger 已提交
1241
      png_free(png_ptr, text_ptr);
1242
      png_ptr->current_text = NULL;
1243 1244

      if (ret)
1245
        png_warning(png_ptr, "Insufficient memory to store text chunk");
G
Guy Schalnat 已提交
1246
   }
G
Guy Schalnat 已提交
1247 1248 1249 1250
}
#endif

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

A
Andreas Dilger 已提交
1261 1262 1263 1264 1265
#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.
    */
1266
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
1267 1268 1269 1270 1271 1272 1273
   {
      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_push_crc_skip(png_ptr, length);
      return;
   }
#endif

1274
   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
1275
      (png_size_t)(length + 1));
A
Andreas Dilger 已提交
1276
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
1277
   png_ptr->current_text_ptr = png_ptr->current_text;
1278 1279
   png_ptr->current_text_size = (png_size_t)length;
   png_ptr->current_text_left = (png_size_t)length;
G
Guy Schalnat 已提交
1280
   png_ptr->process_mode = PNG_READ_zTXt_MODE;
G
Guy Schalnat 已提交
1281 1282
}

1283
void /* PRIVATE */
A
Andreas Dilger 已提交
1284
png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1285
{
G
Guy Schalnat 已提交
1286 1287
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
1288
      png_size_t text_size;
G
Guy Schalnat 已提交
1289

A
Andreas Dilger 已提交
1290
      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
G
Guy Schalnat 已提交
1291
         text_size = png_ptr->buffer_size;
1292

G
Guy Schalnat 已提交
1293 1294
      else
         text_size = png_ptr->current_text_left;
1295

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

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

A
Andreas Dilger 已提交
1314
      png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
1315 1316 1317 1318 1319 1320 1321

      key = png_ptr->current_text;

      for (text = key; *text; text++)
         /* empty loop */ ;

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

      text++;

A
Andreas Dilger 已提交
1331
      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
G
Guy Schalnat 已提交
1332
      {
1333
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1334
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
1335 1336 1337 1338 1339
         return;
      }

      text++;

A
Andreas Dilger 已提交
1340 1341
      png_ptr->zstream.next_in = (png_bytep )text;
      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
G
Guy Schalnat 已提交
1342
         (text - key));
A
Andreas Dilger 已提交
1343
      png_ptr->zstream.next_out = png_ptr->zbuf;
1344
      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
1345 1346 1347 1348 1349 1350

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

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

1371 1372
               png_memcpy(text + key_size, png_ptr->zbuf,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
1373

1374
               png_memcpy(text, key, key_size);
1375

1376 1377
               text_size = key_size + png_ptr->zbuf_size -
                  png_ptr->zstream.avail_out;
1378

1379
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
1380 1381 1382 1383 1384 1385
            }
            else
            {
               png_charp tmp;

               tmp = text;
1386
               text = (png_charp)png_malloc(png_ptr, text_size +
1387
                  (png_ptr->zbuf_size 
1388
                  - png_ptr->zstream.avail_out + 1));
1389

1390 1391
               png_memcpy(text, tmp, text_size);
               png_free(png_ptr, tmp);
1392

1393 1394
               png_memcpy(text + text_size, png_ptr->zbuf,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
1395

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

         if (ret == Z_STREAM_END)
            break;
      }

A
Andreas Dilger 已提交
1414 1415
      inflateReset(&png_ptr->zstream);
      png_ptr->zstream.avail_in = 0;
G
Guy Schalnat 已提交
1416 1417 1418

      if (ret != Z_STREAM_END)
      {
1419
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1420 1421
         png_free(png_ptr, key);
         png_free(png_ptr, text);
G
Guy Schalnat 已提交
1422 1423 1424
         return;
      }

1425
      png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1426
      png_free(png_ptr, key);
G
Guy Schalnat 已提交
1427
      key = text;
A
Andreas Dilger 已提交
1428
      text += key_size;
G
Guy Schalnat 已提交
1429

1430 1431
      text_ptr = (png_textp)png_malloc(png_ptr,
          png_sizeof(png_text));
1432 1433
      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
      text_ptr->key = key;
1434
#ifdef PNG_iTXt_SUPPORTED
1435 1436
      text_ptr->lang = NULL;
      text_ptr->lang_key = NULL;
1437
#endif
1438
      text_ptr->text = text;
1439

1440
      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1441

1442
      png_free(png_ptr, key);
1443
      png_free(png_ptr, text_ptr);
1444 1445

      if (ret)
1446
        png_warning(png_ptr, "Insufficient memory to store text chunk");
1447 1448 1449 1450 1451
   }
}
#endif

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

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

1465
   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
1466 1467 1468 1469 1470 1471 1472 1473
   {
      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,
1474
      (png_size_t)(length + 1));
1475 1476 1477 1478 1479
   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;
1480 1481
}

1482
void /* PRIVATE */
1483 1484
png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
{
1485

1486 1487 1488 1489 1490 1491
   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;
1492

1493 1494
      else
         text_size = png_ptr->current_text_left;
1495

1496 1497 1498 1499 1500 1501 1502 1503
      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;
1504
      int comp_flag;
1505 1506 1507
      png_charp lang;
      png_charp lang_key;
      png_charp text;
1508
      int ret;
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522

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

      png_push_crc_finish(png_ptr);

#if defined(PNG_MAX_MALLOC_64K)
      if (png_ptr->skip_length)
         return;
#endif

1523
      key = png_ptr->current_text;
1524

1525
      for (lang = key; *lang; lang++)
1526 1527
         /* empty loop */ ;

1528
      if (lang < key + png_ptr->current_text_size - 3)
1529
         lang++;
1530

1531 1532 1533 1534 1535
      comp_flag = *lang++;
      lang++;     /* skip comp_type, always zero */

      for (lang_key = lang; *lang_key; lang_key++)
         /* empty loop */ ;
1536

1537 1538
      lang_key++;        /* skip NUL separator */

1539
      text=lang_key;
1540

1541 1542 1543 1544 1545
      if (lang_key < key + png_ptr->current_text_size - 1)
      {
        for (; *text; text++)
           /* empty loop */ ;
      }
1546

1547
      if (text < key + png_ptr->current_text_size)
1548 1549
         text++;

1550 1551
      text_ptr = (png_textp)png_malloc(png_ptr,
         png_sizeof(png_text));
1552

1553
      text_ptr->compression = comp_flag + 2;
A
Andreas Dilger 已提交
1554
      text_ptr->key = key;
1555 1556
      text_ptr->lang = lang;
      text_ptr->lang_key = lang_key;
A
Andreas Dilger 已提交
1557
      text_ptr->text = text;
1558 1559
      text_ptr->text_length = 0;
      text_ptr->itxt_length = png_strlen(text);
A
Andreas Dilger 已提交
1560

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

1563 1564
      png_ptr->current_text = NULL;

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

A
Andreas Dilger 已提交
1572
/* This function is called when we haven't found a handler for this
1573 1574
 * 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.
1575
 */
1576
void /* PRIVATE */
1577 1578
png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
A
Andreas Dilger 已提交
1579
{
1580
   png_uint_32 skip = 0;
A
Andreas Dilger 已提交
1581 1582 1583

   if (!(png_ptr->chunk_name[0] & 0x20))
   {
1584
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
1585 1586
      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
         PNG_HANDLE_CHUNK_ALWAYS
1587
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1588
         && png_ptr->read_user_chunk_fn == NULL
1589 1590
#endif
         )
1591
#endif
1592 1593
         png_chunk_error(png_ptr, "unknown critical chunk");

1594
      info_ptr = info_ptr; /* to quiet some compiler warnings */
A
Andreas Dilger 已提交
1595 1596
   }

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

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

1616 1617
      if (length == 0)
         png_ptr->unknown_chunk.data = NULL;
1618

1619 1620 1621 1622 1623 1624
      else
      {
         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
       (png_size_t)length);
         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
      }
1625

1626
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1627 1628 1629 1630 1631 1632
      if (png_ptr->read_user_chunk_fn != NULL)
      {
         /* callback to user unknown chunk handler */
         int ret;
         ret = (*(png_ptr->read_user_chunk_fn))
           (png_ptr, &png_ptr->unknown_chunk);
1633

1634 1635
         if (ret < 0)
            png_chunk_error(png_ptr, "error in user chunk");
1636

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

1648
      else
1649
#endif
1650 1651 1652
        png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
      png_free(png_ptr, png_ptr->unknown_chunk.data);
      png_ptr->unknown_chunk.data = NULL;
1653
   }
1654

1655 1656 1657 1658
   else
#endif
      skip=length;
   png_push_crc_skip(png_ptr, skip);
A
Andreas Dilger 已提交
1659 1660
}

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

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

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

1683
void PNGAPI
A
Andreas Dilger 已提交
1684 1685
png_progressive_combine_row (png_structp png_ptr,
   png_bytep old_row, png_bytep new_row)
G
Guy Schalnat 已提交
1686
{
1687
#ifdef PNG_USE_LOCAL_ARRAYS
1688
   PNG_CONST int FARDATA png_pass_dsp_mask[7] =
1689
      {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
1690
#endif
1691 1692 1693
   if (png_ptr == NULL)
      return;

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

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

G
Guy Schalnat 已提交
1706 1707
   png_ptr->info_fn = info_fn;
   png_ptr->row_fn = row_fn;
G
Guy Schalnat 已提交
1708
   png_ptr->end_fn = end_fn;
G
Guy Schalnat 已提交
1709

1710
   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
G
Guy Schalnat 已提交
1711 1712
}

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

A
Andreas Dilger 已提交
1719
   return png_ptr->io_ptr;
G
Guy Schalnat 已提交
1720
}
G
Guy Schalnat 已提交
1721
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */