pngpread.c 45.8 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 [August 4, 2008]
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2008 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
   if (png_ptr == NULL || info_ptr == NULL) return;
G
Guy Schalnat 已提交
31
   png_push_restore_buffer(png_ptr, buffer, buffer_size);
G
Guy Schalnat 已提交
32

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

A
Andreas Dilger 已提交
39 40 41
/* What we do with the incoming data depends on what we were previously
 * doing before we ran out of data...
 */
42
void /* PRIVATE */
A
Andreas Dilger 已提交
43
png_process_some_data(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
44
{
45
   if (png_ptr == NULL) return;
G
Guy Schalnat 已提交
46 47 48 49
   switch (png_ptr->process_mode)
   {
      case PNG_READ_SIG_MODE:
      {
A
Andreas Dilger 已提交
50
         png_push_read_sig(png_ptr, info_ptr);
G
Guy Schalnat 已提交
51 52 53 54
         break;
      }
      case PNG_READ_CHUNK_MODE:
      {
A
Andreas Dilger 已提交
55
         png_push_read_chunk(png_ptr, info_ptr);
G
Guy Schalnat 已提交
56 57 58 59
         break;
      }
      case PNG_READ_IDAT_MODE:
      {
G
Guy Schalnat 已提交
60
         png_push_read_IDAT(png_ptr);
G
Guy Schalnat 已提交
61 62
         break;
      }
G
Guy Schalnat 已提交
63
#if defined(PNG_READ_tEXt_SUPPORTED)
G
Guy Schalnat 已提交
64 65
      case PNG_READ_tEXt_MODE:
      {
A
Andreas Dilger 已提交
66
         png_push_read_tEXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
67 68
         break;
      }
G
Guy Schalnat 已提交
69
#endif
G
Guy Schalnat 已提交
70 71 72
#if defined(PNG_READ_zTXt_SUPPORTED)
      case PNG_READ_zTXt_MODE:
      {
A
Andreas Dilger 已提交
73
         png_push_read_zTXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
74 75
         break;
      }
76 77 78 79 80 81 82
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
      case PNG_READ_iTXt_MODE:
      {
         png_push_read_iTXt(png_ptr, info_ptr);
         break;
      }
G
Guy Schalnat 已提交
83 84 85
#endif
      case PNG_SKIP_MODE:
      {
A
Andreas Dilger 已提交
86
         png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
87 88 89 90 91 92 93 94
         break;
      }
      default:
      {
         png_ptr->buffer_size = 0;
         break;
      }
   }
G
Guy Schalnat 已提交
95 96
}

A
Andreas Dilger 已提交
97 98
/* Read any remaining signature bytes from the stream and compare them with
 * the correct PNG signature.  It is possible that this routine is called
99 100 101
 * 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 已提交
102
 */
103
void /* PRIVATE */
A
Andreas Dilger 已提交
104
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
105
{
A
Andreas Dilger 已提交
106 107
   png_size_t num_checked = png_ptr->sig_bytes,
             num_to_check = 8 - num_checked;
G
Guy Schalnat 已提交
108

A
Andreas Dilger 已提交
109
   if (png_ptr->buffer_size < num_to_check)
G
Guy Schalnat 已提交
110
   {
A
Andreas Dilger 已提交
111
      num_to_check = png_ptr->buffer_size;
G
Guy Schalnat 已提交
112 113
   }

114
   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
A
Andreas Dilger 已提交
115
      num_to_check);
116
   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
G
Guy Schalnat 已提交
117

A
Andreas Dilger 已提交
118
   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
G
Guy Schalnat 已提交
119
   {
A
Andreas Dilger 已提交
120 121 122 123 124
      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 已提交
125 126 127
   }
   else
   {
A
Andreas Dilger 已提交
128 129 130 131
      if (png_ptr->sig_bytes >= 8)
      {
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
      }
G
Guy Schalnat 已提交
132
   }
G
Guy Schalnat 已提交
133 134
}

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

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

A
Andreas Dilger 已提交
211
      png_push_fill_buffer(png_ptr, chunk_length, 4);
212
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
213
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
214
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
215
      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
216
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
217 218
   }

219
   if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
220
     if (png_ptr->mode & PNG_AFTER_IDAT)
221 222
        png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;

A
Andreas Dilger 已提交
223
   if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
G
Guy Schalnat 已提交
224
   {
225 226
      if (png_ptr->push_length != 13)
         png_error(png_ptr, "Invalid IHDR length");
227 228 229
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
230
         return;
231
      }
A
Andreas Dilger 已提交
232
      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
233
   }
234 235
   else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
   {
236 237 238
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
239
         return;
240
      }
241 242 243 244 245 246 247 248
      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);
   }
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
   {
249 250 251
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
252
         return;
253
      }
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
      if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
         png_ptr->mode |= PNG_HAVE_IDAT;
      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
      if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
         png_ptr->mode |= PNG_HAVE_PLTE;
      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");
         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
                  !(png_ptr->mode & PNG_HAVE_PLTE))
            png_error(png_ptr, "Missing PLTE before IDAT");
      }
   }
#endif
A
Andreas Dilger 已提交
269
   else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
G
Guy Schalnat 已提交
270
   {
271 272 273
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
A
Andreas Dilger 已提交
274
         return;
275
      }
A
Andreas Dilger 已提交
276
      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
277
   }
278
   else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
279
   {
A
Andreas Dilger 已提交
280
      /* If we reach an IDAT chunk, this means we have read all of the
281 282 283
       * header chunks, and we can start reading the image (or if this
       * is called after the image has been read - we have an error).
       */
284 285 286
     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 &&
287
         !(png_ptr->mode & PNG_HAVE_PLTE))
288 289
       png_error(png_ptr, "Missing PLTE before IDAT");

A
Andreas Dilger 已提交
290 291
      if (png_ptr->mode & PNG_HAVE_IDAT)
      {
292 293 294
         if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
           if (png_ptr->push_length == 0)
              return;
A
Andreas Dilger 已提交
295 296

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

G
Guy Schalnat 已提交
300
      png_ptr->idat_size = png_ptr->push_length;
A
Andreas Dilger 已提交
301
      png_ptr->mode |= PNG_HAVE_IDAT;
G
Guy Schalnat 已提交
302
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
A
Andreas Dilger 已提交
303 304 305
      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 已提交
306 307
      return;
   }
G
Guy Schalnat 已提交
308
#if defined(PNG_READ_gAMA_SUPPORTED)
A
Andreas Dilger 已提交
309
   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
G
Guy Schalnat 已提交
310
   {
311 312 313
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
314
         return;
315
      }
A
Andreas Dilger 已提交
316
      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
317
   }
G
Guy Schalnat 已提交
318 319
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
A
Andreas Dilger 已提交
320
   else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
G
Guy Schalnat 已提交
321
   {
322 323 324
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
325
         return;
326
      }
A
Andreas Dilger 已提交
327
      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
328
   }
G
Guy Schalnat 已提交
329 330
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
A
Andreas Dilger 已提交
331
   else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
G
Guy Schalnat 已提交
332
   {
333 334 335
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
336
         return;
337
      }
A
Andreas Dilger 已提交
338
      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
339
   }
G
Guy Schalnat 已提交
340
#endif
341 342 343
#if defined(PNG_READ_sRGB_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
   {
344 345 346
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
347
         return;
348
      }
349 350 351
      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
352 353 354
#if defined(PNG_READ_iCCP_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
   {
355 356 357
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
358
         return;
359
      }
360 361 362 363 364 365
      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
   {
366 367 368
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
369
         return;
370
      }
371 372 373
      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
G
Guy Schalnat 已提交
374
#if defined(PNG_READ_tRNS_SUPPORTED)
A
Andreas Dilger 已提交
375
   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
G
Guy Schalnat 已提交
376
   {
377 378 379
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
380
         return;
381
      }
A
Andreas Dilger 已提交
382
      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
383
   }
G
Guy Schalnat 已提交
384 385
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
A
Andreas Dilger 已提交
386
   else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
G
Guy Schalnat 已提交
387
   {
388 389 390
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
391
         return;
392
      }
A
Andreas Dilger 已提交
393
      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
394
   }
G
Guy Schalnat 已提交
395 396
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
A
Andreas Dilger 已提交
397
   else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
G
Guy Schalnat 已提交
398
   {
399 400 401
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
402
         return;
403
      }
A
Andreas Dilger 已提交
404
      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
405
   }
G
Guy Schalnat 已提交
406 407
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
A
Andreas Dilger 已提交
408
   else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
G
Guy Schalnat 已提交
409 410 411 412 413 414
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
A
Andreas Dilger 已提交
415
      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
416
   }
G
Guy Schalnat 已提交
417 418
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
A
Andreas Dilger 已提交
419
   else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
G
Guy Schalnat 已提交
420
   {
421 422 423
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
424
         return;
425
      }
A
Andreas Dilger 已提交
426
      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
427
   }
G
Guy Schalnat 已提交
428
#endif
A
Andreas Dilger 已提交
429 430 431
#if defined(PNG_READ_pCAL_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
   {
432 433 434
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
A
Andreas Dilger 已提交
435
         return;
436
      }
A
Andreas Dilger 已提交
437 438 439
      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
440 441 442
#if defined(PNG_READ_sCAL_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
   {
443 444 445
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
446
         return;
447
      }
448 449 450
      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
G
Guy Schalnat 已提交
451
#if defined(PNG_READ_tIME_SUPPORTED)
A
Andreas Dilger 已提交
452
   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
G
Guy Schalnat 已提交
453
   {
454 455 456
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
G
Guy Schalnat 已提交
457
         return;
458
      }
A
Andreas Dilger 已提交
459
      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
460
   }
G
Guy Schalnat 已提交
461 462
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
A
Andreas Dilger 已提交
463
   else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
G
Guy Schalnat 已提交
464
   {
465 466 467
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
468
         return;
469
      }
A
Andreas Dilger 已提交
470
      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
471
   }
G
Guy Schalnat 已提交
472 473
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
A
Andreas Dilger 已提交
474
   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
G
Guy Schalnat 已提交
475
   {
476 477 478
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
479
         return;
480
      }
A
Andreas Dilger 已提交
481
      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
482
   }
483 484
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
485
   else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
486
   {
487 488 489
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
490
         return;
491
      }
492 493
      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
   }
G
Guy Schalnat 已提交
494
#endif
G
Guy Schalnat 已提交
495 496
   else
   {
497 498 499
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
500
         return;
501
      }
A
Andreas Dilger 已提交
502
      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
503
   }
G
Guy Schalnat 已提交
504

505
   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
506 507
}

508
void /* PRIVATE */
A
Andreas Dilger 已提交
509
png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
G
Guy Schalnat 已提交
510
{
G
Guy Schalnat 已提交
511
   png_ptr->process_mode = PNG_SKIP_MODE;
A
Andreas Dilger 已提交
512
   png_ptr->skip_length = skip;
G
Guy Schalnat 已提交
513 514
}

515
void /* PRIVATE */
A
Andreas Dilger 已提交
516
png_push_crc_finish(png_structp png_ptr)
G
Guy Schalnat 已提交
517
{
G
Guy Schalnat 已提交
518 519
   if (png_ptr->skip_length && png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
520
      png_size_t save_size;
G
Guy Schalnat 已提交
521

A
Andreas Dilger 已提交
522 523
      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 已提交
524 525 526 527 528 529 530 531
      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 已提交
532
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
533 534 535
   }
   if (png_ptr->skip_length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
536
      png_size_t save_size;
G
Guy Schalnat 已提交
537

A
Andreas Dilger 已提交
538 539
      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 已提交
540 541 542 543 544 545 546 547
      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 已提交
548
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
549 550 551 552 553 554 555 556
   }
   if (!png_ptr->skip_length)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
A
Andreas Dilger 已提交
557 558

      png_crc_finish(png_ptr, 0);
A
Andreas Dilger 已提交
559
      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
560
   }
G
Guy Schalnat 已提交
561 562
}

563
void PNGAPI
A
Andreas Dilger 已提交
564
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
G
Guy Schalnat 已提交
565
{
G
Guy Schalnat 已提交
566 567
   png_bytep ptr;

568
   if (png_ptr == NULL) return;
G
Guy Schalnat 已提交
569 570 571
   ptr = buffer;
   if (png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
572
      png_size_t save_size;
G
Guy Schalnat 已提交
573 574 575 576 577 578

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

A
Andreas Dilger 已提交
579
      png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
G
Guy Schalnat 已提交
580
      length -= save_size;
A
Andreas Dilger 已提交
581
      ptr += save_size;
G
Guy Schalnat 已提交
582 583
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
584
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
585 586 587
   }
   if (length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
588
      png_size_t save_size;
G
Guy Schalnat 已提交
589 590 591 592 593 594

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

A
Andreas Dilger 已提交
595
      png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
596 597
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
598
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
599
   }
G
Guy Schalnat 已提交
600 601
}

602
void /* PRIVATE */
G
Guy Schalnat 已提交
603 604
png_push_save_buffer(png_structp png_ptr)
{
G
Guy Schalnat 已提交
605 606 607 608
   if (png_ptr->save_buffer_size)
   {
      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
      {
609
         png_size_t i, istop;
G
Guy Schalnat 已提交
610 611 612
         png_bytep sp;
         png_bytep dp;

613
         istop = png_ptr->save_buffer_size;
G
Guy Schalnat 已提交
614
         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
615
            i < istop; i++, sp++, dp++)
G
Guy Schalnat 已提交
616 617 618 619 620 621 622 623
         {
            *dp = *sp;
         }
      }
   }
   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
      png_ptr->save_buffer_max)
   {
A
Andreas Dilger 已提交
624
      png_size_t new_max;
G
Guy Schalnat 已提交
625 626
      png_bytep old_buffer;

627
      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
628 629 630 631
         (png_ptr->current_buffer_size + 256))
      {
        png_error(png_ptr, "Potential overflow of save_buffer");
      }
A
Andreas Dilger 已提交
632
      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
G
Guy Schalnat 已提交
633
      old_buffer = png_ptr->save_buffer;
634 635
      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
         (png_size_t)new_max);
636 637 638
      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 已提交
639 640 641
   }
   if (png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
642 643
      png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
G
Guy Schalnat 已提交
644 645 646 647 648
      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 已提交
649 650
}

651
void /* PRIVATE */
G
Guy Schalnat 已提交
652
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
653
   png_size_t buffer_length)
G
Guy Schalnat 已提交
654
{
G
Guy Schalnat 已提交
655 656 657 658
   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 已提交
659 660
}

661
void /* PRIVATE */
G
Guy Schalnat 已提交
662
png_push_read_IDAT(png_structp png_ptr)
G
Guy Schalnat 已提交
663
{
664
#ifdef PNG_USE_LOCAL_ARRAYS
665
   PNG_CONST PNG_IDAT;
666
#endif
667
   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
668
   {
A
Andreas Dilger 已提交
669
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
670 671 672 673 674 675 676

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

A
Andreas Dilger 已提交
677
      png_push_fill_buffer(png_ptr, chunk_length, 4);
678
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
679
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
680
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
681
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
A
Andreas Dilger 已提交
682

683
      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
684
      {
A
Andreas Dilger 已提交
685
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
686
         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
687 688 689 690 691 692 693 694
            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 已提交
695
      png_size_t save_size;
G
Guy Schalnat 已提交
696

A
Andreas Dilger 已提交
697
      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
698 699 700
      {
         save_size = (png_size_t)png_ptr->idat_size;
         /* check for overflow */
701
         if ((png_uint_32)save_size != png_ptr->idat_size)
702 703
            png_error(png_ptr, "save_size overflowed in pngpread");
      }
G
Guy Schalnat 已提交
704 705 706 707
      else
         save_size = png_ptr->save_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
708 709
      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
         png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
G
Guy Schalnat 已提交
710 711 712
      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
713
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
714 715 716
   }
   if (png_ptr->idat_size && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
717
      png_size_t save_size;
G
Guy Schalnat 已提交
718

A
Andreas Dilger 已提交
719
      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
720 721 722
      {
         save_size = (png_size_t)png_ptr->idat_size;
         /* check for overflow */
723
         if ((png_uint_32)save_size != png_ptr->idat_size)
724 725
            png_error(png_ptr, "save_size overflowed in pngpread");
      }
G
Guy Schalnat 已提交
726 727 728 729
      else
         save_size = png_ptr->current_buffer_size;

      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
730 731
      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
        png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
732 733 734 735

      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
736
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
737 738 739 740 741 742 743 744 745
   }
   if (!png_ptr->idat_size)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
746
      png_crc_finish(png_ptr, 0);
747
      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
748
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
749
   }
G
Guy Schalnat 已提交
750 751
}

752
void /* PRIVATE */
G
Guy Schalnat 已提交
753
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
754
   png_size_t buffer_length)
G
Guy Schalnat 已提交
755
{
G
Guy Schalnat 已提交
756 757
   int ret;

G
Guy Schalnat 已提交
758
   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
759
      png_benign_error(png_ptr, "Extra compression data");
G
Guy Schalnat 已提交
760

A
Andreas Dilger 已提交
761 762
   png_ptr->zstream.next_in = buffer;
   png_ptr->zstream.avail_in = (uInt)buffer_length;
763
   for (;;)
G
Guy Schalnat 已提交
764
   {
A
Andreas Dilger 已提交
765
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
766
      if (ret != Z_OK)
G
Guy Schalnat 已提交
767
      {
768
         if (ret == Z_STREAM_END)
G
Guy Schalnat 已提交
769
         {
770
            if (png_ptr->zstream.avail_in)
771
               png_benign_error(png_ptr, "Extra compressed data");
772 773 774 775 776 777 778 779
            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 已提交
780
         }
781 782 783 784
         else if (ret == Z_BUF_ERROR)
            break;
         else
            png_error(png_ptr, "Decompression Error");
G
Guy Schalnat 已提交
785
      }
A
Andreas Dilger 已提交
786
      if (!(png_ptr->zstream.avail_out))
G
Guy Schalnat 已提交
787
      {
788 789 790 791 792
         if ((
#if defined(PNG_READ_INTERLACING_SUPPORTED)
             png_ptr->interlaced && png_ptr->pass > 6) ||
             (!png_ptr->interlaced &&
#endif
793
             png_ptr->row_number == png_ptr->num_rows))
794
         {
795 796
           if (png_ptr->zstream.avail_in)
             png_warning(png_ptr, "Too much data in IDAT chunks");
797 798 799
           png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
           break;
         }
G
Guy Schalnat 已提交
800
         png_push_process_row(png_ptr);
A
Andreas Dilger 已提交
801 802
         png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
         png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
803
      }
A
Andreas Dilger 已提交
804 805 806
      else
         break;
   }
G
Guy Schalnat 已提交
807 808
}

809
void /* PRIVATE */
G
Guy Schalnat 已提交
810 811
png_push_process_row(png_structp png_ptr)
{
G
Guy Schalnat 已提交
812
   png_ptr->row_info.color_type = png_ptr->color_type;
G
Guy Schalnat 已提交
813 814 815 816
   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;
817

818 819
   png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
       png_ptr->row_info.width);
G
Guy Schalnat 已提交
820

G
Guy Schalnat 已提交
821 822 823
   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 已提交
824

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

827
   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
G
Guy Schalnat 已提交
828 829 830
      png_do_read_transformations(png_ptr);

#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
831
   /* blow up interlaced rows to full size */
A
Andreas Dilger 已提交
832
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
G
Guy Schalnat 已提交
833 834
   {
      if (png_ptr->pass < 6)
835
/*       old interface (pre-1.0.9):
G
Guy Schalnat 已提交
836
         png_do_read_interlace(&(png_ptr->row_info),
A
Andreas Dilger 已提交
837
            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
838 839
 */
         png_do_read_interlace(png_ptr);
G
Guy Schalnat 已提交
840

841 842
    switch (png_ptr->pass)
    {
G
Guy Schalnat 已提交
843 844 845 846 847 848
         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);
849
               png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */
G
Guy Schalnat 已提交
850
            }
851
            if (png_ptr->pass == 2) /* pass 1 might be empty */
852 853 854
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
855
                  png_push_have_row(png_ptr, NULL);
856 857 858
                  png_read_push_finish_row(png_ptr);
               }
            }
859 860 861 862
            if (png_ptr->pass == 4 && png_ptr->height <= 4)
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
863
                  png_push_have_row(png_ptr, NULL);
864 865
                  png_read_push_finish_row(png_ptr);
               }
866 867 868
            }
            if (png_ptr->pass == 6 && png_ptr->height <= 4)
            {
869
                png_push_have_row(png_ptr, NULL);
870 871
                png_read_push_finish_row(png_ptr);
            }
G
Guy Schalnat 已提交
872 873 874 875 876 877 878 879 880 881
            break;
         }
         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);
            }
882
            if (png_ptr->pass == 2) /* skip top 4 generated rows */
G
Guy Schalnat 已提交
883 884 885
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
886
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
                  png_read_push_finish_row(png_ptr);
               }
            }
            break;
         }
         case 2:
         {
            int i;
            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);
            }
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
902
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
903 904
               png_read_push_finish_row(png_ptr);
            }
905
            if (png_ptr->pass == 4) /* pass 3 might be empty */
906 907 908
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
909
                  png_push_have_row(png_ptr, NULL);
910 911 912
                  png_read_push_finish_row(png_ptr);
               }
            }
G
Guy Schalnat 已提交
913 914 915 916 917 918 919 920 921 922
            break;
         }
         case 3:
         {
            int i;
            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);
            }
923
            if (png_ptr->pass == 4) /* skip top two generated rows */
G
Guy Schalnat 已提交
924 925 926
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
927
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
                  png_read_push_finish_row(png_ptr);
               }
            }
            break;
         }
         case 4:
         {
            int i;
            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);
            }
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
943
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
944 945
               png_read_push_finish_row(png_ptr);
            }
946
            if (png_ptr->pass == 6) /* pass 5 might be empty */
947
            {
948
               png_push_have_row(png_ptr, NULL);
949 950
               png_read_push_finish_row(png_ptr);
            }
G
Guy Schalnat 已提交
951 952 953 954 955 956 957 958 959 960
            break;
         }
         case 5:
         {
            int i;
            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);
            }
961
            if (png_ptr->pass == 6) /* skip top generated row */
G
Guy Schalnat 已提交
962
            {
963
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
964 965 966 967 968 969 970 971 972 973
               png_read_push_finish_row(png_ptr);
            }
            break;
         }
         case 6:
         {
            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
            png_read_push_finish_row(png_ptr);
            if (png_ptr->pass != 6)
               break;
974
            png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
975 976 977 978 979
            png_read_push_finish_row(png_ptr);
         }
      }
   }
   else
G
Guy Schalnat 已提交
980
#endif
G
Guy Schalnat 已提交
981 982 983 984
   {
      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
      png_read_push_finish_row(png_ptr);
   }
G
Guy Schalnat 已提交
985 986
}

987
void /* PRIVATE */
G
Guy Schalnat 已提交
988 989
png_read_push_finish_row(png_structp png_ptr)
{
990
#ifdef PNG_USE_LOCAL_ARRAYS
991
   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
992

993
   /* start of interlace block */
994
   PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
995

996
   /* offset to next interlace block */
997
   PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
998

999
   /* start of interlace block in the y direction */
1000
   PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
1001

1002
   /* offset to next interlace block in the y direction */
1003
   PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
1004

1005 1006
   /* Height of interlace block.  This is not currently used - if you need
    * it, uncomment it here and in png.h
1007
   PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
1008
   */
1009
#endif
1010

G
Guy Schalnat 已提交
1011 1012
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
1013
      return;
G
Guy Schalnat 已提交
1014 1015 1016 1017

   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
1018
      png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
1019 1020 1021
      do
      {
         png_ptr->pass++;
1022 1023 1024 1025 1026
         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++;

1027 1028
         if (png_ptr->pass > 7)
            png_ptr->pass--;
G
Guy Schalnat 已提交
1029 1030
         if (png_ptr->pass >= 7)
            break;
1031

G
Guy Schalnat 已提交
1032 1033 1034 1035
         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];
1036

1037
         png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
1038
            png_ptr->iwidth) + 1;
1039

G
Guy Schalnat 已提交
1040 1041
         if (png_ptr->transformations & PNG_INTERLACE)
            break;
1042 1043 1044 1045 1046 1047 1048

         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 已提交
1049 1050 1051 1052
   }
}

#if defined(PNG_READ_tEXt_SUPPORTED)
1053
void /* PRIVATE */
1054 1055
png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
G
Guy Schalnat 已提交
1056
{
1057
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1058 1059
      {
         png_error(png_ptr, "Out of place tEXt");
1060
         info_ptr = info_ptr; /* to quiet some compiler warnings */
1061
      }
A
Andreas Dilger 已提交
1062

A
Andreas Dilger 已提交
1063 1064 1065
#ifdef PNG_MAX_MALLOC_64K
   png_ptr->skip_length = 0;  /* This may not be necessary */

1066
   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
A
Andreas Dilger 已提交
1067 1068
   {
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1069 1070
      png_ptr->skip_length = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
A
Andreas Dilger 已提交
1071 1072 1073
   }
#endif

1074
   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
1075
      (png_size_t)(length + 1));
A
Andreas Dilger 已提交
1076
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
1077
   png_ptr->current_text_ptr = png_ptr->current_text;
1078 1079
   png_ptr->current_text_size = (png_size_t)length;
   png_ptr->current_text_left = (png_size_t)length;
G
Guy Schalnat 已提交
1080
   png_ptr->process_mode = PNG_READ_tEXt_MODE;
G
Guy Schalnat 已提交
1081 1082
}

1083
void /* PRIVATE */
A
Andreas Dilger 已提交
1084
png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1085
{
G
Guy Schalnat 已提交
1086 1087
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
1088
      png_size_t text_size;
G
Guy Schalnat 已提交
1089 1090 1091 1092 1093

      if (png_ptr->buffer_size < png_ptr->current_text_left)
         text_size = png_ptr->buffer_size;
      else
         text_size = png_ptr->current_text_left;
A
Andreas Dilger 已提交
1094
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
1095
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
1096
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
1097 1098 1099
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
1100
      png_textp text_ptr;
G
Guy Schalnat 已提交
1101 1102
      png_charp text;
      png_charp key;
1103
      int ret;
G
Guy Schalnat 已提交
1104 1105 1106 1107 1108 1109 1110

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

A
Andreas Dilger 已提交
1111 1112 1113 1114 1115 1116
      png_push_crc_finish(png_ptr);

#if defined(PNG_MAX_MALLOC_64K)
      if (png_ptr->skip_length)
         return;
#endif
G
Guy Schalnat 已提交
1117 1118 1119 1120 1121 1122

      key = png_ptr->current_text;

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

1123
      if (text < key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
1124 1125
         text++;

1126 1127
      text_ptr = (png_textp)png_malloc(png_ptr,
         png_sizeof(png_text));
A
Andreas Dilger 已提交
1128 1129
      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
      text_ptr->key = key;
1130
#ifdef PNG_iTXt_SUPPORTED
1131 1132
      text_ptr->lang = NULL;
      text_ptr->lang_key = NULL;
1133
#endif
A
Andreas Dilger 已提交
1134
      text_ptr->text = text;
G
Guy Schalnat 已提交
1135

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

1138
      png_free(png_ptr, key);
A
Andreas Dilger 已提交
1139
      png_free(png_ptr, text_ptr);
1140
      png_ptr->current_text = NULL;
1141 1142

      if (ret)
1143
        png_warning(png_ptr, "Insufficient memory to store text chunk");
G
Guy Schalnat 已提交
1144
   }
G
Guy Schalnat 已提交
1145 1146 1147 1148
}
#endif

#if defined(PNG_READ_zTXt_SUPPORTED)
1149
void /* PRIVATE */
1150 1151
png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
G
Guy Schalnat 已提交
1152
{
1153
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1154 1155
      {
         png_error(png_ptr, "Out of place zTXt");
1156
         info_ptr = info_ptr; /* to quiet some compiler warnings */
1157
      }
A
Andreas Dilger 已提交
1158

A
Andreas Dilger 已提交
1159 1160 1161 1162 1163
#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.
    */
1164
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
1165 1166 1167 1168 1169 1170 1171
   {
      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_push_crc_skip(png_ptr, length);
      return;
   }
#endif

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

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

A
Andreas Dilger 已提交
1188
      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
G
Guy Schalnat 已提交
1189 1190 1191
         text_size = png_ptr->buffer_size;
      else
         text_size = png_ptr->current_text_left;
A
Andreas Dilger 已提交
1192
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
1193
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
1194
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
1195 1196 1197
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
1198
      png_textp text_ptr;
G
Guy Schalnat 已提交
1199 1200 1201
      png_charp text;
      png_charp key;
      int ret;
A
Andreas Dilger 已提交
1202
      png_size_t text_size, key_size;
G
Guy Schalnat 已提交
1203 1204 1205 1206 1207 1208 1209

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

A
Andreas Dilger 已提交
1210
      png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
1211 1212 1213 1214 1215 1216 1217

      key = png_ptr->current_text;

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

      /* zTXt can't have zero text */
1218
      if (text >= key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
1219
      {
1220
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1221
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
1222 1223 1224 1225 1226
         return;
      }

      text++;

A
Andreas Dilger 已提交
1227
      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
G
Guy Schalnat 已提交
1228
      {
1229
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1230
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
1231 1232 1233 1234 1235
         return;
      }

      text++;

A
Andreas Dilger 已提交
1236 1237
      png_ptr->zstream.next_in = (png_bytep )text;
      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
G
Guy Schalnat 已提交
1238
         (text - key));
A
Andreas Dilger 已提交
1239
      png_ptr->zstream.next_out = png_ptr->zbuf;
1240
      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
1241 1242 1243 1244 1245 1246

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

A
Andreas Dilger 已提交
1247
      while (png_ptr->zstream.avail_in)
G
Guy Schalnat 已提交
1248
      {
A
Andreas Dilger 已提交
1249
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
1250 1251
         if (ret != Z_OK && ret != Z_STREAM_END)
         {
A
Andreas Dilger 已提交
1252 1253
            inflateReset(&png_ptr->zstream);
            png_ptr->zstream.avail_in = 0;
1254
            png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1255 1256
            png_free(png_ptr, key);
            png_free(png_ptr, text);
G
Guy Schalnat 已提交
1257 1258
            return;
         }
A
Andreas Dilger 已提交
1259
         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
G
Guy Schalnat 已提交
1260
         {
A
Andreas Dilger 已提交
1261
            if (text == NULL)
G
Guy Schalnat 已提交
1262
            {
A
Andreas Dilger 已提交
1263
               text = (png_charp)png_malloc(png_ptr,
1264 1265
                     (png_ptr->zbuf_size
                     - png_ptr->zstream.avail_out + key_size + 1));
1266 1267 1268 1269 1270 1271
               png_memcpy(text + key_size, png_ptr->zbuf,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
               png_memcpy(text, key, key_size);
               text_size = key_size + png_ptr->zbuf_size -
                  png_ptr->zstream.avail_out;
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
1272 1273 1274 1275 1276 1277
            }
            else
            {
               png_charp tmp;

               tmp = text;
1278
               text = (png_charp)png_malloc(png_ptr, text_size +
1279 1280
                  (png_ptr->zbuf_size 
                  - png_ptr->zstream.avail_out));
1281 1282 1283 1284 1285 1286
               png_memcpy(text, tmp, text_size);
               png_free(png_ptr, tmp);
               png_memcpy(text + text_size, png_ptr->zbuf,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
1287 1288 1289
            }
            if (ret != Z_STREAM_END)
            {
A
Andreas Dilger 已提交
1290 1291
               png_ptr->zstream.next_out = png_ptr->zbuf;
               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
            }
         }
         else
         {
            break;
         }

         if (ret == Z_STREAM_END)
            break;
      }

A
Andreas Dilger 已提交
1303 1304
      inflateReset(&png_ptr->zstream);
      png_ptr->zstream.avail_in = 0;
G
Guy Schalnat 已提交
1305 1306 1307

      if (ret != Z_STREAM_END)
      {
1308
         png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1309 1310
         png_free(png_ptr, key);
         png_free(png_ptr, text);
G
Guy Schalnat 已提交
1311 1312 1313
         return;
      }

1314
      png_ptr->current_text = NULL;
A
Andreas Dilger 已提交
1315
      png_free(png_ptr, key);
G
Guy Schalnat 已提交
1316
      key = text;
A
Andreas Dilger 已提交
1317
      text += key_size;
G
Guy Schalnat 已提交
1318

1319 1320
      text_ptr = (png_textp)png_malloc(png_ptr,
          png_sizeof(png_text));
1321 1322
      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
      text_ptr->key = key;
1323
#ifdef PNG_iTXt_SUPPORTED
1324 1325
      text_ptr->lang = NULL;
      text_ptr->lang_key = NULL;
1326
#endif
1327
      text_ptr->text = text;
1328

1329
      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1330

1331
      png_free(png_ptr, key);
1332
      png_free(png_ptr, text_ptr);
1333 1334

      if (ret)
1335
        png_warning(png_ptr, "Insufficient memory to store text chunk");
1336 1337 1338 1339 1340
   }
}
#endif

#if defined(PNG_READ_iTXt_SUPPORTED)
1341
void /* PRIVATE */
1342 1343
png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
1344
{
1345
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
1346 1347
      {
         png_error(png_ptr, "Out of place iTXt");
1348
         info_ptr = info_ptr; /* to quiet some compiler warnings */
1349 1350 1351 1352 1353
      }

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

1354
   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
1355 1356 1357 1358 1359 1360 1361 1362
   {
      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,
1363
      (png_size_t)(length + 1));
1364 1365 1366 1367 1368
   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;
1369 1370
}

1371
void /* PRIVATE */
1372 1373
png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
{
1374

1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
   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;
      else
         text_size = png_ptr->current_text_left;
      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;
1391
      int comp_flag;
1392 1393 1394
      png_charp lang;
      png_charp lang_key;
      png_charp text;
1395
      int ret;
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409

      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

1410
      key = png_ptr->current_text;
1411

1412
      for (lang = key; *lang; lang++)
1413 1414
         /* empty loop */ ;

1415
      if (lang < key + png_ptr->current_text_size - 3)
1416
         lang++;
1417

1418 1419 1420 1421 1422 1423 1424
      comp_flag = *lang++;
      lang++;     /* skip comp_type, always zero */

      for (lang_key = lang; *lang_key; lang_key++)
         /* empty loop */ ;
      lang_key++;        /* skip NUL separator */

1425 1426 1427 1428 1429 1430
      text=lang_key;
      if (lang_key < key + png_ptr->current_text_size - 1)
      {
        for (; *text; text++)
           /* empty loop */ ;
      }
1431

1432
      if (text < key + png_ptr->current_text_size)
1433 1434
         text++;

1435 1436
      text_ptr = (png_textp)png_malloc(png_ptr,
         png_sizeof(png_text));
1437
      text_ptr->compression = comp_flag + 2;
A
Andreas Dilger 已提交
1438
      text_ptr->key = key;
1439 1440
      text_ptr->lang = lang;
      text_ptr->lang_key = lang_key;
A
Andreas Dilger 已提交
1441
      text_ptr->text = text;
1442 1443
      text_ptr->text_length = 0;
      text_ptr->itxt_length = png_strlen(text);
A
Andreas Dilger 已提交
1444

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

1447 1448
      png_ptr->current_text = NULL;

A
Andreas Dilger 已提交
1449
      png_free(png_ptr, text_ptr);
1450
      if (ret)
1451
        png_warning(png_ptr, "Insufficient memory to store iTXt chunk");
G
Guy Schalnat 已提交
1452
   }
G
Guy Schalnat 已提交
1453 1454 1455
}
#endif

A
Andreas Dilger 已提交
1456
/* This function is called when we haven't found a handler for this
1457 1458
 * 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.
1459
 */
1460
void /* PRIVATE */
1461 1462
png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
   length)
A
Andreas Dilger 已提交
1463
{
1464
   png_uint_32 skip = 0;
A
Andreas Dilger 已提交
1465 1466 1467

   if (!(png_ptr->chunk_name[0] & 0x20))
   {
1468
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
1469 1470
      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
         PNG_HANDLE_CHUNK_ALWAYS
1471
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1472
         && png_ptr->read_user_chunk_fn == NULL
1473 1474
#endif
         )
1475
#endif
1476 1477
         png_chunk_error(png_ptr, "unknown critical chunk");

1478
      info_ptr = info_ptr; /* to quiet some compiler warnings */
A
Andreas Dilger 已提交
1479 1480
   }

1481 1482 1483 1484
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
   {
#ifdef PNG_MAX_MALLOC_64K
1485 1486 1487 1488 1489 1490
      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;
      }
1491
#endif
1492 1493 1494
      png_memcpy((png_charp)png_ptr->unknown_chunk.name,
                 (png_charp)png_ptr->chunk_name, 
                 png_sizeof(png_ptr->unknown_chunk.name));
1495 1496
      png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1]
        = '\0';
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506

      png_ptr->unknown_chunk.size = (png_size_t)length;
      if (length == 0)
         png_ptr->unknown_chunk.data = NULL;
      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);
      }
1507
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526
      if (png_ptr->read_user_chunk_fn != NULL)
      {
         /* callback to user unknown chunk handler */
         int ret;
         ret = (*(png_ptr->read_user_chunk_fn))
           (png_ptr, &png_ptr->unknown_chunk);
         if (ret < 0)
            png_chunk_error(png_ptr, "error in user chunk");
         if (ret == 0)
         {
            if (!(png_ptr->chunk_name[0] & 0x20))
               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);
         }
      }
      else
1527
#endif
1528 1529 1530
        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;
1531 1532 1533 1534 1535
   }
   else
#endif
      skip=length;
   png_push_crc_skip(png_ptr, skip);
A
Andreas Dilger 已提交
1536 1537
}

1538
void /* PRIVATE */
A
Andreas Dilger 已提交
1539
png_push_have_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1540
{
A
Andreas Dilger 已提交
1541
   if (png_ptr->info_fn != NULL)
A
Andreas Dilger 已提交
1542
      (*(png_ptr->info_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1543 1544
}

1545
void /* PRIVATE */
A
Andreas Dilger 已提交
1546
png_push_have_end(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1547
{
A
Andreas Dilger 已提交
1548
   if (png_ptr->end_fn != NULL)
A
Andreas Dilger 已提交
1549
      (*(png_ptr->end_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1550 1551
}

1552
void /* PRIVATE */
G
Guy Schalnat 已提交
1553 1554
png_push_have_row(png_structp png_ptr, png_bytep row)
{
A
Andreas Dilger 已提交
1555
   if (png_ptr->row_fn != NULL)
G
Guy Schalnat 已提交
1556 1557
      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
         (int)png_ptr->pass);
G
Guy Schalnat 已提交
1558 1559
}

1560
void PNGAPI
A
Andreas Dilger 已提交
1561 1562
png_progressive_combine_row (png_structp png_ptr,
   png_bytep old_row, png_bytep new_row)
G
Guy Schalnat 已提交
1563
{
1564
#ifdef PNG_USE_LOCAL_ARRAYS
1565
   PNG_CONST int FARDATA png_pass_dsp_mask[7] =
1566
      {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
1567
#endif
1568
   if (png_ptr == NULL) return;
1569
   if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
A
Andreas Dilger 已提交
1570
      png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
G
Guy Schalnat 已提交
1571 1572
}

1573
void PNGAPI
G
Guy Schalnat 已提交
1574
png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
G
Guy Schalnat 已提交
1575 1576
   png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
   png_progressive_end_ptr end_fn)
G
Guy Schalnat 已提交
1577
{
1578
   if (png_ptr == NULL) return;
G
Guy Schalnat 已提交
1579 1580
   png_ptr->info_fn = info_fn;
   png_ptr->row_fn = row_fn;
G
Guy Schalnat 已提交
1581
   png_ptr->end_fn = end_fn;
G
Guy Schalnat 已提交
1582

1583
   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
G
Guy Schalnat 已提交
1584 1585
}

1586
png_voidp PNGAPI
A
Andreas Dilger 已提交
1587
png_get_progressive_ptr(png_structp png_ptr)
G
Guy Schalnat 已提交
1588
{
1589
   if (png_ptr == NULL) return (NULL);
A
Andreas Dilger 已提交
1590
   return png_ptr->io_ptr;
G
Guy Schalnat 已提交
1591
}
G
Guy Schalnat 已提交
1592
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */