blob: 94856e90fe281d4004ea26d4310bff231e18c255 [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-Pehrsonbe3977d2013-12-19 09:04:52 -06004 * Last changed in libpng 1.6.8 [December 19, 2013]
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-Pehrsonbd757ac2013-11-18 18:40:39 -0600188#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600189 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-Pehrsonbd757ac2013-11-18 18:40:39 -0600274#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 }
288#endif
Glenn Randers-Pehrson012d36f2013-11-17 19:42:48 -0600289
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-Pehrson871b1d02013-03-02 14:58:22 -0600540 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
541 PNG_HANDLE_CHUNK_AS_DEFAULT);
Glenn Randers-Pehrson68dfa9e2013-11-17 19:26:40 -0600542 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600543
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600544 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Guy Schalnat6d764711995-12-19 03:22:19 -0600545}
546
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500547void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600548png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip)
Guy Schalnat6d764711995-12-19 03:22:19 -0600549{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600550 png_ptr->process_mode = PNG_SKIP_MODE;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500551 png_ptr->skip_length = skip;
Guy Schalnat6d764711995-12-19 03:22:19 -0600552}
553
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500554void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600555png_push_crc_finish(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600556{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600557 if (png_ptr->skip_length && png_ptr->save_buffer_size)
558 {
Glenn Randers-Pehrson1408c2a2011-01-16 14:16:28 -0600559 png_size_t save_size = png_ptr->save_buffer_size;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500560 png_uint_32 skip_length = png_ptr->skip_length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600561
John Bowler168a4332011-01-16 19:32:22 -0600562 /* We want the smaller of 'skip_length' and 'save_buffer_size', but
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500563 * they are of different types and we don't know which variable has the
564 * fewest bits. Carefully select the smaller and cast it to the type of
565 * the larger - this cannot overflow. Do not cast in the following test
566 * - it will break on either 16 or 64 bit platforms.
567 */
568 if (skip_length < save_size)
569 save_size = (png_size_t)skip_length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500570
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600571 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500572 skip_length = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600573
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600574 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600575
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500576 png_ptr->skip_length -= skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600577 png_ptr->buffer_size -= save_size;
578 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500579 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600580 }
581 if (png_ptr->skip_length && png_ptr->current_buffer_size)
582 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500583 png_size_t save_size = png_ptr->current_buffer_size;
584 png_uint_32 skip_length = png_ptr->skip_length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600585
John Bowler168a4332011-01-16 19:32:22 -0600586 /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
587 * the same problem exists as above and the same solution.
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500588 */
589 if (skip_length < save_size)
590 save_size = (png_size_t)skip_length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500591
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600592 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500593 skip_length = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600594
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600595 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600596
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500597 png_ptr->skip_length -= skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600598 png_ptr->buffer_size -= save_size;
599 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500600 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600601 }
602 if (!png_ptr->skip_length)
603 {
604 if (png_ptr->buffer_size < 4)
605 {
606 png_push_save_buffer(png_ptr);
607 return;
608 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600609
610 png_crc_finish(png_ptr, 0);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500611 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600612 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600613}
614
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -0600615void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500616png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600617{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600618 png_bytep ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -0600619
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500620 if (png_ptr == NULL)
621 return;
622
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600623 ptr = buffer;
624 if (png_ptr->save_buffer_size)
625 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600627
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600628 if (length < png_ptr->save_buffer_size)
629 save_size = length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500630
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600631 else
632 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600633
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600634 memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600635 length -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500636 ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600637 png_ptr->buffer_size -= save_size;
638 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500639 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600640 }
641 if (length && png_ptr->current_buffer_size)
642 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500643 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600644
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600645 if (length < png_ptr->current_buffer_size)
646 save_size = length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500647
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600648 else
649 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600650
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600651 memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600652 png_ptr->buffer_size -= save_size;
653 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500654 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600655 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600656}
657
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500658void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600659png_push_save_buffer(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600660{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600661 if (png_ptr->save_buffer_size)
662 {
663 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
664 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500665 png_size_t i, istop;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600666 png_bytep sp;
667 png_bytep dp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600668
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500669 istop = png_ptr->save_buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600670 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600671 i < istop; i++, sp++, dp++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600672 {
673 *dp = *sp;
674 }
675 }
676 }
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600677 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600678 png_ptr->save_buffer_max)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600679 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500680 png_size_t new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600681 png_bytep old_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600682
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600683 if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600684 (png_ptr->current_buffer_size + 256))
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600685 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600686 png_error(png_ptr, "Potential overflow of save_buffer");
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600687 }
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600688
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600689 new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600690 old_buffer = png_ptr->save_buffer;
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600691 png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600692 (png_size_t)new_max);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500693
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600694 if (png_ptr->save_buffer == NULL)
695 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600696 png_free(png_ptr, old_buffer);
697 png_error(png_ptr, "Insufficient memory for save_buffer");
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600698 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500699
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600700 memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500701 png_free(png_ptr, old_buffer);
702 png_ptr->save_buffer_max = new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600703 }
704 if (png_ptr->current_buffer_size)
705 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600706 memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500707 png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600708 png_ptr->save_buffer_size += png_ptr->current_buffer_size;
709 png_ptr->current_buffer_size = 0;
710 }
711 png_ptr->save_buffer_ptr = png_ptr->save_buffer;
712 png_ptr->buffer_size = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600713}
714
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500715void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600716png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500717 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600718{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600719 png_ptr->current_buffer = buffer;
720 png_ptr->current_buffer_size = buffer_length;
721 png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
722 png_ptr->current_buffer_ptr = png_ptr->current_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600723}
724
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500725void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600726png_push_read_IDAT(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600727{
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600728 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600729 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600730 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500731 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600732
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500733 /* TODO: this code can be commoned up with the same code in push_read */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600734 if (png_ptr->buffer_size < 8)
735 {
736 png_push_save_buffer(png_ptr);
737 return;
738 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600739
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600740 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500741 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600742 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500743 png_crc_read(png_ptr, chunk_tag, 4);
744 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600745 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600746
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500747 if (png_ptr->chunk_name != png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600748 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500749 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500750
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600751 if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600752 png_error(png_ptr, "Not enough compressed data");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500753
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600754 return;
755 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600756
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600757 png_ptr->idat_size = png_ptr->push_length;
758 }
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500759
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600760 if (png_ptr->idat_size && png_ptr->save_buffer_size)
761 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500762 png_size_t save_size = png_ptr->save_buffer_size;
763 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600764
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500765 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
766 * are of different types and we don't know which variable has the fewest
767 * bits. Carefully select the smaller and cast it to the type of the
768 * larger - this cannot overflow. Do not cast in the following test - it
769 * will break on either 16 or 64 bit platforms.
770 */
771 if (idat_size < save_size)
772 save_size = (png_size_t)idat_size;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500773
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600774 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500775 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600776
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600777 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500778
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500779 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500780
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500781 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600782 png_ptr->buffer_size -= save_size;
783 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500784 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600785 }
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500786
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600787 if (png_ptr->idat_size && png_ptr->current_buffer_size)
788 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500789 png_size_t save_size = png_ptr->current_buffer_size;
790 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600791
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500792 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
793 * are of different types and we don't know which variable has the fewest
794 * bits. Carefully select the smaller and cast it to the type of the
795 * larger - this cannot overflow.
796 */
797 if (idat_size < save_size)
798 save_size = (png_size_t)idat_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500799
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600800 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500801 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600802
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600803 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500804
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500805 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600806
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500807 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600808 png_ptr->buffer_size -= save_size;
809 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500810 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600811 }
812 if (!png_ptr->idat_size)
813 {
814 if (png_ptr->buffer_size < 4)
815 {
816 png_push_save_buffer(png_ptr);
817 return;
818 }
819
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600820 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600821 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500822 png_ptr->mode |= PNG_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600823 png_ptr->zowner = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600824 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600825}
826
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500827void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600828png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500829 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600830{
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500831 /* The caller checks for a non-zero buffer length. */
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500832 if (!(buffer_length > 0) || buffer == NULL)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500833 png_error(png_ptr, "No IDAT data (internal error)");
Guy Schalnat6d764711995-12-19 03:22:19 -0600834
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500835 /* This routine must process all the data it has been given
836 * before returning, calling the row callback as required to
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500837 * handle the uncompressed results.
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500838 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600839 png_ptr->zstream.next_in = buffer;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600840 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600841 png_ptr->zstream.avail_in = (uInt)buffer_length;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500842
843 /* Keep going until the decompressed data is all processed
844 * or the stream marked as finished.
845 */
846 while (png_ptr->zstream.avail_in > 0 &&
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600847 !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600848 {
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500849 int ret;
850
851 /* We have data for zlib, but we must check that zlib
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500852 * has someplace to put the results. It doesn't matter
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500853 * if we don't expect any results -- it may be the input
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500854 * data is just the LZ end code.
855 */
856 if (!(png_ptr->zstream.avail_out > 0))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600857 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600858 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
859 png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
860 png_ptr->iwidth) + 1);
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500861
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600862 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600863 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500864
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500865 /* Using Z_SYNC_FLUSH here means that an unterminated
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500866 * LZ stream (a stream with a missing end code) can still
867 * be handled, otherwise (Z_NO_FLUSH) a future zlib
868 * implementation might defer output and therefore
869 * change the current behavior (see comments in inflate.c
870 * for why this doesn't happen at present with zlib 1.2.5).
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500871 */
872 ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
873
874 /* Check for any failure before proceeding. */
875 if (ret != Z_OK && ret != Z_STREAM_END)
876 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500877 /* Terminate the decompression. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600878 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
879 png_ptr->zowner = 0;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500880
881 /* This may be a truncated stream (missing or
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500882 * damaged end code). Treat that as a warning.
883 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500884 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500885 png_ptr->pass > 6)
886 png_warning(png_ptr, "Truncated compressed data in IDAT");
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500887
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500888 else
889 png_error(png_ptr, "Decompression error in IDAT");
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500890
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500891 /* Skip the check on unprocessed input */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500892 return;
893 }
894
895 /* Did inflate output any data? */
896 if (png_ptr->zstream.next_out != png_ptr->row_buf)
897 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500898 /* Is this unexpected data after the last row?
899 * If it is, artificially terminate the LZ output
900 * here.
901 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500902 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500903 png_ptr->pass > 6)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500904 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500905 /* Extra data. */
906 png_warning(png_ptr, "Extra compressed data in IDAT");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600907 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
908 png_ptr->zowner = 0;
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500909
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500910 /* Do no more processing; skip the unprocessed
911 * input check below.
912 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500913 return;
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500914 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500915
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500916 /* Do we have a complete row? */
917 if (png_ptr->zstream.avail_out == 0)
918 png_push_process_row(png_ptr);
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500919 }
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500920
921 /* And check for the end of the stream. */
922 if (ret == Z_STREAM_END)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600923 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500924 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500925
926 /* All the data should have been processed, if anything
927 * is left at this point we have bytes of IDAT data
928 * after the zlib end code.
929 */
930 if (png_ptr->zstream.avail_in > 0)
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500931 png_warning(png_ptr, "Extra compression data in IDAT");
Guy Schalnat6d764711995-12-19 03:22:19 -0600932}
933
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500934void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600935png_push_process_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600936{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500937 /* 1.5.6: row_info moved out of png_struct to a local here. */
938 png_row_info row_info;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600939
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500940 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
941 row_info.color_type = png_ptr->color_type;
942 row_info.bit_depth = png_ptr->bit_depth;
943 row_info.channels = png_ptr->channels;
944 row_info.pixel_depth = png_ptr->pixel_depth;
945 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
Guy Schalnat6d764711995-12-19 03:22:19 -0600946
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500947 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
948 {
949 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
Mans Rullgardd3a94802011-11-03 00:47:55 -0500950 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500951 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
952 else
953 png_error(png_ptr, "bad adaptive filter value");
954 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600955
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500956 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
957 * 1.5.6, while the buffer really is this big in current versions of libpng
958 * it may not be in the future, so this was changed just to copy the
959 * interlaced row count:
960 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600961 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -0600962
John Bowler4a12f4a2011-04-17 18:34:22 -0500963#ifdef PNG_READ_TRANSFORMS_SUPPORTED
John Bowler9b872f42011-02-12 09:00:16 -0600964 if (png_ptr->transformations)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500965 png_do_read_transformations(png_ptr, &row_info);
John Bowler4a12f4a2011-04-17 18:34:22 -0500966#endif
Guy Schalnat6d764711995-12-19 03:22:19 -0600967
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500968 /* The transformed pixel depth should match the depth now in row_info. */
969 if (png_ptr->transformed_pixel_depth == 0)
970 {
971 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
972 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
973 png_error(png_ptr, "progressive row overflow");
974 }
975
976 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
977 png_error(png_ptr, "internal progressive row size calculation error");
978
979
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500980#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500981 /* Blow up interlaced rows to full size */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500982 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600983 {
984 if (png_ptr->pass < 6)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500985 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
986 png_ptr->transformations);
Guy Schalnat6d764711995-12-19 03:22:19 -0600987
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600988 switch (png_ptr->pass)
989 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600990 case 0:
991 {
992 int i;
993 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
994 {
995 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500996 png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600997 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500998
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500999 if (png_ptr->pass == 2) /* Pass 1 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001000 {
1001 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1002 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001003 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001004 png_read_push_finish_row(png_ptr);
1005 }
1006 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001007
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001008 if (png_ptr->pass == 4 && png_ptr->height <= 4)
1009 {
1010 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1011 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001012 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001013 png_read_push_finish_row(png_ptr);
1014 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001015 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001016
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001017 if (png_ptr->pass == 6 && png_ptr->height <= 4)
1018 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001019 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001020 png_read_push_finish_row(png_ptr);
1021 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001022
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001023 break;
1024 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001025
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001026 case 1:
1027 {
1028 int i;
1029 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
1030 {
1031 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1032 png_read_push_finish_row(png_ptr);
1033 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001034
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001035 if (png_ptr->pass == 2) /* Skip top 4 generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001036 {
1037 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1038 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001039 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001040 png_read_push_finish_row(png_ptr);
1041 }
1042 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001043
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001044 break;
1045 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001046
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001047 case 2:
1048 {
1049 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001050
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001051 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1052 {
1053 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1054 png_read_push_finish_row(png_ptr);
1055 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001056
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001057 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1058 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001059 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001060 png_read_push_finish_row(png_ptr);
1061 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001062
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001063 if (png_ptr->pass == 4) /* Pass 3 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001064 {
1065 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1066 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001067 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001068 png_read_push_finish_row(png_ptr);
1069 }
1070 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001071
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001072 break;
1073 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001074
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001075 case 3:
1076 {
1077 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001078
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001079 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
1080 {
1081 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1082 png_read_push_finish_row(png_ptr);
1083 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001084
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001085 if (png_ptr->pass == 4) /* Skip top two generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001086 {
1087 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1088 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001089 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001090 png_read_push_finish_row(png_ptr);
1091 }
1092 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001093
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001094 break;
1095 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001096
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001097 case 4:
1098 {
1099 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001100
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001101 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1102 {
1103 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1104 png_read_push_finish_row(png_ptr);
1105 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001106
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001107 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1108 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001109 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001110 png_read_push_finish_row(png_ptr);
1111 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001112
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001113 if (png_ptr->pass == 6) /* Pass 5 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001114 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001115 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001116 png_read_push_finish_row(png_ptr);
1117 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001118
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001119 break;
1120 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001121
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001122 case 5:
1123 {
1124 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001125
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001126 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
1127 {
1128 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1129 png_read_push_finish_row(png_ptr);
1130 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001131
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001132 if (png_ptr->pass == 6) /* Skip top generated row */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001133 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001134 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001135 png_read_push_finish_row(png_ptr);
1136 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001137
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001138 break;
1139 }
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05001140
Glenn Randers-Pehrsonb3edc732010-11-21 14:06:41 -06001141 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001142 case 6:
1143 {
1144 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1145 png_read_push_finish_row(png_ptr);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001146
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001147 if (png_ptr->pass != 6)
1148 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001149
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001150 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001151 png_read_push_finish_row(png_ptr);
1152 }
1153 }
1154 }
1155 else
Guy Schalnat6d764711995-12-19 03:22:19 -06001156#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001157 {
1158 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1159 png_read_push_finish_row(png_ptr);
1160 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001161}
1162
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001163void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001164png_read_push_finish_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001165{
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001166#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001167 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001168
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001169 /* Start of interlace block */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001170 static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001171
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001172 /* Offset to next interlace block */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001173 static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001174
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001175 /* Start of interlace block in the y direction */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001176 static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001177
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001178 /* Offset to next interlace block in the y direction */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001179 static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001180
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001181 /* Height of interlace block. This is not currently used - if you need
1182 * it, uncomment it here and in png.h
John Bowlerbaeb6d12011-11-26 18:21:02 -06001183 static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001184 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001185#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001186
Guy Schalnat6d764711995-12-19 03:22:19 -06001187 png_ptr->row_number++;
1188 if (png_ptr->row_number < png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001189 return;
Guy Schalnat6d764711995-12-19 03:22:19 -06001190
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001191#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat6d764711995-12-19 03:22:19 -06001192 if (png_ptr->interlaced)
1193 {
1194 png_ptr->row_number = 0;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001195 memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001196
Guy Schalnat6d764711995-12-19 03:22:19 -06001197 do
1198 {
1199 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001200 if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1201 (png_ptr->pass == 3 && png_ptr->width < 3) ||
1202 (png_ptr->pass == 5 && png_ptr->width < 2))
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001203 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001204
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05001205 if (png_ptr->pass > 7)
1206 png_ptr->pass--;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001207
Guy Schalnat6d764711995-12-19 03:22:19 -06001208 if (png_ptr->pass >= 7)
1209 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001210
Guy Schalnat6d764711995-12-19 03:22:19 -06001211 png_ptr->iwidth = (png_ptr->width +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001212 png_pass_inc[png_ptr->pass] - 1 -
1213 png_pass_start[png_ptr->pass]) /
1214 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001215
Guy Schalnat6d764711995-12-19 03:22:19 -06001216 if (png_ptr->transformations & PNG_INTERLACE)
1217 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001218
1219 png_ptr->num_rows = (png_ptr->height +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001220 png_pass_yinc[png_ptr->pass] - 1 -
1221 png_pass_ystart[png_ptr->pass]) /
1222 png_pass_yinc[png_ptr->pass];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001223
1224 } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
Guy Schalnat6d764711995-12-19 03:22:19 -06001225 }
Glenn Randers-Pehrsona31c74f2009-05-18 15:52:01 -05001226#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat6d764711995-12-19 03:22:19 -06001227}
1228
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001229void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001230png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001231{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001232 if (png_ptr->info_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001233 (*(png_ptr->info_fn))(png_ptr, info_ptr);
1234}
1235
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001236void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001237png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001238{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001239 if (png_ptr->end_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001240 (*(png_ptr->end_fn))(png_ptr, info_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001241}
1242
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001243void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001244png_push_have_row(png_structrp png_ptr, png_bytep row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001245{
Glenn Randers-Pehrson78d55452010-06-19 07:03:50 -05001246 if (png_ptr->row_fn != NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001247 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1248 (int)png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -06001249}
1250
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001251#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001252void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001253png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001254 png_const_bytep new_row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001255{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001256 if (png_ptr == NULL)
1257 return;
1258
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001259 /* new_row is a flag here - if it is NULL then the app callback was called
1260 * from an empty row (see the calls to png_struct::row_fn below), otherwise
1261 * it must be png_ptr->row_buf+1
1262 */
1263 if (new_row != NULL)
1264 png_combine_row(png_ptr, old_row, 1/*display*/);
Guy Schalnat6d764711995-12-19 03:22:19 -06001265}
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001266#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat6d764711995-12-19 03:22:19 -06001267
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001268void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001269png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001270 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1271 png_progressive_end_ptr end_fn)
Guy Schalnat6d764711995-12-19 03:22:19 -06001272{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001273 if (png_ptr == NULL)
1274 return;
1275
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001276 png_ptr->info_fn = info_fn;
1277 png_ptr->row_fn = row_fn;
Guy Schalnat6d764711995-12-19 03:22:19 -06001278 png_ptr->end_fn = end_fn;
Guy Schalnate5a37791996-06-05 15:50:50 -05001279
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -05001280 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001281}
1282
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001283png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001284png_get_progressive_ptr(png_const_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001285{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001286 if (png_ptr == NULL)
1287 return (NULL);
1288
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001289 return png_ptr->io_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001290}
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001291#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */