Coverage Report

Created: 2018-09-25 14:53

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