Coverage Report

Created: 2024-09-14 07:19

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