blob: af28e3645655c7edc669176a44721ee7923e2514 [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-Pehrsona31c74f2009-05-18 15:52:01 -05004 * Last changed in libpng 1.4.0 [May 18, 2009]
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -06006 * Copyright (c) 1998-2009 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05007 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 */
Guy Schalnat6d764711995-12-19 03:22:19 -060010
Guy Schalnat6d764711995-12-19 03:22:19 -060011#include "png.h"
Guy Schalnat4ee97b01996-01-16 01:51:56 -060012#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050013#include "pngpriv.h"
Guy Schalnat4ee97b01996-01-16 01:51:56 -060014
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060015/* push model modes */
16#define PNG_READ_SIG_MODE 0
17#define PNG_READ_CHUNK_MODE 1
18#define PNG_READ_IDAT_MODE 2
19#define PNG_SKIP_MODE 3
20#define PNG_READ_tEXt_MODE 4
21#define PNG_READ_zTXt_MODE 5
22#define PNG_READ_DONE_MODE 6
23#define PNG_READ_iTXt_MODE 7
24#define PNG_ERROR_MODE 8
25
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050026void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060027png_process_data(png_structp png_ptr, png_infop info_ptr,
Andreas Dilger47a0c421997-05-16 02:46:07 -050028 png_bytep buffer, png_size_t buffer_size)
Guy Schalnat6d764711995-12-19 03:22:19 -060029{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050030 if (png_ptr == NULL || info_ptr == NULL)
31 return;
32
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060033 png_push_restore_buffer(png_ptr, buffer, buffer_size);
Guy Schalnat6d764711995-12-19 03:22:19 -060034
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060035 while (png_ptr->buffer_size)
36 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060037 png_process_some_data(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060038 }
Guy Schalnat6d764711995-12-19 03:22:19 -060039}
40
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060041/* What we do with the incoming data depends on what we were previously
42 * doing before we ran out of data...
43 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050044void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060045png_process_some_data(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -060046{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050047 if (png_ptr == NULL)
48 return;
49
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060050 switch (png_ptr->process_mode)
51 {
52 case PNG_READ_SIG_MODE:
53 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060054 png_push_read_sig(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060055 break;
56 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050057
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060058 case PNG_READ_CHUNK_MODE:
59 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060060 png_push_read_chunk(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060061 break;
62 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050063
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060064 case PNG_READ_IDAT_MODE:
65 {
Guy Schalnate5a37791996-06-05 15:50:50 -050066 png_push_read_IDAT(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060067 break;
68 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050069
Guy Schalnat6d764711995-12-19 03:22:19 -060070#if defined(PNG_READ_tEXt_SUPPORTED)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060071 case PNG_READ_tEXt_MODE:
72 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060073 png_push_read_tEXt(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060074 break;
75 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050076
Guy Schalnat6d764711995-12-19 03:22:19 -060077#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060078#if defined(PNG_READ_zTXt_SUPPORTED)
79 case PNG_READ_zTXt_MODE:
80 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060081 png_push_read_zTXt(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060082 break;
83 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050084
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060085#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060086#if defined(PNG_READ_iTXt_SUPPORTED)
87 case PNG_READ_iTXt_MODE:
88 {
89 png_push_read_iTXt(png_ptr, info_ptr);
90 break;
91 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050092
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060093#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060094 case PNG_SKIP_MODE:
95 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050096 png_push_crc_finish(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060097 break;
98 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050099
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600100 default:
101 {
102 png_ptr->buffer_size = 0;
103 break;
104 }
105 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600106}
107
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600108/* Read any remaining signature bytes from the stream and compare them with
109 * the correct PNG signature. It is possible that this routine is called
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500110 * with bytes already read from the signature, either because they have been
111 * checked by the calling application, or because of multiple calls to this
112 * routine.
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600113 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500114void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600115png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600116{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500117 png_size_t num_checked = png_ptr->sig_bytes,
118 num_to_check = 8 - num_checked;
Guy Schalnat6d764711995-12-19 03:22:19 -0600119
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600120 if (png_ptr->buffer_size < num_to_check)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600121 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600122 num_to_check = png_ptr->buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600123 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600124
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600125 png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
Andreas Dilger47a0c421997-05-16 02:46:07 -0500126 num_to_check);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500127 png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
Guy Schalnat6d764711995-12-19 03:22:19 -0600128
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600129 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600130 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600131 if (num_checked < 4 &&
132 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
133 png_error(png_ptr, "Not a PNG file");
134 else
135 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600136 }
137 else
138 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600139 if (png_ptr->sig_bytes >= 8)
140 {
141 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
142 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600143 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600144}
145
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500146void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600147png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600148{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600149#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500150 PNG_CONST PNG_IHDR;
151 PNG_CONST PNG_IDAT;
152 PNG_CONST PNG_IEND;
153 PNG_CONST PNG_PLTE;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600154#if defined(PNG_READ_bKGD_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500155 PNG_CONST PNG_bKGD;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600156#endif
157#if defined(PNG_READ_cHRM_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500158 PNG_CONST PNG_cHRM;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600159#endif
160#if defined(PNG_READ_gAMA_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500161 PNG_CONST PNG_gAMA;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600162#endif
163#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500164 PNG_CONST PNG_hIST;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600165#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600166#if defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500167 PNG_CONST PNG_iCCP;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600168#endif
169#if defined(PNG_READ_iTXt_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500170 PNG_CONST PNG_iTXt;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600171#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600172#if defined(PNG_READ_oFFs_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500173 PNG_CONST PNG_oFFs;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600174#endif
175#if defined(PNG_READ_pCAL_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500176 PNG_CONST PNG_pCAL;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600177#endif
178#if defined(PNG_READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500179 PNG_CONST PNG_pHYs;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600180#endif
181#if defined(PNG_READ_sBIT_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500182 PNG_CONST PNG_sBIT;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600183#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600184#if defined(PNG_READ_sCAL_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500185 PNG_CONST PNG_sCAL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600186#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600187#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500188 PNG_CONST PNG_sRGB;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600189#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600190#if defined(PNG_READ_sPLT_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500191 PNG_CONST PNG_sPLT;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600192#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600193#if defined(PNG_READ_tEXt_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500194 PNG_CONST PNG_tEXt;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600195#endif
196#if defined(PNG_READ_tIME_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500197 PNG_CONST PNG_tIME;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600198#endif
199#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500200 PNG_CONST PNG_tRNS;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600201#endif
202#if defined(PNG_READ_zTXt_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500203 PNG_CONST PNG_zTXt;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600204#endif
205#endif /* PNG_USE_LOCAL_ARRAYS */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600206 /* First we make sure we have enough data for the 4 byte chunk name
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600207 * and the 4 byte chunk length before proceeding with decoding the
208 * chunk data. To fully decode each of these chunks, we also make
209 * sure we have enough data in the buffer for the 4 byte CRC at the
210 * end of every chunk (except IDAT, which is handled separately).
211 */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600212 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600213 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600214 png_byte chunk_length[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600215
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600216 if (png_ptr->buffer_size < 8)
217 {
218 png_push_save_buffer(png_ptr);
219 return;
220 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600221
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600222 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500223 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600224 png_reset_crc(png_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500225 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500226 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600227 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600228 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600229
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500230 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500231 if (png_ptr->mode & PNG_AFTER_IDAT)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500232 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
233
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600234 if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600235 {
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500236 if (png_ptr->push_length != 13)
237 png_error(png_ptr, "Invalid IHDR length");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500238
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500239 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
240 {
241 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600242 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500243 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500244
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600245 png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600246 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500247
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500248 else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
249 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500250 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
251 {
252 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500253 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500254 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500255
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500256 png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
257
258 png_ptr->process_mode = PNG_READ_DONE_MODE;
259 png_push_have_end(png_ptr, info_ptr);
260 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500261
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500262#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
263 else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
264 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500265 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
266 {
267 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500268 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500269 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500270
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500271 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
272 png_ptr->mode |= PNG_HAVE_IDAT;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500273
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500274 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500275
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500276 if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
277 png_ptr->mode |= PNG_HAVE_PLTE;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500278
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500279 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
280 {
281 if (!(png_ptr->mode & PNG_HAVE_IHDR))
282 png_error(png_ptr, "Missing IHDR before IDAT");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500283
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500284 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
285 !(png_ptr->mode & PNG_HAVE_PLTE))
286 png_error(png_ptr, "Missing PLTE before IDAT");
287 }
288 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500289
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500290#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600291 else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600292 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500293 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
294 {
295 png_push_save_buffer(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600296 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500297 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600298 png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600299 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500300
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500301 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600302 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600303 /* If we reach an IDAT chunk, this means we have read all of the
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600304 * header chunks, and we can start reading the image (or if this
305 * is called after the image has been read - we have an error).
306 */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500307
308 if (!(png_ptr->mode & PNG_HAVE_IHDR))
309 png_error(png_ptr, "Missing IHDR before IDAT");
310
311 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
312 !(png_ptr->mode & PNG_HAVE_PLTE))
313 png_error(png_ptr, "Missing PLTE before IDAT");
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600314
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600315 if (png_ptr->mode & PNG_HAVE_IDAT)
316 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500317 if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500318 if (png_ptr->push_length == 0)
319 return;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600320
321 if (png_ptr->mode & PNG_AFTER_IDAT)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500322 png_benign_error(png_ptr, "Too many IDATs found");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600323 }
324
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600325 png_ptr->idat_size = png_ptr->push_length;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600326 png_ptr->mode |= PNG_HAVE_IDAT;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600327 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600328 png_push_have_info(png_ptr, info_ptr);
329 png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
330 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600331 return;
332 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500333
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600334#if defined(PNG_READ_gAMA_SUPPORTED)
335 else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
336 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500337 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
338 {
339 png_push_save_buffer(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600340 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500341 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500342
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600343 png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600344 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500345
Guy Schalnat6d764711995-12-19 03:22:19 -0600346#endif
347#if defined(PNG_READ_sBIT_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600348 else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600349 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500350 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
351 {
352 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600353 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500354 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500355
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600356 png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600357 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500358
Guy Schalnat6d764711995-12-19 03:22:19 -0600359#endif
360#if defined(PNG_READ_cHRM_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600361 else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600362 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500363 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
364 {
365 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600366 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500367 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500368
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600369 png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600370 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500371
Guy Schalnat6d764711995-12-19 03:22:19 -0600372#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600373#if defined(PNG_READ_sRGB_SUPPORTED)
374 else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
375 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500376 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
377 {
378 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600379 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500380 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500381
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600382 png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
383 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500384
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600385#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600386#if defined(PNG_READ_iCCP_SUPPORTED)
387 else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
388 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500389 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
390 {
391 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600392 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500393 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500394
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600395 png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
396 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500397
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600398#endif
399#if defined(PNG_READ_sPLT_SUPPORTED)
400 else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
401 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500402 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
403 {
404 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600405 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500406 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500407
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600408 png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
409 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500410
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600411#endif
Guy Schalnat6d764711995-12-19 03:22:19 -0600412#if defined(PNG_READ_tRNS_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600413 else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600414 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500415 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
416 {
417 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600418 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500419 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500420
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600421 png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600422 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500423
Guy Schalnat6d764711995-12-19 03:22:19 -0600424#endif
425#if defined(PNG_READ_bKGD_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600426 else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600427 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500428 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
429 {
430 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600431 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500432 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500433
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600434 png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600435 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500436
Guy Schalnat6d764711995-12-19 03:22:19 -0600437#endif
438#if defined(PNG_READ_hIST_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600439 else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600440 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500441 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
442 {
443 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600444 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500445 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500446
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600447 png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600448 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500449
Guy Schalnat6d764711995-12-19 03:22:19 -0600450#endif
451#if defined(PNG_READ_pHYs_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600452 else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600453 {
454 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
455 {
456 png_push_save_buffer(png_ptr);
457 return;
458 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500459
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600460 png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600461 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500462
Guy Schalnat6d764711995-12-19 03:22:19 -0600463#endif
464#if defined(PNG_READ_oFFs_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600465 else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600466 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500467 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
468 {
469 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600470 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500471 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500472
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600473 png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600474 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600475#endif
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500476
Andreas Dilger47a0c421997-05-16 02:46:07 -0500477#if defined(PNG_READ_pCAL_SUPPORTED)
478 else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
479 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500480 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
481 {
482 png_push_save_buffer(png_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500483 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500484 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500485
Andreas Dilger47a0c421997-05-16 02:46:07 -0500486 png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
487 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500488
Andreas Dilger47a0c421997-05-16 02:46:07 -0500489#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600490#if defined(PNG_READ_sCAL_SUPPORTED)
491 else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
492 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500493 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
494 {
495 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600496 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500497 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500498
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600499 png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
500 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500501
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600502#endif
Guy Schalnat6d764711995-12-19 03:22:19 -0600503#if defined(PNG_READ_tIME_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600504 else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600505 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500506 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
507 {
508 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600509 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500510 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500511
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600512 png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600513 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500514
Guy Schalnat6d764711995-12-19 03:22:19 -0600515#endif
516#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600517 else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600518 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500519 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
520 {
521 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500522 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500523 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500524
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600525 png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600526 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500527
Guy Schalnat6d764711995-12-19 03:22:19 -0600528#endif
529#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600530 else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600531 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500532 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
533 {
534 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500535 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500536 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500537
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600538 png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600539 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500540
Guy Schalnat6d764711995-12-19 03:22:19 -0600541#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600542#if defined(PNG_READ_iTXt_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600543 else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600544 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500545 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
546 {
547 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500548 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500549 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500550
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600551 png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
552 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500553
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600554#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600555 else
556 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500557 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
558 {
559 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500560 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500561 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600562 png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600563 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600564
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600565 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Guy Schalnat6d764711995-12-19 03:22:19 -0600566}
567
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500568void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500569png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat6d764711995-12-19 03:22:19 -0600570{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600571 png_ptr->process_mode = PNG_SKIP_MODE;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500572 png_ptr->skip_length = skip;
Guy Schalnat6d764711995-12-19 03:22:19 -0600573}
574
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500575void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500576png_push_crc_finish(png_structp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600577{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600578 if (png_ptr->skip_length && png_ptr->save_buffer_size)
579 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500580 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600581
Andreas Dilger47a0c421997-05-16 02:46:07 -0500582 if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
583 save_size = (png_size_t)png_ptr->skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600584 else
585 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600586
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600587 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600588
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600589 png_ptr->skip_length -= save_size;
590 png_ptr->buffer_size -= save_size;
591 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500592 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600593 }
594 if (png_ptr->skip_length && png_ptr->current_buffer_size)
595 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500596 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600597
Andreas Dilger47a0c421997-05-16 02:46:07 -0500598 if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
599 save_size = (png_size_t)png_ptr->skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600600 else
601 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600602
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600603 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600604
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600605 png_ptr->skip_length -= save_size;
606 png_ptr->buffer_size -= save_size;
607 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500608 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600609 }
610 if (!png_ptr->skip_length)
611 {
612 if (png_ptr->buffer_size < 4)
613 {
614 png_push_save_buffer(png_ptr);
615 return;
616 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600617
618 png_crc_finish(png_ptr, 0);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500619 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600620 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600621}
622
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500623void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500624png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600625{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600626 png_bytep ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -0600627
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500628 if (png_ptr == NULL)
629 return;
630
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600631 ptr = buffer;
632 if (png_ptr->save_buffer_size)
633 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500634 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600635
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600636 if (length < png_ptr->save_buffer_size)
637 save_size = length;
638 else
639 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600640
Andreas Dilger47a0c421997-05-16 02:46:07 -0500641 png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600642 length -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500643 ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600644 png_ptr->buffer_size -= save_size;
645 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500646 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600647 }
648 if (length && png_ptr->current_buffer_size)
649 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500650 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600651
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600652 if (length < png_ptr->current_buffer_size)
653 save_size = length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500654
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600655 else
656 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600657
Andreas Dilger47a0c421997-05-16 02:46:07 -0500658 png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600659 png_ptr->buffer_size -= save_size;
660 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500661 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600662 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600663}
664
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500665void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600666png_push_save_buffer(png_structp png_ptr)
667{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600668 if (png_ptr->save_buffer_size)
669 {
670 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
671 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500672 png_size_t i, istop;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600673 png_bytep sp;
674 png_bytep dp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600675
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500676 istop = png_ptr->save_buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600677 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500678 i < istop; i++, sp++, dp++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600679 {
680 *dp = *sp;
681 }
682 }
683 }
684 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
685 png_ptr->save_buffer_max)
686 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500687 png_size_t new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600688 png_bytep old_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600689
Glenn Randers-Pehrsone6474622006-03-04 16:50:47 -0600690 if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500691 (png_ptr->current_buffer_size + 256))
692 {
693 png_error(png_ptr, "Potential overflow of save_buffer");
694 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500695
Andreas Dilger47a0c421997-05-16 02:46:07 -0500696 new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600697 old_buffer = png_ptr->save_buffer;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500698 png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
699 (png_size_t)new_max);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500700 png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
701 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 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500706 png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
707 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 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600716png_push_restore_buffer(png_structp 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 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500726png_push_read_IDAT(png_structp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600727{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600728#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500729 PNG_CONST PNG_IDAT;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600730#endif
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600731 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600732 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600733 png_byte chunk_length[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600734
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600735 if (png_ptr->buffer_size < 8)
736 {
737 png_push_save_buffer(png_ptr);
738 return;
739 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600740
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600741 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500742 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600743 png_reset_crc(png_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500744 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
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-Pehrsonbeb572e2006-08-19 13:59:24 -0500747 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600748 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500749 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500750 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600751 png_error(png_ptr, "Not enough compressed data");
752 return;
753 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600754
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600755 png_ptr->idat_size = png_ptr->push_length;
756 }
757 if (png_ptr->idat_size && png_ptr->save_buffer_size)
758 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500759 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600760
Andreas Dilger47a0c421997-05-16 02:46:07 -0500761 if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600762 {
763 save_size = (png_size_t)png_ptr->idat_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500764
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600765 /* check for overflow */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500766 if ((png_uint_32)save_size != png_ptr->idat_size)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600767 png_error(png_ptr, "save_size overflowed in pngpread");
768 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600769 else
770 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600771
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600772 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500773
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500774 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
775 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500776
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600777 png_ptr->idat_size -= save_size;
778 png_ptr->buffer_size -= save_size;
779 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500780 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600781 }
782 if (png_ptr->idat_size && png_ptr->current_buffer_size)
783 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500784 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600785
Andreas Dilger47a0c421997-05-16 02:46:07 -0500786 if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600787 {
788 save_size = (png_size_t)png_ptr->idat_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500789
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600790 /* check for overflow */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500791 if ((png_uint_32)save_size != png_ptr->idat_size)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600792 png_error(png_ptr, "save_size overflowed in pngpread");
793 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600794 else
795 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600796
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600797 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500798 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
799 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600800
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600801 png_ptr->idat_size -= save_size;
802 png_ptr->buffer_size -= save_size;
803 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500804 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600805 }
806 if (!png_ptr->idat_size)
807 {
808 if (png_ptr->buffer_size < 4)
809 {
810 png_push_save_buffer(png_ptr);
811 return;
812 }
813
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600814 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600815 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500816 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600817 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600818}
819
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500820void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600821png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500822 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600823{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600824 int ret;
Guy Schalnat6d764711995-12-19 03:22:19 -0600825
Guy Schalnate5a37791996-06-05 15:50:50 -0500826 if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500827 png_benign_error(png_ptr, "Extra compression data");
Guy Schalnat6d764711995-12-19 03:22:19 -0600828
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600829 png_ptr->zstream.next_in = buffer;
830 png_ptr->zstream.avail_in = (uInt)buffer_length;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500831 for (;;)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600832 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600833 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -0500834 if (ret != Z_OK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600835 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -0500836 if (ret == Z_STREAM_END)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600837 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -0500838 if (png_ptr->zstream.avail_in)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500839 png_benign_error(png_ptr, "Extra compressed data");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500840
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -0500841 if (!(png_ptr->zstream.avail_out))
842 {
843 png_push_process_row(png_ptr);
844 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500845
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -0500846 png_ptr->mode |= PNG_AFTER_IDAT;
847 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
848 break;
849 }
850 else if (ret == Z_BUF_ERROR)
851 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500852
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -0500853 else
854 png_error(png_ptr, "Decompression Error");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600855 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600856 if (!(png_ptr->zstream.avail_out))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600857 {
Glenn Randers-Pehrsond020e9d2002-06-28 09:34:00 -0500858 if ((
859#if defined(PNG_READ_INTERLACING_SUPPORTED)
860 png_ptr->interlaced && png_ptr->pass > 6) ||
861 (!png_ptr->interlaced &&
862#endif
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -0500863 png_ptr->row_number == png_ptr->num_rows))
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500864 {
Glenn Randers-Pehrson8a7df002002-08-15 22:02:57 -0500865 if (png_ptr->zstream.avail_in)
866 png_warning(png_ptr, "Too much data in IDAT chunks");
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500867 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
868 break;
869 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600870 png_push_process_row(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600871 png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
872 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600873 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500874
Andreas Dilger47a0c421997-05-16 02:46:07 -0500875 else
876 break;
877 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600878}
879
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500880void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600881png_push_process_row(png_structp png_ptr)
882{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600883 png_ptr->row_info.color_type = png_ptr->color_type;
Guy Schalnat6d764711995-12-19 03:22:19 -0600884 png_ptr->row_info.width = png_ptr->iwidth;
885 png_ptr->row_info.channels = png_ptr->channels;
886 png_ptr->row_info.bit_depth = png_ptr->bit_depth;
887 png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600888
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500889 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
890 png_ptr->row_info.width);
Guy Schalnat6d764711995-12-19 03:22:19 -0600891
Guy Schalnate5a37791996-06-05 15:50:50 -0500892 png_read_filter_row(png_ptr, &(png_ptr->row_info),
893 png_ptr->row_buf + 1, png_ptr->prev_row + 1,
894 (int)(png_ptr->row_buf[0]));
Guy Schalnat6d764711995-12-19 03:22:19 -0600895
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500896 png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -0600897
Glenn Randers-Pehrson73b029f2004-11-26 17:28:09 -0600898 if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
Guy Schalnat6d764711995-12-19 03:22:19 -0600899 png_do_read_transformations(png_ptr);
900
901#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600902 /* blow up interlaced rows to full size */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500903 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600904 {
905 if (png_ptr->pass < 6)
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600906/* old interface (pre-1.0.9):
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600907 png_do_read_interlace(&(png_ptr->row_info),
Andreas Dilger47a0c421997-05-16 02:46:07 -0500908 png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600909 */
910 png_do_read_interlace(png_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -0600911
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600912 switch (png_ptr->pass)
913 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600914 case 0:
915 {
916 int i;
917 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
918 {
919 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -0600920 png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600921 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500922
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -0600923 if (png_ptr->pass == 2) /* pass 1 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600924 {
925 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
926 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500927 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600928 png_read_push_finish_row(png_ptr);
929 }
930 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500931
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500932 if (png_ptr->pass == 4 && png_ptr->height <= 4)
933 {
934 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
935 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500936 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500937 png_read_push_finish_row(png_ptr);
938 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500939 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500940
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500941 if (png_ptr->pass == 6 && png_ptr->height <= 4)
942 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500943 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500944 png_read_push_finish_row(png_ptr);
945 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500946
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600947 break;
948 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500949
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600950 case 1:
951 {
952 int i;
953 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
954 {
955 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
956 png_read_push_finish_row(png_ptr);
957 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500958
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -0600959 if (png_ptr->pass == 2) /* skip top 4 generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600960 {
961 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
962 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500963 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600964 png_read_push_finish_row(png_ptr);
965 }
966 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500967
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600968 break;
969 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500970
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600971 case 2:
972 {
973 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500974
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600975 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
976 {
977 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
978 png_read_push_finish_row(png_ptr);
979 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500980
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600981 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
982 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500983 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600984 png_read_push_finish_row(png_ptr);
985 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500986
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -0600987 if (png_ptr->pass == 4) /* pass 3 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600988 {
989 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
990 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500991 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -0600992 png_read_push_finish_row(png_ptr);
993 }
994 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500995
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600996 break;
997 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500998
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600999 case 3:
1000 {
1001 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001002
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001003 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
1004 {
1005 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1006 png_read_push_finish_row(png_ptr);
1007 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001008
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -06001009 if (png_ptr->pass == 4) /* skip top two generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001010 {
1011 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1012 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001013 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001014 png_read_push_finish_row(png_ptr);
1015 }
1016 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001017
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001018 break;
1019 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001020
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001021 case 4:
1022 {
1023 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001024
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001025 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1026 {
1027 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1028 png_read_push_finish_row(png_ptr);
1029 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001030
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001031 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1032 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001033 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001034 png_read_push_finish_row(png_ptr);
1035 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001036
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -06001037 if (png_ptr->pass == 6) /* pass 5 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001038 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001039 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001040 png_read_push_finish_row(png_ptr);
1041 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001042
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001043 break;
1044 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001045
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001046 case 5:
1047 {
1048 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001049
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001050 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
1051 {
1052 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1053 png_read_push_finish_row(png_ptr);
1054 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001055
Glenn Randers-Pehrsonbe9de0f2001-01-22 08:52:16 -06001056 if (png_ptr->pass == 6) /* skip top generated row */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001057 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001058 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001059 png_read_push_finish_row(png_ptr);
1060 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001061
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001062 break;
1063 }
1064 case 6:
1065 {
1066 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1067 png_read_push_finish_row(png_ptr);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001068
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001069 if (png_ptr->pass != 6)
1070 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001071
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001072 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001073 png_read_push_finish_row(png_ptr);
1074 }
1075 }
1076 }
1077 else
Guy Schalnat6d764711995-12-19 03:22:19 -06001078#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001079 {
1080 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1081 png_read_push_finish_row(png_ptr);
1082 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001083}
1084
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001085void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001086png_read_push_finish_row(png_structp png_ptr)
1087{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06001088#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001089 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001090
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001091 /* Start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001092 PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001093
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001094 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001095 PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001096
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001097 /* Start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001098 PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001099
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001100 /* Offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001101 PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001102
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001103 /* Height of interlace block. This is not currently used - if you need
1104 * it, uncomment it here and in png.h
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001105 PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001106 */
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06001107#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001108
Guy Schalnat6d764711995-12-19 03:22:19 -06001109 png_ptr->row_number++;
1110 if (png_ptr->row_number < png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001111 return;
Guy Schalnat6d764711995-12-19 03:22:19 -06001112
Glenn Randers-Pehrsona31c74f2009-05-18 15:52:01 -05001113#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnat6d764711995-12-19 03:22:19 -06001114 if (png_ptr->interlaced)
1115 {
1116 png_ptr->row_number = 0;
Glenn Randers-Pehrsona31c74f2009-05-18 15:52:01 -05001117 png_memset(png_ptr->prev_row, 0,
1118 png_ptr->rowbytes + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -06001119 do
1120 {
1121 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001122 if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1123 (png_ptr->pass == 3 && png_ptr->width < 3) ||
1124 (png_ptr->pass == 5 && png_ptr->width < 2))
1125 png_ptr->pass++;
1126
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05001127 if (png_ptr->pass > 7)
1128 png_ptr->pass--;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001129
Guy Schalnat6d764711995-12-19 03:22:19 -06001130 if (png_ptr->pass >= 7)
1131 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001132
Guy Schalnat6d764711995-12-19 03:22:19 -06001133 png_ptr->iwidth = (png_ptr->width +
1134 png_pass_inc[png_ptr->pass] - 1 -
1135 png_pass_start[png_ptr->pass]) /
1136 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001137
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001138 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05001139 png_ptr->iwidth) + 1;
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001140
Guy Schalnat6d764711995-12-19 03:22:19 -06001141 if (png_ptr->transformations & PNG_INTERLACE)
1142 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001143
1144 png_ptr->num_rows = (png_ptr->height +
1145 png_pass_yinc[png_ptr->pass] - 1 -
1146 png_pass_ystart[png_ptr->pass]) /
1147 png_pass_yinc[png_ptr->pass];
1148
1149 } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
Guy Schalnat6d764711995-12-19 03:22:19 -06001150 }
Glenn Randers-Pehrsona31c74f2009-05-18 15:52:01 -05001151#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat6d764711995-12-19 03:22:19 -06001152}
1153
Guy Schalnat6d764711995-12-19 03:22:19 -06001154#if defined(PNG_READ_tEXt_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001155void /* PRIVATE */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001156png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
1157 length)
Guy Schalnat6d764711995-12-19 03:22:19 -06001158{
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001159 if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001160 {
1161 png_error(png_ptr, "Out of place tEXt");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001162 info_ptr = info_ptr; /* to quiet some compiler warnings */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001163 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001164
Andreas Dilger47a0c421997-05-16 02:46:07 -05001165#ifdef PNG_MAX_MALLOC_64K
1166 png_ptr->skip_length = 0; /* This may not be necessary */
1167
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001168 if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001169 {
1170 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001171 png_ptr->skip_length = length - (png_uint_32)65535L;
1172 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001173 }
1174#endif
1175
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001176 png_ptr->current_text = (png_charp)png_malloc(png_ptr,
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001177 (png_size_t)(length + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001178 png_ptr->current_text[length] = '\0';
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001179 png_ptr->current_text_ptr = png_ptr->current_text;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001180 png_ptr->current_text_size = (png_size_t)length;
1181 png_ptr->current_text_left = (png_size_t)length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001182 png_ptr->process_mode = PNG_READ_tEXt_MODE;
Guy Schalnat6d764711995-12-19 03:22:19 -06001183}
1184
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001185void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001186png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001187{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001188 if (png_ptr->buffer_size && png_ptr->current_text_left)
1189 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001190 png_size_t text_size;
Guy Schalnat6d764711995-12-19 03:22:19 -06001191
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001192 if (png_ptr->buffer_size < png_ptr->current_text_left)
1193 text_size = png_ptr->buffer_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001194
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001195 else
1196 text_size = png_ptr->current_text_left;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001197
Andreas Dilger47a0c421997-05-16 02:46:07 -05001198 png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001199 png_ptr->current_text_left -= text_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001200 png_ptr->current_text_ptr += text_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001201 }
1202 if (!(png_ptr->current_text_left))
1203 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001204 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001205 png_charp text;
1206 png_charp key;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001207 int ret;
Guy Schalnat6d764711995-12-19 03:22:19 -06001208
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001209 if (png_ptr->buffer_size < 4)
1210 {
1211 png_push_save_buffer(png_ptr);
1212 return;
1213 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001214
Andreas Dilger47a0c421997-05-16 02:46:07 -05001215 png_push_crc_finish(png_ptr);
1216
1217#if defined(PNG_MAX_MALLOC_64K)
1218 if (png_ptr->skip_length)
1219 return;
1220#endif
Guy Schalnat6d764711995-12-19 03:22:19 -06001221
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001222 key = png_ptr->current_text;
Guy Schalnat6d764711995-12-19 03:22:19 -06001223
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001224 for (text = key; *text; text++)
1225 /* empty loop */ ;
Guy Schalnat6d764711995-12-19 03:22:19 -06001226
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001227 if (text < key + png_ptr->current_text_size)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001228 text++;
1229
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001230 text_ptr = (png_textp)png_malloc(png_ptr,
1231 png_sizeof(png_text));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001232 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1233 text_ptr->key = key;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001234#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -05001235 text_ptr->lang = NULL;
1236 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001237#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001238 text_ptr->text = text;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001239
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001240 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001241
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -05001242 png_free(png_ptr, key);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001243 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001244 png_ptr->current_text = NULL;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001245
1246 if (ret)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001247 png_warning(png_ptr, "Insufficient memory to store text chunk");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001248 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001249}
1250#endif
1251
1252#if defined(PNG_READ_zTXt_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001253void /* PRIVATE */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001254png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
1255 length)
Guy Schalnat6d764711995-12-19 03:22:19 -06001256{
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001257 if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001258 {
1259 png_error(png_ptr, "Out of place zTXt");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001260 info_ptr = info_ptr; /* to quiet some compiler warnings */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001261 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001262
Andreas Dilger47a0c421997-05-16 02:46:07 -05001263#ifdef PNG_MAX_MALLOC_64K
1264 /* We can't handle zTXt chunks > 64K, since we don't have enough space
1265 * to be able to store the uncompressed data. Actually, the threshold
1266 * is probably around 32K, but it isn't as definite as 64K is.
1267 */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001268 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001269 {
1270 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
1271 png_push_crc_skip(png_ptr, length);
1272 return;
1273 }
1274#endif
1275
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001276 png_ptr->current_text = (png_charp)png_malloc(png_ptr,
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001277 (png_size_t)(length + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001278 png_ptr->current_text[length] = '\0';
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001279 png_ptr->current_text_ptr = png_ptr->current_text;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001280 png_ptr->current_text_size = (png_size_t)length;
1281 png_ptr->current_text_left = (png_size_t)length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001282 png_ptr->process_mode = PNG_READ_zTXt_MODE;
Guy Schalnat6d764711995-12-19 03:22:19 -06001283}
1284
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001285void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001286png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001287{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001288 if (png_ptr->buffer_size && png_ptr->current_text_left)
1289 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001290 png_size_t text_size;
Guy Schalnat6d764711995-12-19 03:22:19 -06001291
Andreas Dilger47a0c421997-05-16 02:46:07 -05001292 if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001293 text_size = png_ptr->buffer_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001294
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001295 else
1296 text_size = png_ptr->current_text_left;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001297
Andreas Dilger47a0c421997-05-16 02:46:07 -05001298 png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001299 png_ptr->current_text_left -= text_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001300 png_ptr->current_text_ptr += text_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001301 }
1302 if (!(png_ptr->current_text_left))
1303 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001304 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001305 png_charp text;
1306 png_charp key;
1307 int ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001308 png_size_t text_size, key_size;
Guy Schalnat6d764711995-12-19 03:22:19 -06001309
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001310 if (png_ptr->buffer_size < 4)
1311 {
1312 png_push_save_buffer(png_ptr);
1313 return;
1314 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001315
Andreas Dilger47a0c421997-05-16 02:46:07 -05001316 png_push_crc_finish(png_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001317
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001318 key = png_ptr->current_text;
Guy Schalnat6d764711995-12-19 03:22:19 -06001319
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001320 for (text = key; *text; text++)
1321 /* empty loop */ ;
Guy Schalnat6d764711995-12-19 03:22:19 -06001322
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001323 /* zTXt can't have zero text */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001324 if (text >= key + png_ptr->current_text_size)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001325 {
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001326 png_ptr->current_text = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001327 png_free(png_ptr, key);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001328 return;
1329 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001330
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001331 text++;
Guy Schalnat6d764711995-12-19 03:22:19 -06001332
Andreas Dilger47a0c421997-05-16 02:46:07 -05001333 if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001334 {
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001335 png_ptr->current_text = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001336 png_free(png_ptr, key);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001337 return;
1338 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001339
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001340 text++;
Guy Schalnat6d764711995-12-19 03:22:19 -06001341
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001342 png_ptr->zstream.next_in = (png_bytep )text;
1343 png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001344 (text - key));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001345 png_ptr->zstream.next_out = png_ptr->zbuf;
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001346 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnat6d764711995-12-19 03:22:19 -06001347
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001348 key_size = text - key;
1349 text_size = 0;
1350 text = NULL;
1351 ret = Z_STREAM_END;
Guy Schalnat6d764711995-12-19 03:22:19 -06001352
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001353 while (png_ptr->zstream.avail_in)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001354 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001355 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001356 if (ret != Z_OK && ret != Z_STREAM_END)
1357 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001358 inflateReset(&png_ptr->zstream);
1359 png_ptr->zstream.avail_in = 0;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001360 png_ptr->current_text = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001361 png_free(png_ptr, key);
1362 png_free(png_ptr, text);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001363 return;
1364 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001365 if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001366 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001367 if (text == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001368 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001369 text = (png_charp)png_malloc(png_ptr,
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001370 (png_ptr->zbuf_size
1371 - png_ptr->zstream.avail_out + key_size + 1));
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001372
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001373 png_memcpy(text + key_size, png_ptr->zbuf,
1374 png_ptr->zbuf_size - png_ptr->zstream.avail_out);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001375
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001376 png_memcpy(text, key, key_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001377
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001378 text_size = key_size + png_ptr->zbuf_size -
1379 png_ptr->zstream.avail_out;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001380
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001381 *(text + text_size) = '\0';
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001382 }
1383 else
1384 {
1385 png_charp tmp;
Guy Schalnat6d764711995-12-19 03:22:19 -06001386
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001387 tmp = text;
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001388 text = (png_charp)png_malloc(png_ptr, text_size +
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001389 (png_ptr->zbuf_size
Glenn Randers-Pehrsona5fa5c92008-09-06 07:06:22 -05001390 - png_ptr->zstream.avail_out + 1));
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001391
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001392 png_memcpy(text, tmp, text_size);
1393 png_free(png_ptr, tmp);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001394
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001395 png_memcpy(text + text_size, png_ptr->zbuf,
1396 png_ptr->zbuf_size - png_ptr->zstream.avail_out);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001397
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001398 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
1399 *(text + text_size) = '\0';
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001400 }
1401 if (ret != Z_STREAM_END)
1402 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001403 png_ptr->zstream.next_out = png_ptr->zbuf;
1404 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001405 }
1406 }
1407 else
1408 {
1409 break;
1410 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001411
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001412 if (ret == Z_STREAM_END)
1413 break;
1414 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001415
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001416 inflateReset(&png_ptr->zstream);
1417 png_ptr->zstream.avail_in = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -06001418
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001419 if (ret != Z_STREAM_END)
1420 {
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001421 png_ptr->current_text = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001422 png_free(png_ptr, key);
1423 png_free(png_ptr, text);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001424 return;
1425 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001426
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001427 png_ptr->current_text = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001428 png_free(png_ptr, key);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001429 key = text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001430 text += key_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001431
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001432 text_ptr = (png_textp)png_malloc(png_ptr,
1433 png_sizeof(png_text));
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001434 text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
1435 text_ptr->key = key;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001436#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -05001437 text_ptr->lang = NULL;
1438 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001439#endif
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001440 text_ptr->text = text;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001441
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001442 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001443
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -05001444 png_free(png_ptr, key);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001445 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001446
1447 if (ret)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001448 png_warning(png_ptr, "Insufficient memory to store text chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001449 }
1450}
1451#endif
1452
1453#if defined(PNG_READ_iTXt_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001454void /* PRIVATE */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001455png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
1456 length)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001457{
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001458 if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001459 {
1460 png_error(png_ptr, "Out of place iTXt");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001461 info_ptr = info_ptr; /* to quiet some compiler warnings */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001462 }
1463
1464#ifdef PNG_MAX_MALLOC_64K
1465 png_ptr->skip_length = 0; /* This may not be necessary */
1466
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001467 if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001468 {
1469 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
1470 png_ptr->skip_length = length - (png_uint_32)65535L;
1471 length = (png_uint_32)65535L;
1472 }
1473#endif
1474
1475 png_ptr->current_text = (png_charp)png_malloc(png_ptr,
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001476 (png_size_t)(length + 1));
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001477 png_ptr->current_text[length] = '\0';
1478 png_ptr->current_text_ptr = png_ptr->current_text;
1479 png_ptr->current_text_size = (png_size_t)length;
1480 png_ptr->current_text_left = (png_size_t)length;
1481 png_ptr->process_mode = PNG_READ_iTXt_MODE;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001482}
1483
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001484void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001485png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
1486{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001487
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001488 if (png_ptr->buffer_size && png_ptr->current_text_left)
1489 {
1490 png_size_t text_size;
1491
1492 if (png_ptr->buffer_size < png_ptr->current_text_left)
1493 text_size = png_ptr->buffer_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001494
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001495 else
1496 text_size = png_ptr->current_text_left;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001497
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001498 png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
1499 png_ptr->current_text_left -= text_size;
1500 png_ptr->current_text_ptr += text_size;
1501 }
1502 if (!(png_ptr->current_text_left))
1503 {
1504 png_textp text_ptr;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001505 png_charp key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001506 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001507 png_charp lang;
1508 png_charp lang_key;
1509 png_charp text;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001510 int ret;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001511
1512 if (png_ptr->buffer_size < 4)
1513 {
1514 png_push_save_buffer(png_ptr);
1515 return;
1516 }
1517
1518 png_push_crc_finish(png_ptr);
1519
1520#if defined(PNG_MAX_MALLOC_64K)
1521 if (png_ptr->skip_length)
1522 return;
1523#endif
1524
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001525 key = png_ptr->current_text;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001526
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001527 for (lang = key; *lang; lang++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001528 /* empty loop */ ;
1529
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001530 if (lang < key + png_ptr->current_text_size - 3)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001531 lang++;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001532
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001533 comp_flag = *lang++;
1534 lang++; /* skip comp_type, always zero */
1535
1536 for (lang_key = lang; *lang_key; lang_key++)
1537 /* empty loop */ ;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001538
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001539 lang_key++; /* skip NUL separator */
1540
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001541 text=lang_key;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001542
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001543 if (lang_key < key + png_ptr->current_text_size - 1)
1544 {
1545 for (; *text; text++)
1546 /* empty loop */ ;
1547 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001548
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001549 if (text < key + png_ptr->current_text_size)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001550 text++;
1551
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001552 text_ptr = (png_textp)png_malloc(png_ptr,
1553 png_sizeof(png_text));
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001554
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001555 text_ptr->compression = comp_flag + 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001556 text_ptr->key = key;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001557 text_ptr->lang = lang;
1558 text_ptr->lang_key = lang_key;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001559 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001560 text_ptr->text_length = 0;
1561 text_ptr->itxt_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001562
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001563 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001564
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001565 png_ptr->current_text = NULL;
1566
Andreas Dilger47a0c421997-05-16 02:46:07 -05001567 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001568 if (ret)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001569 png_warning(png_ptr, "Insufficient memory to store iTXt chunk");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001570 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001571}
1572#endif
1573
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001574/* This function is called when we haven't found a handler for this
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001575 * chunk. If there isn't a problem with the chunk itself (ie a bad chunk
1576 * name or a critical chunk), the chunk is (currently) silently ignored.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001577 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001578void /* PRIVATE */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001579png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
1580 length)
Guy Schalnat6d764711995-12-19 03:22:19 -06001581{
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05001582 png_uint_32 skip = 0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001583
1584 if (!(png_ptr->chunk_name[0] & 0x20))
1585 {
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001586#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001587 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
1588 PNG_HANDLE_CHUNK_ALWAYS
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001589#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001590 && png_ptr->read_user_chunk_fn == NULL
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001591#endif
1592 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001593#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001594 png_chunk_error(png_ptr, "unknown critical chunk");
1595
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001596 info_ptr = info_ptr; /* to quiet some compiler warnings */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001597 }
1598
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001599#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
1600 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
1601 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001602#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001603 if (length > (png_uint_32)65535L)
1604 {
1605 png_warning(png_ptr, "unknown chunk too large to fit in memory");
1606 skip = length - (png_uint_32)65535L;
1607 length = (png_uint_32)65535L;
1608 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001609#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001610 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
1611 (png_charp)png_ptr->chunk_name,
1612 png_sizeof(png_ptr->unknown_chunk.name));
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05001613 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1]
1614 = '\0';
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001615
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001616 png_ptr->unknown_chunk.size = (png_size_t)length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001617
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001618 if (length == 0)
1619 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001620
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001621 else
1622 {
1623 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
1624 (png_size_t)length);
1625 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
1626 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001627
Glenn Randers-Pehrsone1eff582001-04-14 20:15:41 -05001628#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001629 if (png_ptr->read_user_chunk_fn != NULL)
1630 {
1631 /* callback to user unknown chunk handler */
1632 int ret;
1633 ret = (*(png_ptr->read_user_chunk_fn))
1634 (png_ptr, &png_ptr->unknown_chunk);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001635
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001636 if (ret < 0)
1637 png_chunk_error(png_ptr, "error in user chunk");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001638
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001639 if (ret == 0)
1640 {
1641 if (!(png_ptr->chunk_name[0] & 0x20))
1642 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
1643 PNG_HANDLE_CHUNK_ALWAYS)
1644 png_chunk_error(png_ptr, "unknown critical chunk");
1645 png_set_unknown_chunks(png_ptr, info_ptr,
1646 &png_ptr->unknown_chunk, 1);
1647 }
1648 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001649
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001650 else
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001651#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001652 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
1653 png_free(png_ptr, png_ptr->unknown_chunk.data);
1654 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001655 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001656
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001657 else
1658#endif
1659 skip=length;
1660 png_push_crc_skip(png_ptr, skip);
Guy Schalnat6d764711995-12-19 03:22:19 -06001661}
1662
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001663void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001664png_push_have_info(png_structp png_ptr, png_infop info_ptr)
1665{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001666 if (png_ptr->info_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001667 (*(png_ptr->info_fn))(png_ptr, info_ptr);
1668}
1669
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001670void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001671png_push_have_end(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001672{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001673 if (png_ptr->end_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001674 (*(png_ptr->end_fn))(png_ptr, info_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001675}
1676
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001677void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001678png_push_have_row(png_structp png_ptr, png_bytep row)
1679{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001680 if (png_ptr->row_fn != NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001681 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1682 (int)png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -06001683}
1684
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001685void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001686png_progressive_combine_row (png_structp png_ptr,
1687 png_bytep old_row, png_bytep new_row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001688{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06001689#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001690 PNG_CONST int FARDATA png_pass_dsp_mask[7] =
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001691 {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06001692#endif
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001693 if (png_ptr == NULL)
1694 return;
1695
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05001696 if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001697 png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
Guy Schalnat6d764711995-12-19 03:22:19 -06001698}
1699
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001700void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -06001701png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001702 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1703 png_progressive_end_ptr end_fn)
Guy Schalnat6d764711995-12-19 03:22:19 -06001704{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001705 if (png_ptr == NULL)
1706 return;
1707
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001708 png_ptr->info_fn = info_fn;
1709 png_ptr->row_fn = row_fn;
Guy Schalnat6d764711995-12-19 03:22:19 -06001710 png_ptr->end_fn = end_fn;
Guy Schalnate5a37791996-06-05 15:50:50 -05001711
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -05001712 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001713}
1714
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001715png_voidp PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001716png_get_progressive_ptr(png_structp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001717{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001718 if (png_ptr == NULL)
1719 return (NULL);
1720
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001721 return png_ptr->io_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001722}
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001723#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */