blob: e283627b77cd34e25e5ccccbf14137332a999ac6 [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 *
Cosmin Trutaa8738932018-07-28 18:47:21 -04004 * Copyright (c) 2018 Cosmin Truta
Cosmin Truta46aedd82018-07-15 23:58:00 -04005 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
Cosmin Trutaa8738932018-07-28 18:47:21 -04006 * Copyright (c) 1996-1997 Andreas Dilger
7 * 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
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060022#define PNG_READ_tEXt_MODE 4
23#define PNG_READ_zTXt_MODE 5
24#define PNG_READ_DONE_MODE 6
25#define PNG_READ_iTXt_MODE 7
26#define PNG_ERROR_MODE 8
27
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -050028#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
29if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
30 { png_push_save_buffer(png_ptr); return; }
Glenn Randers-Pehrson25d240d2014-10-07 18:46:53 -050031#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -050032if (png_ptr->buffer_size < N) \
33 { png_push_save_buffer(png_ptr); return; }
34
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050035void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060036png_process_data(png_structrp png_ptr, png_inforp info_ptr,
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -040037 png_bytep buffer, size_t buffer_size)
Guy Schalnat6d764711995-12-19 03:22:19 -060038{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050039 if (png_ptr == NULL || info_ptr == NULL)
40 return;
41
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060042 png_push_restore_buffer(png_ptr, buffer, buffer_size);
Guy Schalnat6d764711995-12-19 03:22:19 -060043
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060044 while (png_ptr->buffer_size)
45 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060046 png_process_some_data(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060047 }
Guy Schalnat6d764711995-12-19 03:22:19 -060048}
49
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -040050size_t PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060051png_process_data_pause(png_structrp png_ptr, int save)
John Bowler0a5c9c02011-01-22 17:36:34 -060052{
53 if (png_ptr != NULL)
54 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -050055 /* It's easiest for the caller if we do the save; then the caller doesn't
John Bowler0a5c9c02011-01-22 17:36:34 -060056 * have to supply the same data again:
57 */
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -060058 if (save != 0)
John Bowler0a5c9c02011-01-22 17:36:34 -060059 png_push_save_buffer(png_ptr);
60 else
61 {
62 /* This includes any pending saved bytes: */
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -040063 size_t remaining = png_ptr->buffer_size;
John Bowler0a5c9c02011-01-22 17:36:34 -060064 png_ptr->buffer_size = 0;
65
66 /* So subtract the saved buffer size, unless all the data
67 * is actually 'saved', in which case we just return 0
68 */
69 if (png_ptr->save_buffer_size < remaining)
70 return remaining - png_ptr->save_buffer_size;
71 }
72 }
73
74 return 0;
75}
76
77png_uint_32 PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060078png_process_data_skip(png_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -060079{
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -050080/* TODO: Deprecate and remove this API.
81 * Somewhere the implementation of this seems to have been lost,
82 * or abandoned. It was only to support some internal back-door access
83 * to png_struct) in libpng-1.4.x.
84 */
John Bowler25bfb132015-06-03 14:31:08 -050085 png_app_warning(png_ptr,
86"png_process_data_skip is not implemented in any current version of libpng");
87 return 0;
John Bowler0a5c9c02011-01-22 17:36:34 -060088}
89
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060090/* What we do with the incoming data depends on what we were previously
91 * doing before we ran out of data...
92 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050093void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -060094png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -060095{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050096 if (png_ptr == NULL)
97 return;
98
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060099 switch (png_ptr->process_mode)
100 {
101 case PNG_READ_SIG_MODE:
102 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600103 png_push_read_sig(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600104 break;
105 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500106
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600107 case PNG_READ_CHUNK_MODE:
108 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600109 png_push_read_chunk(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600110 break;
111 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500112
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600113 case PNG_READ_IDAT_MODE:
114 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500115 png_push_read_IDAT(png_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 default:
120 {
121 png_ptr->buffer_size = 0;
122 break;
123 }
124 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600125}
126
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600127/* Read any remaining signature bytes from the stream and compare them with
128 * the correct PNG signature. It is possible that this routine is called
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500129 * with bytes already read from the signature, either because they have been
130 * checked by the calling application, or because of multiple calls to this
131 * routine.
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600132 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500133void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600134png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600135{
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400136 size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */
137 size_t num_to_check = 8 - num_checked;
Guy Schalnat6d764711995-12-19 03:22:19 -0600138
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600139 if (png_ptr->buffer_size < num_to_check)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600140 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600141 num_to_check = png_ptr->buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600142 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600143
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600144 png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600145 num_to_check);
Glenn Randers-Pehrsonc5370ed2015-03-21 11:54:32 -0500146 png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
Guy Schalnat6d764711995-12-19 03:22:19 -0600147
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600148 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600149 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600150 if (num_checked < 4 &&
151 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
152 png_error(png_ptr, "Not a PNG file");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500153
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600154 else
155 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600156 }
157 else
158 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600159 if (png_ptr->sig_bytes >= 8)
160 {
161 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
162 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600163 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600164}
165
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500166void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600167png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600168{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500169 png_uint_32 chunk_name;
Glenn Randers-Pehrsonbd757ac2013-11-18 18:40:39 -0600170#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600171 int keep; /* unknown handling method */
172#endif
Glenn Randers-Pehrsona2567be2009-10-19 20:31:31 -0500173
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500174 /* First we make sure we have enough data for the 4-byte chunk name
175 * and the 4-byte chunk length before proceeding with decoding the
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600176 * chunk data. To fully decode each of these chunks, we also make
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500177 * sure we have enough data in the buffer for the 4-byte CRC at the
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600178 * end of every chunk (except IDAT, which is handled separately).
179 */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500180 if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600181 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600182 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500183 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600184
Glenn Randers-Pehrson25d240d2014-10-07 18:46:53 -0500185 PNG_PUSH_SAVE_BUFFER_IF_LT(8)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600186 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500187 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600188 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500189 png_crc_read(png_ptr, chunk_tag, 4);
190 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500191 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
Glenn Randers-Pehrsonfcd1bb92017-08-05 15:08:40 -0500192 png_check_chunk_length(png_ptr, png_ptr->push_length);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600193 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600194 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600195
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500196 chunk_name = png_ptr->chunk_name;
197
198 if (chunk_name == png_IDAT)
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -0500199 {
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500200 if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600201 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600202
203 /* If we reach an IDAT chunk, this means we have read all of the
204 * header chunks, and we can start reading the image (or if this
205 * is called after the image has been read - we have an error).
206 */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500207 if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600208 png_error(png_ptr, "Missing IHDR before IDAT");
209
210 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
Glenn Randers-Pehrsonb963fee2014-11-01 13:18:36 -0500211 (png_ptr->mode & PNG_HAVE_PLTE) == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600212 png_error(png_ptr, "Missing PLTE before IDAT");
213
Glenn Randers-Pehrsoneb657ae2014-02-22 21:59:40 -0600214 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600215
Timothy Nikkel3f46c672016-05-29 09:31:48 -0500216 if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
217 if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
218 if (png_ptr->push_length == 0)
219 return;
220
221 png_ptr->mode |= PNG_HAVE_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600222
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500223 if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600224 png_benign_error(png_ptr, "Too many IDATs found");
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -0500225 }
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500226
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500227 if (chunk_name == png_IHDR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600228 {
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500229 if (png_ptr->push_length != 13)
230 png_error(png_ptr, "Invalid IHDR length");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500231
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500232 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600233 png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600234 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500235
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500236 else if (chunk_name == png_IEND)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500237 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500238 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500239 png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
240
241 png_ptr->process_mode = PNG_READ_DONE_MODE;
242 png_push_have_end(png_ptr, info_ptr);
243 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500244
Glenn Randers-Pehrsonbd757ac2013-11-18 18:40:39 -0600245#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600246 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500247 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500248 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600249 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500250
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500251 if (chunk_name == png_PLTE)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500252 png_ptr->mode |= PNG_HAVE_PLTE;
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500253 }
254#endif
Glenn Randers-Pehrson012d36f2013-11-17 19:42:48 -0600255
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500256 else if (chunk_name == png_PLTE)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600257 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500258 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600259 png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600260 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500261
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500262 else if (chunk_name == png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600263 {
264 png_ptr->idat_size = png_ptr->push_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600265 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600266 png_push_have_info(png_ptr, info_ptr);
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600267 png_ptr->zstream.avail_out =
268 (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
269 png_ptr->iwidth) + 1;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600270 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600271 return;
272 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500273
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500274#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500275 else if (png_ptr->chunk_name == png_gAMA)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600276 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500277 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600278 png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600279 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500280
Guy Schalnat6d764711995-12-19 03:22:19 -0600281#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500282#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500283 else if (png_ptr->chunk_name == png_sBIT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600284 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500285 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600286 png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600287 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500288
Guy Schalnat6d764711995-12-19 03:22:19 -0600289#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500290#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500291 else if (png_ptr->chunk_name == png_cHRM)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600292 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500293 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600294 png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600295 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500296
Guy Schalnat6d764711995-12-19 03:22:19 -0600297#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500298#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500299 else if (chunk_name == png_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600300 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500301 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600302 png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
303 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500304
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600305#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500306#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500307 else if (png_ptr->chunk_name == png_iCCP)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600308 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500309 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600310 png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
311 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500312
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600313#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500314#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500315 else if (chunk_name == png_sPLT)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600316 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500317 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600318 png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
319 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500320
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600321#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500322#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500323 else if (chunk_name == png_tRNS)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600324 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500325 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600326 png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600327 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500328
Guy Schalnat6d764711995-12-19 03:22:19 -0600329#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500330#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500331 else if (chunk_name == png_bKGD)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600332 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500333 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600334 png_handle_bKGD(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_hIST_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500339 else if (chunk_name == png_hIST)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600340 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500341 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600342 png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600343 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500344
Guy Schalnat6d764711995-12-19 03:22:19 -0600345#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500346#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500347 else if (chunk_name == png_pHYs)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600348 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500349 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600350 png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600351 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500352
Guy Schalnat6d764711995-12-19 03:22:19 -0600353#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500354#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500355 else if (chunk_name == png_oFFs)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600356 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500357 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600358 png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600359 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600360#endif
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500361
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500362#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500363 else if (chunk_name == png_pCAL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500364 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500365 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger47a0c421997-05-16 02:46:07 -0500366 png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
367 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500368
Andreas Dilger47a0c421997-05-16 02:46:07 -0500369#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500370#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500371 else if (chunk_name == png_sCAL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600372 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500373 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600374 png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
375 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500376
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600377#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500378#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500379 else if (chunk_name == png_tIME)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600380 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500381 PNG_PUSH_SAVE_BUFFER_IF_FULL
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600382 png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600383 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500384
Guy Schalnat6d764711995-12-19 03:22:19 -0600385#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500386#ifdef PNG_READ_tEXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500387 else if (chunk_name == png_tEXt)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600388 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500389 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600390 png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600391 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500392
Guy Schalnat6d764711995-12-19 03:22:19 -0600393#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500394#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500395 else if (chunk_name == png_zTXt)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600396 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500397 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600398 png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600399 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500400
Guy Schalnat6d764711995-12-19 03:22:19 -0600401#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500402#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500403 else if (chunk_name == png_iTXt)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600404 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500405 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600406 png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600407 }
408#endif
Glenn Randers-Pehrson416bb932013-11-17 11:01:31 -0600409
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600410 else
411 {
Glenn Randers-Pehrson27f03322014-10-04 10:28:58 -0500412 PNG_PUSH_SAVE_BUFFER_IF_FULL
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600413 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500414 PNG_HANDLE_CHUNK_AS_DEFAULT);
Glenn Randers-Pehrson68dfa9e2013-11-17 19:26:40 -0600415 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600416
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600417 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Guy Schalnat6d764711995-12-19 03:22:19 -0600418}
419
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -0600420void PNGCBAPI
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400421png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600422{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600423 png_bytep ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -0600424
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500425 if (png_ptr == NULL)
426 return;
427
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600428 ptr = buffer;
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500429 if (png_ptr->save_buffer_size != 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600430 {
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400431 size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600432
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600433 if (length < png_ptr->save_buffer_size)
434 save_size = length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500435
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600436 else
437 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600438
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600439 memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600440 length -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500441 ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600442 png_ptr->buffer_size -= save_size;
443 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500444 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600445 }
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500446 if (length != 0 && png_ptr->current_buffer_size != 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600447 {
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400448 size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600449
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600450 if (length < png_ptr->current_buffer_size)
451 save_size = length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500452
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600453 else
454 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600455
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600456 memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600457 png_ptr->buffer_size -= save_size;
458 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500459 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600460 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600461}
462
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500463void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600464png_push_save_buffer(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600465{
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500466 if (png_ptr->save_buffer_size != 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600467 {
468 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
469 {
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400470 size_t i, istop;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600471 png_bytep sp;
472 png_bytep dp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600473
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500474 istop = png_ptr->save_buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600475 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600476 i < istop; i++, sp++, dp++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600477 {
478 *dp = *sp;
479 }
480 }
481 }
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600482 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600483 png_ptr->save_buffer_max)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600484 {
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400485 size_t new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600486 png_bytep old_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600487
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600488 if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600489 (png_ptr->current_buffer_size + 256))
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600490 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600491 png_error(png_ptr, "Potential overflow of save_buffer");
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600492 }
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600493
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600494 new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600495 old_buffer = png_ptr->save_buffer;
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600496 png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400497 (size_t)new_max);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500498
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600499 if (png_ptr->save_buffer == NULL)
500 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600501 png_free(png_ptr, old_buffer);
502 png_error(png_ptr, "Insufficient memory for save_buffer");
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600503 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500504
Glenn Randers-Pehrson89158b92016-06-03 18:40:42 -0500505 if (old_buffer)
506 memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
507 else if (png_ptr->save_buffer_size)
508 png_error(png_ptr, "save_buffer error");
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500509 png_free(png_ptr, old_buffer);
510 png_ptr->save_buffer_max = new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600511 }
512 if (png_ptr->current_buffer_size)
513 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600514 memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500515 png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600516 png_ptr->save_buffer_size += png_ptr->current_buffer_size;
517 png_ptr->current_buffer_size = 0;
518 }
519 png_ptr->save_buffer_ptr = png_ptr->save_buffer;
520 png_ptr->buffer_size = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600521}
522
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500523void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600524png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400525 size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600526{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600527 png_ptr->current_buffer = buffer;
528 png_ptr->current_buffer_size = buffer_length;
529 png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
530 png_ptr->current_buffer_ptr = png_ptr->current_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600531}
532
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500533void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600534png_push_read_IDAT(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600535{
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500536 if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600537 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600538 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500539 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600540
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500541 /* TODO: this code can be commoned up with the same code in push_read */
Glenn Randers-Pehrson25d240d2014-10-07 18:46:53 -0500542 PNG_PUSH_SAVE_BUFFER_IF_LT(8)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600543 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500544 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600545 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500546 png_crc_read(png_ptr, chunk_tag, 4);
547 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600548 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600549
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500550 if (png_ptr->chunk_name != png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600551 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500552 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500553
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500554 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600555 png_error(png_ptr, "Not enough compressed data");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500556
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600557 return;
558 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600559
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600560 png_ptr->idat_size = png_ptr->push_length;
561 }
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500562
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500563 if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600564 {
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400565 size_t save_size = png_ptr->save_buffer_size;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500566 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600567
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500568 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
569 * are of different types and we don't know which variable has the fewest
570 * bits. Carefully select the smaller and cast it to the type of the
571 * larger - this cannot overflow. Do not cast in the following test - it
Glenn Randers-Pehrson8b83ff32015-08-13 20:57:18 -0500572 * will break on either 16-bit or 64-bit platforms.
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500573 */
574 if (idat_size < save_size)
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400575 save_size = (size_t)idat_size;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500576
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600577 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500578 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600579
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600580 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500581
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500582 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500583
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500584 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600585 png_ptr->buffer_size -= save_size;
586 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500587 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600588 }
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500589
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500590 if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600591 {
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400592 size_t save_size = png_ptr->current_buffer_size;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500593 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600594
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500595 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
596 * are of different types and we don't know which variable has the fewest
597 * bits. Carefully select the smaller and cast it to the type of the
598 * larger - this cannot overflow.
599 */
600 if (idat_size < save_size)
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400601 save_size = (size_t)idat_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500602
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600603 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500604 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600605
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600606 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500607
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500608 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600609
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500610 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600611 png_ptr->buffer_size -= save_size;
612 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500613 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600614 }
Glenn Randers-Pehrsonf86720c2015-06-11 22:00:14 -0500615
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500616 if (png_ptr->idat_size == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600617 {
Glenn Randers-Pehrson25d240d2014-10-07 18:46:53 -0500618 PNG_PUSH_SAVE_BUFFER_IF_LT(4)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600619 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600620 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500621 png_ptr->mode |= PNG_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600622 png_ptr->zowner = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600623 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600624}
625
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500626void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600627png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400628 size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600629{
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500630 /* The caller checks for a non-zero buffer length. */
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500631 if (!(buffer_length > 0) || buffer == NULL)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500632 png_error(png_ptr, "No IDAT data (internal error)");
Guy Schalnat6d764711995-12-19 03:22:19 -0600633
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500634 /* This routine must process all the data it has been given
635 * before returning, calling the row callback as required to
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500636 * handle the uncompressed results.
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500637 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600638 png_ptr->zstream.next_in = buffer;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600639 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600640 png_ptr->zstream.avail_in = (uInt)buffer_length;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500641
642 /* Keep going until the decompressed data is all processed
643 * or the stream marked as finished.
644 */
645 while (png_ptr->zstream.avail_in > 0 &&
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -0600646 (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600647 {
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500648 int ret;
649
650 /* We have data for zlib, but we must check that zlib
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500651 * has someplace to put the results. It doesn't matter
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500652 * if we don't expect any results -- it may be the input
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500653 * data is just the LZ end code.
654 */
655 if (!(png_ptr->zstream.avail_out > 0))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600656 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600657 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
658 png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
659 png_ptr->iwidth) + 1);
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500660
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600661 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600662 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500663
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500664 /* Using Z_SYNC_FLUSH here means that an unterminated
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500665 * LZ stream (a stream with a missing end code) can still
666 * be handled, otherwise (Z_NO_FLUSH) a future zlib
667 * implementation might defer output and therefore
668 * change the current behavior (see comments in inflate.c
669 * for why this doesn't happen at present with zlib 1.2.5).
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500670 */
John Bowler28a1cdf2015-11-27 23:57:39 -0800671 ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500672
673 /* Check for any failure before proceeding. */
674 if (ret != Z_OK && ret != Z_STREAM_END)
675 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500676 /* Terminate the decompression. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600677 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
678 png_ptr->zowner = 0;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500679
680 /* This may be a truncated stream (missing or
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500681 * damaged end code). Treat that as a warning.
682 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500683 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500684 png_ptr->pass > 6)
685 png_warning(png_ptr, "Truncated compressed data in IDAT");
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500686
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500687 else
Glenn Randers-Pehrson61a9a052016-12-27 07:37:23 -0600688 {
689 if (ret == Z_DATA_ERROR)
690 png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
691 else
692 png_error(png_ptr, "Decompression error in IDAT");
693 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500694
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500695 /* Skip the check on unprocessed input */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500696 return;
697 }
698
699 /* Did inflate output any data? */
700 if (png_ptr->zstream.next_out != png_ptr->row_buf)
701 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500702 /* Is this unexpected data after the last row?
703 * If it is, artificially terminate the LZ output
704 * here.
705 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500706 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500707 png_ptr->pass > 6)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500708 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500709 /* Extra data. */
710 png_warning(png_ptr, "Extra compressed data in IDAT");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600711 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
712 png_ptr->zowner = 0;
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500713
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500714 /* Do no more processing; skip the unprocessed
715 * input check below.
716 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500717 return;
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500718 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500719
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500720 /* Do we have a complete row? */
721 if (png_ptr->zstream.avail_out == 0)
722 png_push_process_row(png_ptr);
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500723 }
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500724
725 /* And check for the end of the stream. */
726 if (ret == Z_STREAM_END)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600727 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500728 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500729
730 /* All the data should have been processed, if anything
731 * is left at this point we have bytes of IDAT data
732 * after the zlib end code.
733 */
734 if (png_ptr->zstream.avail_in > 0)
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500735 png_warning(png_ptr, "Extra compression data in IDAT");
Guy Schalnat6d764711995-12-19 03:22:19 -0600736}
737
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500738void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600739png_push_process_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600740{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500741 /* 1.5.6: row_info moved out of png_struct to a local here. */
742 png_row_info row_info;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600743
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500744 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
745 row_info.color_type = png_ptr->color_type;
746 row_info.bit_depth = png_ptr->bit_depth;
747 row_info.channels = png_ptr->channels;
748 row_info.pixel_depth = png_ptr->pixel_depth;
749 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
Guy Schalnat6d764711995-12-19 03:22:19 -0600750
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500751 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
752 {
753 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
Mans Rullgardd3a94802011-11-03 00:47:55 -0500754 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500755 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
756 else
757 png_error(png_ptr, "bad adaptive filter value");
758 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600759
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500760 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
761 * 1.5.6, while the buffer really is this big in current versions of libpng
762 * it may not be in the future, so this was changed just to copy the
763 * interlaced row count:
764 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600765 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -0600766
John Bowler4a12f4a2011-04-17 18:34:22 -0500767#ifdef PNG_READ_TRANSFORMS_SUPPORTED
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500768 if (png_ptr->transformations != 0)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500769 png_do_read_transformations(png_ptr, &row_info);
John Bowler4a12f4a2011-04-17 18:34:22 -0500770#endif
Guy Schalnat6d764711995-12-19 03:22:19 -0600771
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500772 /* The transformed pixel depth should match the depth now in row_info. */
773 if (png_ptr->transformed_pixel_depth == 0)
774 {
775 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
776 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
777 png_error(png_ptr, "progressive row overflow");
778 }
779
780 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
781 png_error(png_ptr, "internal progressive row size calculation error");
782
783
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500784#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500785 /* Expand interlaced rows to full size */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500786 if (png_ptr->interlaced != 0 &&
787 (png_ptr->transformations & PNG_INTERLACE) != 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600788 {
789 if (png_ptr->pass < 6)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500790 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500791 png_ptr->transformations);
Guy Schalnat6d764711995-12-19 03:22:19 -0600792
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500793 switch (png_ptr->pass)
794 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600795 case 0:
796 {
797 int i;
798 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
799 {
800 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500801 png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600802 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500803
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500804 if (png_ptr->pass == 2) /* Pass 1 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600805 {
806 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
807 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500808 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600809 png_read_push_finish_row(png_ptr);
810 }
811 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500812
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500813 if (png_ptr->pass == 4 && png_ptr->height <= 4)
814 {
815 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
816 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500817 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500818 png_read_push_finish_row(png_ptr);
819 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500820 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500821
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500822 if (png_ptr->pass == 6 && png_ptr->height <= 4)
823 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500824 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500825 png_read_push_finish_row(png_ptr);
826 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500827
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600828 break;
829 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500830
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600831 case 1:
832 {
833 int i;
834 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
835 {
836 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
837 png_read_push_finish_row(png_ptr);
838 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500839
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500840 if (png_ptr->pass == 2) /* Skip top 4 generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600841 {
842 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
843 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500844 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600845 png_read_push_finish_row(png_ptr);
846 }
847 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500848
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600849 break;
850 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500851
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600852 case 2:
853 {
854 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500855
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600856 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
857 {
858 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
859 png_read_push_finish_row(png_ptr);
860 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500861
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600862 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
863 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500864 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600865 png_read_push_finish_row(png_ptr);
866 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500867
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500868 if (png_ptr->pass == 4) /* Pass 3 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600869 {
870 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
871 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500872 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600873 png_read_push_finish_row(png_ptr);
874 }
875 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500876
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600877 break;
878 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500879
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600880 case 3:
881 {
882 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500883
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600884 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
885 {
886 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
887 png_read_push_finish_row(png_ptr);
888 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500889
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500890 if (png_ptr->pass == 4) /* Skip top two generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600891 {
892 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
893 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500894 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600895 png_read_push_finish_row(png_ptr);
896 }
897 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500898
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600899 break;
900 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500901
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600902 case 4:
903 {
904 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500905
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600906 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
907 {
908 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
909 png_read_push_finish_row(png_ptr);
910 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500911
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600912 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
913 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500914 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600915 png_read_push_finish_row(png_ptr);
916 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500917
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500918 if (png_ptr->pass == 6) /* Pass 5 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600919 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500920 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600921 png_read_push_finish_row(png_ptr);
922 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500923
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600924 break;
925 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500926
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600927 case 5:
928 {
929 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500930
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600931 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
932 {
933 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
934 png_read_push_finish_row(png_ptr);
935 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500936
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500937 if (png_ptr->pass == 6) /* Skip top generated row */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600938 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500939 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600940 png_read_push_finish_row(png_ptr);
941 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500942
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600943 break;
944 }
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -0500945
Glenn Randers-Pehrsonb3edc732010-11-21 14:06:41 -0600946 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600947 case 6:
948 {
949 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
950 png_read_push_finish_row(png_ptr);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500951
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600952 if (png_ptr->pass != 6)
953 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500954
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500955 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600956 png_read_push_finish_row(png_ptr);
957 }
958 }
959 }
960 else
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -0600961#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600962 {
963 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
964 png_read_push_finish_row(png_ptr);
965 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600966}
967
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500968void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600969png_read_push_finish_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600970{
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -0600971#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500972 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600973
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500974 /* Start of interlace block */
Cosmin Truta1ef88822018-08-18 21:01:02 -0400975 static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600976
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500977 /* Offset to next interlace block */
Cosmin Truta1ef88822018-08-18 21:01:02 -0400978 static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600979
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500980 /* Start of interlace block in the y direction */
Cosmin Truta1ef88822018-08-18 21:01:02 -0400981 static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600982
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500983 /* Offset to next interlace block in the y direction */
Cosmin Truta1ef88822018-08-18 21:01:02 -0400984 static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600985
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600986 /* Height of interlace block. This is not currently used - if you need
987 * it, uncomment it here and in png.h
Cosmin Truta1ef88822018-08-18 21:01:02 -0400988 static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600989 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600990#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600991
Guy Schalnat6d764711995-12-19 03:22:19 -0600992 png_ptr->row_number++;
993 if (png_ptr->row_number < png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600994 return;
Guy Schalnat6d764711995-12-19 03:22:19 -0600995
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -0600996#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500997 if (png_ptr->interlaced != 0)
Guy Schalnat6d764711995-12-19 03:22:19 -0600998 {
999 png_ptr->row_number = 0;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001000 memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001001
Guy Schalnat6d764711995-12-19 03:22:19 -06001002 do
1003 {
1004 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001005 if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1006 (png_ptr->pass == 3 && png_ptr->width < 3) ||
1007 (png_ptr->pass == 5 && png_ptr->width < 2))
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001008 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001009
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05001010 if (png_ptr->pass > 7)
1011 png_ptr->pass--;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001012
Guy Schalnat6d764711995-12-19 03:22:19 -06001013 if (png_ptr->pass >= 7)
1014 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001015
Guy Schalnat6d764711995-12-19 03:22:19 -06001016 png_ptr->iwidth = (png_ptr->width +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001017 png_pass_inc[png_ptr->pass] - 1 -
1018 png_pass_start[png_ptr->pass]) /
1019 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001020
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001021 if ((png_ptr->transformations & PNG_INTERLACE) != 0)
Guy Schalnat6d764711995-12-19 03:22:19 -06001022 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001023
1024 png_ptr->num_rows = (png_ptr->height +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001025 png_pass_yinc[png_ptr->pass] - 1 -
1026 png_pass_ystart[png_ptr->pass]) /
1027 png_pass_yinc[png_ptr->pass];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001028
1029 } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
Guy Schalnat6d764711995-12-19 03:22:19 -06001030 }
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -06001031#endif /* READ_INTERLACING */
Guy Schalnat6d764711995-12-19 03:22:19 -06001032}
1033
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001034void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001035png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001036{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001037 if (png_ptr->info_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001038 (*(png_ptr->info_fn))(png_ptr, info_ptr);
1039}
1040
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001041void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001042png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001043{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001044 if (png_ptr->end_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001045 (*(png_ptr->end_fn))(png_ptr, info_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001046}
1047
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001048void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001049png_push_have_row(png_structrp png_ptr, png_bytep row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001050{
Glenn Randers-Pehrson78d55452010-06-19 07:03:50 -05001051 if (png_ptr->row_fn != NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001052 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001053 (int)png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -06001054}
1055
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -06001056#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001057void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001058png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001059 png_const_bytep new_row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001060{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001061 if (png_ptr == NULL)
1062 return;
1063
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001064 /* new_row is a flag here - if it is NULL then the app callback was called
1065 * from an empty row (see the calls to png_struct::row_fn below), otherwise
1066 * it must be png_ptr->row_buf+1
1067 */
1068 if (new_row != NULL)
Glenn Randers-Pehrson72855fb2014-04-13 21:27:25 -05001069 png_combine_row(png_ptr, old_row, 1/*blocky display*/);
Guy Schalnat6d764711995-12-19 03:22:19 -06001070}
Glenn Randers-Pehrson6ef579d2015-01-27 07:02:46 -06001071#endif /* READ_INTERLACING */
Guy Schalnat6d764711995-12-19 03:22:19 -06001072
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001073void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001074png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001075 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1076 png_progressive_end_ptr end_fn)
Guy Schalnat6d764711995-12-19 03:22:19 -06001077{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001078 if (png_ptr == NULL)
1079 return;
1080
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001081 png_ptr->info_fn = info_fn;
1082 png_ptr->row_fn = row_fn;
Guy Schalnat6d764711995-12-19 03:22:19 -06001083 png_ptr->end_fn = end_fn;
Guy Schalnate5a37791996-06-05 15:50:50 -05001084
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -05001085 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001086}
1087
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001088png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001089png_get_progressive_ptr(png_const_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001090{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001091 if (png_ptr == NULL)
1092 return (NULL);
1093
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001094 return png_ptr->io_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001095}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -06001096#endif /* PROGRESSIVE_READ */