blob: 581fa9d5a7ffcfd5045387e8d10ade52092dc128 [file] [log] [blame]
Guy Schalnat6d764711995-12-19 03:22:19 -06001
2/* pngpread.c - read a png file in push mode
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson416bb932013-11-17 11:01:31 -06004 * Last changed in libpng 1.6.8 [(PENDING RELEASE)]
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06005 * Copyright (c) 1998-2013 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -05008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060012 */
Guy Schalnat6d764711995-12-19 03:22:19 -060013
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050014#include "pngpriv.h"
Guy Schalnat4ee97b01996-01-16 01:51:56 -060015
Glenn Randers-Pehrsonc3cd22b2010-03-08 21:10:25 -060016#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
17
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050018/* Push model modes */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060019#define PNG_READ_SIG_MODE 0
20#define PNG_READ_CHUNK_MODE 1
21#define PNG_READ_IDAT_MODE 2
22#define PNG_SKIP_MODE 3
23#define PNG_READ_tEXt_MODE 4
24#define PNG_READ_zTXt_MODE 5
25#define PNG_READ_DONE_MODE 6
26#define PNG_READ_iTXt_MODE 7
27#define PNG_ERROR_MODE 8
28
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050029void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060030png_process_data(png_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -060031 png_bytep buffer, png_size_t buffer_size)
Guy Schalnat6d764711995-12-19 03:22:19 -060032{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050033 if (png_ptr == NULL || info_ptr == NULL)
34 return;
35
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060036 png_push_restore_buffer(png_ptr, buffer, buffer_size);
Guy Schalnat6d764711995-12-19 03:22:19 -060037
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060038 while (png_ptr->buffer_size)
39 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060040 png_process_some_data(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060041 }
Guy Schalnat6d764711995-12-19 03:22:19 -060042}
43
John Bowler0a5c9c02011-01-22 17:36:34 -060044png_size_t PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060045png_process_data_pause(png_structrp png_ptr, int save)
John Bowler0a5c9c02011-01-22 17:36:34 -060046{
47 if (png_ptr != NULL)
48 {
49 /* It's easiest for the caller if we do the save, then the caller doesn't
50 * have to supply the same data again:
51 */
52 if (save)
53 png_push_save_buffer(png_ptr);
54 else
55 {
56 /* This includes any pending saved bytes: */
57 png_size_t remaining = png_ptr->buffer_size;
58 png_ptr->buffer_size = 0;
59
60 /* So subtract the saved buffer size, unless all the data
61 * is actually 'saved', in which case we just return 0
62 */
63 if (png_ptr->save_buffer_size < remaining)
64 return remaining - png_ptr->save_buffer_size;
65 }
66 }
67
68 return 0;
69}
70
71png_uint_32 PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060072png_process_data_skip(png_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -060073{
John Bowlerfca50df2011-01-28 06:34:02 -060074 png_uint_32 remaining = 0;
John Bowler0a5c9c02011-01-22 17:36:34 -060075
76 if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE &&
77 png_ptr->skip_length > 0)
78 {
79 /* At the end of png_process_data the buffer size must be 0 (see the loop
80 * above) so we can detect a broken call here:
81 */
82 if (png_ptr->buffer_size != 0)
83 png_error(png_ptr,
84 "png_process_data_skip called inside png_process_data");
85
86 /* If is impossible for there to be a saved buffer at this point -
87 * otherwise we could not be in SKIP mode. This will also happen if
88 * png_process_skip is called inside png_process_data (but only very
89 * rarely.)
90 */
91 if (png_ptr->save_buffer_size != 0)
92 png_error(png_ptr, "png_process_data_skip called with saved data");
93
94 remaining = png_ptr->skip_length;
95 png_ptr->skip_length = 0;
96 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
97 }
98
99 return remaining;
100}
101
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600102/* What we do with the incoming data depends on what we were previously
103 * doing before we ran out of data...
104 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500105void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600106png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600107{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500108 if (png_ptr == NULL)
109 return;
110
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600111 switch (png_ptr->process_mode)
112 {
113 case PNG_READ_SIG_MODE:
114 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600115 png_push_read_sig(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600116 break;
117 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500118
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600119 case PNG_READ_CHUNK_MODE:
120 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600121 png_push_read_chunk(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600122 break;
123 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500124
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600125 case PNG_READ_IDAT_MODE:
126 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500127 png_push_read_IDAT(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600128 break;
129 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500130
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600131 case PNG_SKIP_MODE:
132 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500133 png_push_crc_finish(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600134 break;
135 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500136
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600137 default:
138 {
139 png_ptr->buffer_size = 0;
140 break;
141 }
142 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600143}
144
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600145/* Read any remaining signature bytes from the stream and compare them with
146 * the correct PNG signature. It is possible that this routine is called
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500147 * with bytes already read from the signature, either because they have been
148 * checked by the calling application, or because of multiple calls to this
149 * routine.
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600150 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500151void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600152png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600153{
Glenn Randers-Pehrsonbc8e40d2013-07-15 08:44:53 -0500154 png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500155 num_to_check = 8 - num_checked;
Guy Schalnat6d764711995-12-19 03:22:19 -0600156
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600157 if (png_ptr->buffer_size < num_to_check)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600158 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600159 num_to_check = png_ptr->buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600160 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600161
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600162 png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600163 num_to_check);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500164 png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
Guy Schalnat6d764711995-12-19 03:22:19 -0600165
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600166 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600167 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600168 if (num_checked < 4 &&
169 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
170 png_error(png_ptr, "Not a PNG file");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500171
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600172 else
173 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600174 }
175 else
176 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600177 if (png_ptr->sig_bytes >= 8)
178 {
179 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
180 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600181 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600182}
183
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500184void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600185png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600186{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500187 png_uint_32 chunk_name;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600188#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
189 int keep; /* unknown handling method */
190#endif
Glenn Randers-Pehrsona2567be2009-10-19 20:31:31 -0500191
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600192 /* First we make sure we have enough data for the 4 byte chunk name
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600193 * and the 4 byte chunk length before proceeding with decoding the
194 * chunk data. To fully decode each of these chunks, we also make
195 * sure we have enough data in the buffer for the 4 byte CRC at the
196 * end of every chunk (except IDAT, which is handled separately).
197 */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600198 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600199 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600200 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500201 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600202
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600203 if (png_ptr->buffer_size < 8)
204 {
205 png_push_save_buffer(png_ptr);
206 return;
207 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600208
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600209 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500210 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600211 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500212 png_crc_read(png_ptr, chunk_tag, 4);
213 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500214 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600215 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600216 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600217
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500218 chunk_name = png_ptr->chunk_name;
219
220 if (chunk_name == png_IDAT)
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -0500221 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600222 if (png_ptr->mode & PNG_AFTER_IDAT)
223 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600224
225 /* If we reach an IDAT chunk, this means we have read all of the
226 * header chunks, and we can start reading the image (or if this
227 * is called after the image has been read - we have an error).
228 */
229 if (!(png_ptr->mode & PNG_HAVE_IHDR))
230 png_error(png_ptr, "Missing IHDR before IDAT");
231
232 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
233 !(png_ptr->mode & PNG_HAVE_PLTE))
234 png_error(png_ptr, "Missing PLTE before IDAT");
235
236 png_ptr->mode |= PNG_HAVE_IDAT;
237
238 if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
239 if (png_ptr->push_length == 0)
240 return;
241
242 if (png_ptr->mode & PNG_AFTER_IDAT)
243 png_benign_error(png_ptr, "Too many IDATs found");
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -0500244 }
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500245
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500246 if (chunk_name == png_IHDR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600247 {
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500248 if (png_ptr->push_length != 13)
249 png_error(png_ptr, "Invalid IHDR length");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500250
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500251 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
252 {
253 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600254 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500255 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500256
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600257 png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600258 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500259
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500260 else if (chunk_name == png_IEND)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500261 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500262 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
263 {
264 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500265 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500266 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500267
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500268 png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
269
270 png_ptr->process_mode = PNG_READ_DONE_MODE;
271 png_push_have_end(png_ptr, info_ptr);
272 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500273
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500274#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600275 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500276 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500277 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
278 {
279 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500280 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500281 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500282
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600283 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500284
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500285 if (chunk_name == png_PLTE)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500286 png_ptr->mode |= PNG_HAVE_PLTE;
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500287 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500288
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500289#endif
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500290 else if (chunk_name == png_PLTE)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600291 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500292 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
293 {
294 png_push_save_buffer(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600295 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500296 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600297 png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600298 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500299
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500300 else if (chunk_name == png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600301 {
302 png_ptr->idat_size = png_ptr->push_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600303 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600304 png_push_have_info(png_ptr, info_ptr);
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600305 png_ptr->zstream.avail_out =
306 (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
307 png_ptr->iwidth) + 1;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600308 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600309 return;
310 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500311
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500312#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500313 else if (png_ptr->chunk_name == png_gAMA)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600314 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500315 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
316 {
317 png_push_save_buffer(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600318 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500319 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500320
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600321 png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600322 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500323
Guy Schalnat6d764711995-12-19 03:22:19 -0600324#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500325#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500326 else if (png_ptr->chunk_name == png_sBIT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600327 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500328 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
329 {
330 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600331 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500332 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500333
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600334 png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600335 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500336
Guy Schalnat6d764711995-12-19 03:22:19 -0600337#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500338#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500339 else if (png_ptr->chunk_name == png_cHRM)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600340 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500341 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
342 {
343 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600344 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500345 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500346
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600347 png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600348 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500349
Guy Schalnat6d764711995-12-19 03:22:19 -0600350#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500351#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500352 else if (chunk_name == png_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600353 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500354 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
355 {
356 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600357 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500358 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500359
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600360 png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
361 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500362
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600363#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500364#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500365 else if (png_ptr->chunk_name == png_iCCP)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600366 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500367 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
368 {
369 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600370 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500371 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500372
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600373 png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
374 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500375
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600376#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500377#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500378 else if (chunk_name == png_sPLT)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600379 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500380 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
381 {
382 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600383 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500384 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500385
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600386 png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
387 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500388
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600389#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500390#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500391 else if (chunk_name == png_tRNS)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600392 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500393 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
394 {
395 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600396 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500397 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500398
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600399 png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600400 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500401
Guy Schalnat6d764711995-12-19 03:22:19 -0600402#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500403#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500404 else if (chunk_name == png_bKGD)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600405 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500406 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
407 {
408 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600409 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500410 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500411
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600412 png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600413 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500414
Guy Schalnat6d764711995-12-19 03:22:19 -0600415#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500416#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500417 else if (chunk_name == png_hIST)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600418 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500419 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
420 {
421 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600422 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500423 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500424
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600425 png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600426 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500427
Guy Schalnat6d764711995-12-19 03:22:19 -0600428#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500429#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500430 else if (chunk_name == png_pHYs)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600431 {
432 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
433 {
434 png_push_save_buffer(png_ptr);
435 return;
436 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500437
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600438 png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600439 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500440
Guy Schalnat6d764711995-12-19 03:22:19 -0600441#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500442#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500443 else if (chunk_name == png_oFFs)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600444 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500445 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
446 {
447 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600448 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500449 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500450
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600451 png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600452 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600453#endif
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500454
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500455#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500456 else if (chunk_name == png_pCAL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500457 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500458 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
459 {
460 png_push_save_buffer(png_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500461 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500462 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500463
Andreas Dilger47a0c421997-05-16 02:46:07 -0500464 png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
465 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500466
Andreas Dilger47a0c421997-05-16 02:46:07 -0500467#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500468#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500469 else if (chunk_name == png_sCAL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600470 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500471 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
472 {
473 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600474 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500475 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500476
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600477 png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
478 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500479
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600480#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500481#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500482 else if (chunk_name == png_tIME)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600483 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500484 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
485 {
486 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600487 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500488 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500489
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600490 png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600491 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500492
Guy Schalnat6d764711995-12-19 03:22:19 -0600493#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500494#ifdef PNG_READ_tEXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500495 else if (chunk_name == png_tEXt)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600496 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500497 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
498 {
499 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500500 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500501 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500502
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600503 png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600504 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500505
Guy Schalnat6d764711995-12-19 03:22:19 -0600506#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500507#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500508 else if (chunk_name == png_zTXt)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600509 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500510 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
511 {
512 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500513 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500514 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500515
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600516 png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600517 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500518
Guy Schalnat6d764711995-12-19 03:22:19 -0600519#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500520#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500521 else if (chunk_name == png_iTXt)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600522 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500523 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
524 {
525 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500526 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500527 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500528
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600529 png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600530 }
531#endif
Glenn Randers-Pehrson416bb932013-11-17 11:01:31 -0600532
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600533 else
534 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500535 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
536 {
537 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500538 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500539 }
Glenn Randers-Pehrson68dfa9e2013-11-17 19:26:40 -0600540#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600541 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
542 PNG_HANDLE_CHUNK_AS_DEFAULT);
Glenn Randers-Pehrson416bb932013-11-17 11:01:31 -0600543#endif
Glenn Randers-Pehrson68dfa9e2013-11-17 19:26:40 -0600544 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600545
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600546 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Guy Schalnat6d764711995-12-19 03:22:19 -0600547}
548
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500549void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600550png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip)
Guy Schalnat6d764711995-12-19 03:22:19 -0600551{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600552 png_ptr->process_mode = PNG_SKIP_MODE;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500553 png_ptr->skip_length = skip;
Guy Schalnat6d764711995-12-19 03:22:19 -0600554}
555
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500556void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600557png_push_crc_finish(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600558{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600559 if (png_ptr->skip_length && png_ptr->save_buffer_size)
560 {
Glenn Randers-Pehrson1408c2a2011-01-16 14:16:28 -0600561 png_size_t save_size = png_ptr->save_buffer_size;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500562 png_uint_32 skip_length = png_ptr->skip_length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600563
John Bowler168a4332011-01-16 19:32:22 -0600564 /* We want the smaller of 'skip_length' and 'save_buffer_size', but
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500565 * they are of different types and we don't know which variable has the
566 * fewest bits. Carefully select the smaller and cast it to the type of
567 * the larger - this cannot overflow. Do not cast in the following test
568 * - it will break on either 16 or 64 bit platforms.
569 */
570 if (skip_length < save_size)
571 save_size = (png_size_t)skip_length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500572
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600573 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500574 skip_length = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600575
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600576 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600577
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500578 png_ptr->skip_length -= skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600579 png_ptr->buffer_size -= save_size;
580 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500581 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600582 }
583 if (png_ptr->skip_length && png_ptr->current_buffer_size)
584 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500585 png_size_t save_size = png_ptr->current_buffer_size;
586 png_uint_32 skip_length = png_ptr->skip_length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600587
John Bowler168a4332011-01-16 19:32:22 -0600588 /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
589 * the same problem exists as above and the same solution.
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500590 */
591 if (skip_length < save_size)
592 save_size = (png_size_t)skip_length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500593
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600594 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500595 skip_length = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600596
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600597 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600598
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500599 png_ptr->skip_length -= skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600600 png_ptr->buffer_size -= save_size;
601 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500602 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600603 }
604 if (!png_ptr->skip_length)
605 {
606 if (png_ptr->buffer_size < 4)
607 {
608 png_push_save_buffer(png_ptr);
609 return;
610 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600611
612 png_crc_finish(png_ptr, 0);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500613 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600614 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600615}
616
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -0600617void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500618png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600619{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600620 png_bytep ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -0600621
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500622 if (png_ptr == NULL)
623 return;
624
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600625 ptr = buffer;
626 if (png_ptr->save_buffer_size)
627 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500628 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600629
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600630 if (length < png_ptr->save_buffer_size)
631 save_size = length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500632
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600633 else
634 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600635
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600636 memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600637 length -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500638 ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600639 png_ptr->buffer_size -= save_size;
640 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500641 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600642 }
643 if (length && png_ptr->current_buffer_size)
644 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500645 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600646
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600647 if (length < png_ptr->current_buffer_size)
648 save_size = length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500649
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600650 else
651 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600652
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600653 memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600654 png_ptr->buffer_size -= save_size;
655 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500656 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600657 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600658}
659
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500660void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600661png_push_save_buffer(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600662{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600663 if (png_ptr->save_buffer_size)
664 {
665 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
666 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500667 png_size_t i, istop;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600668 png_bytep sp;
669 png_bytep dp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600670
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500671 istop = png_ptr->save_buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600672 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600673 i < istop; i++, sp++, dp++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600674 {
675 *dp = *sp;
676 }
677 }
678 }
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600679 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600680 png_ptr->save_buffer_max)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600681 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500682 png_size_t new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600683 png_bytep old_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600684
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600685 if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600686 (png_ptr->current_buffer_size + 256))
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600687 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600688 png_error(png_ptr, "Potential overflow of save_buffer");
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600689 }
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600690
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600691 new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600692 old_buffer = png_ptr->save_buffer;
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600693 png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600694 (png_size_t)new_max);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500695
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600696 if (png_ptr->save_buffer == NULL)
697 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600698 png_free(png_ptr, old_buffer);
699 png_error(png_ptr, "Insufficient memory for save_buffer");
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600700 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500701
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600702 memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500703 png_free(png_ptr, old_buffer);
704 png_ptr->save_buffer_max = new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600705 }
706 if (png_ptr->current_buffer_size)
707 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600708 memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500709 png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600710 png_ptr->save_buffer_size += png_ptr->current_buffer_size;
711 png_ptr->current_buffer_size = 0;
712 }
713 png_ptr->save_buffer_ptr = png_ptr->save_buffer;
714 png_ptr->buffer_size = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600715}
716
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500717void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600718png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500719 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600720{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600721 png_ptr->current_buffer = buffer;
722 png_ptr->current_buffer_size = buffer_length;
723 png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
724 png_ptr->current_buffer_ptr = png_ptr->current_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600725}
726
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500727void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600728png_push_read_IDAT(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600729{
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600730 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600731 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600732 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500733 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600734
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500735 /* TODO: this code can be commoned up with the same code in push_read */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600736 if (png_ptr->buffer_size < 8)
737 {
738 png_push_save_buffer(png_ptr);
739 return;
740 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600741
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600742 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500743 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600744 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500745 png_crc_read(png_ptr, chunk_tag, 4);
746 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600747 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600748
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500749 if (png_ptr->chunk_name != png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600750 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500751 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500752
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600753 if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600754 png_error(png_ptr, "Not enough compressed data");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500755
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600756 return;
757 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600758
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600759 png_ptr->idat_size = png_ptr->push_length;
760 }
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500761
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600762 if (png_ptr->idat_size && png_ptr->save_buffer_size)
763 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500764 png_size_t save_size = png_ptr->save_buffer_size;
765 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600766
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500767 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
768 * are of different types and we don't know which variable has the fewest
769 * bits. Carefully select the smaller and cast it to the type of the
770 * larger - this cannot overflow. Do not cast in the following test - it
771 * will break on either 16 or 64 bit platforms.
772 */
773 if (idat_size < save_size)
774 save_size = (png_size_t)idat_size;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500775
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600776 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500777 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600778
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600779 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500780
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500781 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500782
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500783 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600784 png_ptr->buffer_size -= save_size;
785 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500786 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600787 }
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500788
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600789 if (png_ptr->idat_size && png_ptr->current_buffer_size)
790 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500791 png_size_t save_size = png_ptr->current_buffer_size;
792 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600793
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500794 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
795 * are of different types and we don't know which variable has the fewest
796 * bits. Carefully select the smaller and cast it to the type of the
797 * larger - this cannot overflow.
798 */
799 if (idat_size < save_size)
800 save_size = (png_size_t)idat_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500801
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600802 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500803 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600804
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600805 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500806
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500807 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600808
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500809 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600810 png_ptr->buffer_size -= save_size;
811 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500812 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600813 }
814 if (!png_ptr->idat_size)
815 {
816 if (png_ptr->buffer_size < 4)
817 {
818 png_push_save_buffer(png_ptr);
819 return;
820 }
821
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600822 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600823 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500824 png_ptr->mode |= PNG_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600825 png_ptr->zowner = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600826 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600827}
828
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500829void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600830png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500831 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600832{
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500833 /* The caller checks for a non-zero buffer length. */
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500834 if (!(buffer_length > 0) || buffer == NULL)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500835 png_error(png_ptr, "No IDAT data (internal error)");
Guy Schalnat6d764711995-12-19 03:22:19 -0600836
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500837 /* This routine must process all the data it has been given
838 * before returning, calling the row callback as required to
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500839 * handle the uncompressed results.
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500840 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600841 png_ptr->zstream.next_in = buffer;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600842 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600843 png_ptr->zstream.avail_in = (uInt)buffer_length;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500844
845 /* Keep going until the decompressed data is all processed
846 * or the stream marked as finished.
847 */
848 while (png_ptr->zstream.avail_in > 0 &&
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600849 !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600850 {
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500851 int ret;
852
853 /* We have data for zlib, but we must check that zlib
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500854 * has someplace to put the results. It doesn't matter
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500855 * if we don't expect any results -- it may be the input
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500856 * data is just the LZ end code.
857 */
858 if (!(png_ptr->zstream.avail_out > 0))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600859 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600860 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
861 png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
862 png_ptr->iwidth) + 1);
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500863
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600864 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600865 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500866
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500867 /* Using Z_SYNC_FLUSH here means that an unterminated
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500868 * LZ stream (a stream with a missing end code) can still
869 * be handled, otherwise (Z_NO_FLUSH) a future zlib
870 * implementation might defer output and therefore
871 * change the current behavior (see comments in inflate.c
872 * for why this doesn't happen at present with zlib 1.2.5).
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500873 */
874 ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
875
876 /* Check for any failure before proceeding. */
877 if (ret != Z_OK && ret != Z_STREAM_END)
878 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500879 /* Terminate the decompression. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600880 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
881 png_ptr->zowner = 0;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500882
883 /* This may be a truncated stream (missing or
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500884 * damaged end code). Treat that as a warning.
885 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500886 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500887 png_ptr->pass > 6)
888 png_warning(png_ptr, "Truncated compressed data in IDAT");
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500889
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500890 else
891 png_error(png_ptr, "Decompression error in IDAT");
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500892
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500893 /* Skip the check on unprocessed input */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500894 return;
895 }
896
897 /* Did inflate output any data? */
898 if (png_ptr->zstream.next_out != png_ptr->row_buf)
899 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500900 /* Is this unexpected data after the last row?
901 * If it is, artificially terminate the LZ output
902 * here.
903 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500904 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500905 png_ptr->pass > 6)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500906 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500907 /* Extra data. */
908 png_warning(png_ptr, "Extra compressed data in IDAT");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600909 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
910 png_ptr->zowner = 0;
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500911
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500912 /* Do no more processing; skip the unprocessed
913 * input check below.
914 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500915 return;
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500916 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500917
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500918 /* Do we have a complete row? */
919 if (png_ptr->zstream.avail_out == 0)
920 png_push_process_row(png_ptr);
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500921 }
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500922
923 /* And check for the end of the stream. */
924 if (ret == Z_STREAM_END)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600925 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500926 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500927
928 /* All the data should have been processed, if anything
929 * is left at this point we have bytes of IDAT data
930 * after the zlib end code.
931 */
932 if (png_ptr->zstream.avail_in > 0)
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500933 png_warning(png_ptr, "Extra compression data in IDAT");
Guy Schalnat6d764711995-12-19 03:22:19 -0600934}
935
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500936void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600937png_push_process_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600938{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500939 /* 1.5.6: row_info moved out of png_struct to a local here. */
940 png_row_info row_info;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600941
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500942 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
943 row_info.color_type = png_ptr->color_type;
944 row_info.bit_depth = png_ptr->bit_depth;
945 row_info.channels = png_ptr->channels;
946 row_info.pixel_depth = png_ptr->pixel_depth;
947 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
Guy Schalnat6d764711995-12-19 03:22:19 -0600948
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500949 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
950 {
951 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
Mans Rullgardd3a94802011-11-03 00:47:55 -0500952 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500953 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
954 else
955 png_error(png_ptr, "bad adaptive filter value");
956 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600957
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500958 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
959 * 1.5.6, while the buffer really is this big in current versions of libpng
960 * it may not be in the future, so this was changed just to copy the
961 * interlaced row count:
962 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600963 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -0600964
John Bowler4a12f4a2011-04-17 18:34:22 -0500965#ifdef PNG_READ_TRANSFORMS_SUPPORTED
John Bowler9b872f42011-02-12 09:00:16 -0600966 if (png_ptr->transformations)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500967 png_do_read_transformations(png_ptr, &row_info);
John Bowler4a12f4a2011-04-17 18:34:22 -0500968#endif
Guy Schalnat6d764711995-12-19 03:22:19 -0600969
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500970 /* The transformed pixel depth should match the depth now in row_info. */
971 if (png_ptr->transformed_pixel_depth == 0)
972 {
973 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
974 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
975 png_error(png_ptr, "progressive row overflow");
976 }
977
978 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
979 png_error(png_ptr, "internal progressive row size calculation error");
980
981
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500982#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500983 /* Blow up interlaced rows to full size */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500984 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600985 {
986 if (png_ptr->pass < 6)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500987 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
988 png_ptr->transformations);
Guy Schalnat6d764711995-12-19 03:22:19 -0600989
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600990 switch (png_ptr->pass)
991 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600992 case 0:
993 {
994 int i;
995 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
996 {
997 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500998 png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600999 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001000
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001001 if (png_ptr->pass == 2) /* Pass 1 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001002 {
1003 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1004 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001005 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001006 png_read_push_finish_row(png_ptr);
1007 }
1008 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001009
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001010 if (png_ptr->pass == 4 && png_ptr->height <= 4)
1011 {
1012 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1013 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001014 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001015 png_read_push_finish_row(png_ptr);
1016 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001017 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001018
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001019 if (png_ptr->pass == 6 && png_ptr->height <= 4)
1020 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001021 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001022 png_read_push_finish_row(png_ptr);
1023 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001024
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001025 break;
1026 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001027
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001028 case 1:
1029 {
1030 int i;
1031 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
1032 {
1033 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1034 png_read_push_finish_row(png_ptr);
1035 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001036
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001037 if (png_ptr->pass == 2) /* Skip top 4 generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001038 {
1039 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1040 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001041 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001042 png_read_push_finish_row(png_ptr);
1043 }
1044 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001045
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001046 break;
1047 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001048
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001049 case 2:
1050 {
1051 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001052
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001053 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1054 {
1055 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1056 png_read_push_finish_row(png_ptr);
1057 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001058
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001059 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1060 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001061 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001062 png_read_push_finish_row(png_ptr);
1063 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001064
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001065 if (png_ptr->pass == 4) /* Pass 3 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001066 {
1067 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1068 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001069 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001070 png_read_push_finish_row(png_ptr);
1071 }
1072 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001073
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001074 break;
1075 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001076
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001077 case 3:
1078 {
1079 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001080
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001081 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
1082 {
1083 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1084 png_read_push_finish_row(png_ptr);
1085 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001086
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001087 if (png_ptr->pass == 4) /* Skip top two generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001088 {
1089 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1090 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001091 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001092 png_read_push_finish_row(png_ptr);
1093 }
1094 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001095
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001096 break;
1097 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001098
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001099 case 4:
1100 {
1101 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001102
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001103 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1104 {
1105 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1106 png_read_push_finish_row(png_ptr);
1107 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001108
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001109 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1110 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001111 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001112 png_read_push_finish_row(png_ptr);
1113 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001114
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001115 if (png_ptr->pass == 6) /* Pass 5 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001116 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001117 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001118 png_read_push_finish_row(png_ptr);
1119 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001120
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001121 break;
1122 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001123
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001124 case 5:
1125 {
1126 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001127
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001128 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
1129 {
1130 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1131 png_read_push_finish_row(png_ptr);
1132 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001133
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001134 if (png_ptr->pass == 6) /* Skip top generated row */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001135 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001136 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001137 png_read_push_finish_row(png_ptr);
1138 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001139
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001140 break;
1141 }
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05001142
Glenn Randers-Pehrsonb3edc732010-11-21 14:06:41 -06001143 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001144 case 6:
1145 {
1146 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1147 png_read_push_finish_row(png_ptr);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001148
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001149 if (png_ptr->pass != 6)
1150 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001151
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001152 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001153 png_read_push_finish_row(png_ptr);
1154 }
1155 }
1156 }
1157 else
Guy Schalnat6d764711995-12-19 03:22:19 -06001158#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001159 {
1160 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1161 png_read_push_finish_row(png_ptr);
1162 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001163}
1164
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001165void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001166png_read_push_finish_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001167{
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001168#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001169 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001170
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001171 /* Start of interlace block */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001172 static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001173
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001174 /* Offset to next interlace block */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001175 static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001176
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001177 /* Start of interlace block in the y direction */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001178 static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001179
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001180 /* Offset to next interlace block in the y direction */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001181 static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001182
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001183 /* Height of interlace block. This is not currently used - if you need
1184 * it, uncomment it here and in png.h
John Bowlerbaeb6d12011-11-26 18:21:02 -06001185 static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001186 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001187#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001188
Guy Schalnat6d764711995-12-19 03:22:19 -06001189 png_ptr->row_number++;
1190 if (png_ptr->row_number < png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001191 return;
Guy Schalnat6d764711995-12-19 03:22:19 -06001192
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001193#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat6d764711995-12-19 03:22:19 -06001194 if (png_ptr->interlaced)
1195 {
1196 png_ptr->row_number = 0;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001197 memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001198
Guy Schalnat6d764711995-12-19 03:22:19 -06001199 do
1200 {
1201 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001202 if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1203 (png_ptr->pass == 3 && png_ptr->width < 3) ||
1204 (png_ptr->pass == 5 && png_ptr->width < 2))
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001205 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001206
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05001207 if (png_ptr->pass > 7)
1208 png_ptr->pass--;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001209
Guy Schalnat6d764711995-12-19 03:22:19 -06001210 if (png_ptr->pass >= 7)
1211 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001212
Guy Schalnat6d764711995-12-19 03:22:19 -06001213 png_ptr->iwidth = (png_ptr->width +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001214 png_pass_inc[png_ptr->pass] - 1 -
1215 png_pass_start[png_ptr->pass]) /
1216 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001217
Guy Schalnat6d764711995-12-19 03:22:19 -06001218 if (png_ptr->transformations & PNG_INTERLACE)
1219 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001220
1221 png_ptr->num_rows = (png_ptr->height +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001222 png_pass_yinc[png_ptr->pass] - 1 -
1223 png_pass_ystart[png_ptr->pass]) /
1224 png_pass_yinc[png_ptr->pass];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001225
1226 } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
Guy Schalnat6d764711995-12-19 03:22:19 -06001227 }
Glenn Randers-Pehrsona31c74f2009-05-18 15:52:01 -05001228#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat6d764711995-12-19 03:22:19 -06001229}
1230
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001231void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001232png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001233{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001234 if (png_ptr->info_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001235 (*(png_ptr->info_fn))(png_ptr, info_ptr);
1236}
1237
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001238void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001239png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001240{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001241 if (png_ptr->end_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001242 (*(png_ptr->end_fn))(png_ptr, info_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001243}
1244
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001245void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001246png_push_have_row(png_structrp png_ptr, png_bytep row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001247{
Glenn Randers-Pehrson78d55452010-06-19 07:03:50 -05001248 if (png_ptr->row_fn != NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001249 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1250 (int)png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -06001251}
1252
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001253#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001254void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001255png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001256 png_const_bytep new_row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001257{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001258 if (png_ptr == NULL)
1259 return;
1260
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001261 /* new_row is a flag here - if it is NULL then the app callback was called
1262 * from an empty row (see the calls to png_struct::row_fn below), otherwise
1263 * it must be png_ptr->row_buf+1
1264 */
1265 if (new_row != NULL)
1266 png_combine_row(png_ptr, old_row, 1/*display*/);
Guy Schalnat6d764711995-12-19 03:22:19 -06001267}
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001268#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat6d764711995-12-19 03:22:19 -06001269
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001270void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001271png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001272 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1273 png_progressive_end_ptr end_fn)
Guy Schalnat6d764711995-12-19 03:22:19 -06001274{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001275 if (png_ptr == NULL)
1276 return;
1277
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001278 png_ptr->info_fn = info_fn;
1279 png_ptr->row_fn = row_fn;
Guy Schalnat6d764711995-12-19 03:22:19 -06001280 png_ptr->end_fn = end_fn;
Guy Schalnate5a37791996-06-05 15:50:50 -05001281
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -05001282 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001283}
1284
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001285png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001286png_get_progressive_ptr(png_const_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001287{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001288 if (png_ptr == NULL)
1289 return (NULL);
1290
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001291 return png_ptr->io_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001292}
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001293#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */