1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* pngpread.c - read a png file in push mode
3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *
4b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Last changed in libpng 1.6.10 [March 6, 2014]
5b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Copyright (c) 1998-2014 Glenn Randers-Pehrson
6893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott *
9a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * This code is released under the libpng license.
10a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * For conditions of distribution and use, see the disclaimer
11a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * and license in png.h
12893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
14b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include "pngpriv.h"
15b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
17893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
18a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Push model modes */
19893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_SIG_MODE   0
20893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_CHUNK_MODE 1
21893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_IDAT_MODE  2
22893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_SKIP_MODE       3
23893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_tEXt_MODE  4
24893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_zTXt_MODE  5
25893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_DONE_MODE  6
26893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_READ_iTXt_MODE  7
27893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#define PNG_ERROR_MODE      8
28893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
29893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
30b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_process_data(png_structrp png_ptr, png_inforp info_ptr,
31b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_bytep buffer, png_size_t buffer_size)
32893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
33a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL || info_ptr == NULL)
34a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
35a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
36893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_push_restore_buffer(png_ptr, buffer, buffer_size);
37893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
38893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   while (png_ptr->buffer_size)
39893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
40893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_process_some_data(png_ptr, info_ptr);
41893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
42893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
43893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
44b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_size_t PNGAPI
45b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_process_data_pause(png_structrp png_ptr, int save)
46b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
47b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr != NULL)
48b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
49b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* It's easiest for the caller if we do the save, then the caller doesn't
50b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * have to supply the same data again:
51b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
52b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (save)
53b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_push_save_buffer(png_ptr);
54b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
55b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      {
56b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* This includes any pending saved bytes: */
57b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_size_t remaining = png_ptr->buffer_size;
58b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->buffer_size = 0;
59b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
60b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* So subtract the saved buffer size, unless all the data
61b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * is actually 'saved', in which case we just return 0
62b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
63b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->save_buffer_size < remaining)
64b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return remaining - png_ptr->save_buffer_size;
65b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      }
66b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
67b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
68b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return 0;
69b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
70b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
71b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_uint_32 PNGAPI
72b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_process_data_skip(png_structrp png_ptr)
73b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{
74b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 remaining = 0;
75b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
76b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE &&
77b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->skip_length > 0)
78b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
79b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* At the end of png_process_data the buffer size must be 0 (see the loop
80b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * above) so we can detect a broken call here:
81b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
82b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->buffer_size != 0)
83b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr,
84b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            "png_process_data_skip called inside png_process_data");
85b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
86b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* If is impossible for there to be a saved buffer at this point -
87b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * otherwise we could not be in SKIP mode.  This will also happen if
88b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * png_process_skip is called inside png_process_data (but only very
89b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * rarely.)
90b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
91b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->save_buffer_size != 0)
92b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "png_process_data_skip called with saved data");
93b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
94b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      remaining = png_ptr->skip_length;
95b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->skip_length = 0;
96b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
97b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
98b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
99b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   return remaining;
100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}
101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* What we do with the incoming data depends on what we were previously
103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * doing before we ran out of data...
104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
106b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
108a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL)
109a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
110a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   switch (png_ptr->process_mode)
112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      case PNG_READ_SIG_MODE:
114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_read_sig(png_ptr, info_ptr);
116893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
118a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
119893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      case PNG_READ_CHUNK_MODE:
120893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_read_chunk(png_ptr, info_ptr);
122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
124a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      case PNG_READ_IDAT_MODE:
126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_read_IDAT(png_ptr);
128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
130a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      case PNG_SKIP_MODE:
132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_crc_finish(png_ptr);
134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
136a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      default:
138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->buffer_size = 0;
140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         break;
141893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Read any remaining signature bytes from the stream and compare them with
146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * the correct PNG signature.  It is possible that this routine is called
147893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * with bytes already read from the signature, either because they have been
148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * checked by the calling application, or because of multiple calls to this
149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * routine.
150893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
152b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project             num_to_check = 8 - num_checked;
156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->buffer_size < num_to_check)
158893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      num_to_check = png_ptr->buffer_size;
160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       num_to_check);
1644215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (num_checked < 4 &&
169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
170893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_error(png_ptr, "Not a PNG file");
171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
176893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->sig_bytes >= 8)
178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
185b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_uint_32 chunk_name;
188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   int keep; /* unknown handling method */
190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   /* First we make sure we have enough data for the 4 byte chunk name
193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    * and the 4 byte chunk length before proceeding with decoding the
194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    * chunk data.  To fully decode each of these chunks, we also make
195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    * sure we have enough data in the buffer for the 4 byte CRC at the
196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    * end of every chunk (except IDAT, which is handled separately).
197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    */
198893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_byte chunk_length[4];
201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_byte chunk_tag[4];
202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->buffer_size < 8)
204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
208893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_push_fill_buffer(png_ptr, chunk_length, 4);
2104215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_reset_crc(png_ptr);
212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_crc_read(png_ptr, chunk_tag, 4);
213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
2144215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   chunk_name = png_ptr->chunk_name;
219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (chunk_name == png_IDAT)
221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->mode & PNG_AFTER_IDAT)
223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* If we reach an IDAT chunk, this means we have read all of the
226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * header chunks, and we can start reading the image (or if this
227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * is called after the image has been read - we have an error).
228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (!(png_ptr->mode & PNG_HAVE_IHDR))
230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "Missing IHDR before IDAT");
231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          !(png_ptr->mode & PNG_HAVE_PLTE))
234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "Missing PLTE before IDAT");
235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->mode |= PNG_HAVE_IDAT;
237b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari      png_ptr->process_mode = PNG_READ_IDAT_MODE;
238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->push_length == 0)
241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            return;
242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->mode & PNG_AFTER_IDAT)
244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_benign_error(png_ptr, "Too many IDATs found");
245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (chunk_name == png_IHDR)
248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
2494215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      if (png_ptr->push_length != 13)
2504215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_error(png_ptr, "Invalid IHDR length");
251a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
255893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
257a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
260a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_IEND)
262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
268a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->process_mode = PNG_READ_DONE_MODE;
272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_push_have_end(png_ptr, info_ptr);
273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
274a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
283a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
285a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (chunk_name == png_PLTE)
287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->mode |= PNG_HAVE_PLTE;
288893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
290b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_PLTE)
292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
300a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_IDAT)
302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->idat_size = png_ptr->push_length;
304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->process_mode = PNG_READ_IDAT_MODE;
305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_push_have_info(png_ptr, info_ptr);
3065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      png_ptr->zstream.avail_out =
3075f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott          (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
3085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott          png_ptr->iwidth) + 1;
309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->zstream.next_out = png_ptr->row_buf;
310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      return;
311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
312a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
3135f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_gAMA_SUPPORTED
314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (png_ptr->chunk_name == png_gAMA)
315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
321a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
324a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3265f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sBIT_SUPPORTED
327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (png_ptr->chunk_name == png_sBIT)
328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
330893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
334a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
337a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_cHRM_SUPPORTED
340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (png_ptr->chunk_name == png_cHRM)
341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
347a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
350a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sRGB_SUPPORTED
353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_sRGB)
354893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
360a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
363a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3655f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_iCCP_SUPPORTED
366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (png_ptr->chunk_name == png_iCCP)
367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
373a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
376a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3785f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sPLT_SUPPORTED
379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_sPLT)
380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
381893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
386a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
389a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
3915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tRNS_SUPPORTED
392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_tRNS)
393893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
396893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
399a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
402a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4045f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_bKGD_SUPPORTED
405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_bKGD)
406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
412a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
413893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
414893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
415a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_hIST_SUPPORTED
418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_hIST)
419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
425a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
428a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_pHYs_SUPPORTED
431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_pHYs)
432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
438a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
441a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4435f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_oFFs_SUPPORTED
444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_oFFs)
445893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
447893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
451a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
453893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
455a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
4565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_pCAL_SUPPORTED
457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_pCAL)
458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
460893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
463893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
464a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
467a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4695f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sCAL_SUPPORTED
470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_sCAL)
471893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
477a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
480a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tIME_SUPPORTED
483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_tIME)
484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
487893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
490a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
492893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
493a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
4955f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tEXt_SUPPORTED
496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_tEXt)
497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
503a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
506a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
507893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
5085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_zTXt_SUPPORTED
509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_zTXt)
510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
512893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
513893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
516a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
518893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
519a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
5215f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_iTXt_SUPPORTED
522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (chunk_name == png_iTXt)
523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
524893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
525893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
529a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
533b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari
534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
536893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         PNG_HANDLE_CHUNK_AS_DEFAULT);
543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
549b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_crc_skip(png_structrp png_ptr, png_uint_32 skip)
550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->process_mode = PNG_SKIP_MODE;
552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->skip_length = skip;
553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
556b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_crc_finish(png_structrp png_ptr)
557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->skip_length && png_ptr->save_buffer_size)
559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_size_t save_size = png_ptr->save_buffer_size;
561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_uint_32 skip_length = png_ptr->skip_length;
562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* We want the smaller of 'skip_length' and 'save_buffer_size', but
564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * they are of different types and we don't know which variable has the
565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * fewest bits.  Carefully select the smaller and cast it to the type of
566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the larger - this cannot overflow.  Do not cast in the following test
567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * - it will break on either 16 or 64 bit platforms.
568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (skip_length < save_size)
570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         save_size = (png_size_t)skip_length;
571893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         skip_length = (png_uint_32)save_size;
574893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
575893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->skip_length -= skip_length;
578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->buffer_size -= save_size;
579893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_size -= save_size;
580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_ptr += save_size;
581893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->skip_length && png_ptr->current_buffer_size)
583893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_size_t save_size = png_ptr->current_buffer_size;
585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_uint_32 skip_length = png_ptr->skip_length;
586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * the same problem exists as above and the same solution.
589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (skip_length < save_size)
591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         save_size = (png_size_t)skip_length;
592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         skip_length = (png_uint_32)save_size;
595893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->skip_length -= skip_length;
599893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->buffer_size -= save_size;
600893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_size -= save_size;
601893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_ptr += save_size;
602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (!png_ptr->skip_length)
604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->buffer_size < 4)
606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_crc_finish(png_ptr, 0);
612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
616b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGCBAPI
617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_bytep ptr;
620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
621a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL)
622a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
623a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   ptr = buffer;
625893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->save_buffer_size)
626893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_size_t save_size;
628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
629893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (length < png_ptr->save_buffer_size)
630893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         save_size = length;
631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
632893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         save_size = png_ptr->save_buffer_size;
634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      length -= save_size;
637893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      ptr += save_size;
638893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->buffer_size -= save_size;
639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_size -= save_size;
640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_ptr += save_size;
641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
642893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (length && png_ptr->current_buffer_size)
643893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_size_t save_size;
645893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (length < png_ptr->current_buffer_size)
647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         save_size = length;
648a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         save_size = png_ptr->current_buffer_size;
651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
653893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->buffer_size -= save_size;
654893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_size -= save_size;
655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_ptr += save_size;
656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
657893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
660b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_save_buffer(png_structrp png_ptr)
661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->save_buffer_size)
663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
664893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
665893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
6664215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_size_t i, istop;
667893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_bytep sp;
668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_bytep dp;
669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         istop = png_ptr->save_buffer_size;
671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             i < istop; i++, sp++, dp++)
673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            *dp = *sp;
675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       png_ptr->save_buffer_max)
680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_size_t new_max;
682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_bytep old_buffer;
683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (png_ptr->current_buffer_size + 256))
686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "Potential overflow of save_buffer");
688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
689a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
690893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      old_buffer = png_ptr->save_buffer;
6925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          (png_size_t)new_max);
694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
6955f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      if (png_ptr->save_buffer == NULL)
6965f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      {
697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_free(png_ptr, old_buffer);
698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "Insufficient memory for save_buffer");
6995f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      }
700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_free(png_ptr, old_buffer);
703893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_max = new_max;
704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->current_buffer_size)
706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_size = 0;
711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->buffer_size = 0;
714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
717b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_size_t buffer_length)
719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->current_buffer = buffer;
721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->current_buffer_size = buffer_length;
722893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
727b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_read_IDAT(png_structrp png_ptr)
728893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_byte chunk_length[4];
732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_byte chunk_tag[4];
733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* TODO: this code can be commoned up with the same code in push_read */
735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->buffer_size < 8)
736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
740893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_push_fill_buffer(png_ptr, chunk_length, 4);
7424215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_reset_crc(png_ptr);
744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_crc_read(png_ptr, chunk_tag, 4);
745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
746893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->chunk_name != png_IDAT)
749893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
750893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_error(png_ptr, "Not enough compressed data");
754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->idat_size = png_ptr->push_length;
759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->idat_size && png_ptr->save_buffer_size)
762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_size_t save_size = png_ptr->save_buffer_size;
764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_uint_32 idat_size = png_ptr->idat_size;
765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * are of different types and we don't know which variable has the fewest
768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * bits.  Carefully select the smaller and cast it to the type of the
769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * larger - this cannot overflow.  Do not cast in the following test - it
770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * will break on either 16 or 64 bit platforms.
771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (idat_size < save_size)
773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         save_size = (png_size_t)idat_size;
774a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         idat_size = (png_uint_32)save_size;
777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
779a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
7805f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
781a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->idat_size -= idat_size;
783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->buffer_size -= save_size;
784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_size -= save_size;
785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->save_buffer_ptr += save_size;
786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->idat_size && png_ptr->current_buffer_size)
789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_size_t save_size = png_ptr->current_buffer_size;
791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_uint_32 idat_size = png_ptr->idat_size;
792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * are of different types and we don't know which variable has the fewest
795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * bits.  Carefully select the smaller and cast it to the type of the
796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * larger - this cannot overflow.
797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       */
798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (idat_size < save_size)
799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         save_size = (png_size_t)idat_size;
800a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      else
802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         idat_size = (png_uint_32)save_size;
803893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
8055f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->idat_size -= idat_size;
809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->buffer_size -= save_size;
810893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_size -= save_size;
811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->current_buffer_ptr += save_size;
812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (!png_ptr->idat_size)
814893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
815893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->buffer_size < 4)
816893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
817893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         png_push_save_buffer(png_ptr);
818893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         return;
819893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
820893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_crc_finish(png_ptr, 0);
822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->mode |= PNG_AFTER_IDAT;
824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->zowner = 0;
825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
826893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
827893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
829b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_size_t buffer_length)
831893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
8325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   /* The caller checks for a non-zero buffer length. */
8335f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   if (!(buffer_length > 0) || buffer == NULL)
8345f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      png_error(png_ptr, "No IDAT data (internal error)");
835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
8365f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   /* This routine must process all the data it has been given
8375f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    * before returning, calling the row callback as required to
8385f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    * handle the uncompressed results.
8395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    */
840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->zstream.next_in = buffer;
841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
842893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->zstream.avail_in = (uInt)buffer_length;
8435f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8445f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   /* Keep going until the decompressed data is all processed
8455f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    * or the stream marked as finished.
8465f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    */
8475f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   while (png_ptr->zstream.avail_in > 0 &&
848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
849893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
8505f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      int ret;
851a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
8525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      /* We have data for zlib, but we must check that zlib
853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * has someplace to put the results.  It doesn't matter
8545f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott       * if we don't expect any results -- it may be the input
8555f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott       * data is just the LZ end code.
8565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott       */
8575f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      if (!(png_ptr->zstream.avail_out > 0))
8585f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      {
859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->iwidth) + 1);
862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
8635f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         png_ptr->zstream.next_out = png_ptr->row_buf;
8645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      }
865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
8665f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      /* Using Z_SYNC_FLUSH here means that an unterminated
867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * LZ stream (a stream with a missing end code) can still
868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * be handled, otherwise (Z_NO_FLUSH) a future zlib
869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * implementation might defer output and therefore
870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * change the current behavior (see comments in inflate.c
871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik       * for why this doesn't happen at present with zlib 1.2.5).
8725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott       */
8735f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
874a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
8755f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      /* Check for any failure before proceeding. */
8765f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      if (ret != Z_OK && ret != Z_STREAM_END)
8775f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      {
878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Terminate the decompression. */
879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->zowner = 0;
8815f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         /* This may be a truncated stream (missing or
883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * damaged end code).  Treat that as a warning.
884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
8855f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         if (png_ptr->row_number >= png_ptr->num_rows ||
886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->pass > 6)
887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_warning(png_ptr, "Truncated compressed data in IDAT");
8885f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         else
890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_error(png_ptr, "Decompression error in IDAT");
891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Skip the check on unprocessed input */
8935f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         return;
894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
8955f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
8965f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      /* Did inflate output any data? */
8975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      if (png_ptr->zstream.next_out != png_ptr->row_buf)
898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Is this unexpected data after the last row?
900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * If it is, artificially terminate the LZ output
901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          * here.
902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik          */
9035f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott         if (png_ptr->row_number >= png_ptr->num_rows ||
904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_ptr->pass > 6)
905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* Extra data. */
907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_warning(png_ptr, "Extra compressed data in IDAT");
908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->zowner = 0;
910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            /* Do no more processing; skip the unprocessed
912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             * input check below.
913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             */
9145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott            return;
915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         }
9165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         /* Do we have a complete row? */
918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         if (png_ptr->zstream.avail_out == 0)
919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_push_process_row(png_ptr);
920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
921a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
9225f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      /* And check for the end of the stream. */
9235f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott      if (ret == Z_STREAM_END)
924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
9265f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott
9275f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   /* All the data should have been processed, if anything
9285f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    * is left at this point we have bytes of IDAT data
9295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    * after the zlib end code.
9305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    */
9315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott   if (png_ptr->zstream.avail_in > 0)
932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_warning(png_ptr, "Extra compression data in IDAT");
933893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
934893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
935893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
936b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_process_row(png_structrp png_ptr)
937893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* 1.5.6: row_info moved out of png_struct to a local here. */
939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   png_row_info row_info;
940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_info.color_type = png_ptr->color_type;
943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_info.bit_depth = png_ptr->bit_depth;
944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_info.channels = png_ptr->channels;
945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_info.pixel_depth = png_ptr->pixel_depth;
946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      else
954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "bad adaptive filter value");
955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
956893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * 1.5.6, while the buffer really is this big in current versions of libpng
959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * it may not be in the future, so this was changed just to copy the
960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * interlaced row count:
961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_TRANSFORMS_SUPPORTED
965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformations)
966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_do_read_transformations(png_ptr, &row_info);
967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif
968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* The transformed pixel depth should match the depth now in row_info. */
970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (png_ptr->transformed_pixel_depth == 0)
971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   {
972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_error(png_ptr, "progressive row overflow");
975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   }
976893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_error(png_ptr, "internal progressive row size calculation error");
979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
980893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
9815f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_INTERLACING_SUPPORTED
982a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   /* Blow up interlaced rows to full size */
983893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      if (png_ptr->pass < 6)
986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->transformations);
988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
989893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    switch (png_ptr->pass)
990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
991893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 0:
992893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
996893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
997a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott               png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
998893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
999a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1000a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            if (png_ptr->pass == 2) /* Pass 1 might be empty */
1001893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1002893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1003893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_push_have_row(png_ptr, NULL);
1005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_read_push_finish_row(png_ptr);
1006893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1007893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1008a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1009893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (png_ptr->pass == 4 && png_ptr->height <= 4)
1010893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1011893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_push_have_row(png_ptr, NULL);
1014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_read_push_finish_row(png_ptr);
1015893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1016893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1017a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1018893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (png_ptr->pass == 6 && png_ptr->height <= 4)
1019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                png_push_have_row(png_ptr, NULL);
1021893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                png_read_push_finish_row(png_ptr);
1022893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1023a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1024893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
1025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1026a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1027893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 1:
1028893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1029893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
1031893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1032893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1033893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1035a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1036a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            if (png_ptr->pass == 2) /* Skip top 4 generated rows */
1037893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1038893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_push_have_row(png_ptr, NULL);
1041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_read_push_finish_row(png_ptr);
1042893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1044a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
1046893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1047a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1048893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 2:
1049893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1051a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1052893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1053893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1054893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1055893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1056893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1057a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1058893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1059893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_push_have_row(png_ptr, NULL);
1061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1063a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1064a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            if (png_ptr->pass == 4) /* Pass 3 might be empty */
1065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_push_have_row(png_ptr, NULL);
1069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_read_push_finish_row(png_ptr);
1070893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1071893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1072a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
1074893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1075a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1076893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 3:
1077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1078893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1079a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1080893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
1081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1082893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1083893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1085a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1086a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            if (png_ptr->pass == 4) /* Skip top two generated rows */
1087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               {
1090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik                  png_push_have_row(png_ptr, NULL);
1091893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                  png_read_push_finish_row(png_ptr);
1092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               }
1093893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1094a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
1096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1097a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1098893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 4:
1099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1101a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1107a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1108893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_push_have_row(png_ptr, NULL);
1111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1113a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1114a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            if (png_ptr->pass == 6) /* Pass 5 might be empty */
1115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_push_have_row(png_ptr, NULL);
1117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1118893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1119a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1120893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
1121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1122a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 5:
1124893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            int i;
1126a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
1128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1130893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1132a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1133a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott            if (png_ptr->pass == 6) /* Skip top generated row */
1134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            {
1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik               png_push_have_row(png_ptr, NULL);
1136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               png_read_push_finish_row(png_ptr);
1137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            }
1138a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            break;
1140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik         default:
1143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         case 6:
1144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         {
1145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_read_push_finish_row(png_ptr);
1147a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            if (png_ptr->pass != 6)
1149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project               break;
1150a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_push_have_row(png_ptr, NULL);
1152893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_read_push_finish_row(png_ptr);
1153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         }
1154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      }
1155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   else
1157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1158893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_read_push_finish_row(png_ptr);
1161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1164893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
1165b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_push_finish_row(png_structrp png_ptr)
1166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_INTERLACING_SUPPORTED
1168a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1170a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   /* Start of interlace block */
1171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
1172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1173a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   /* Offset to next interlace block */
1174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
1175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1176a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   /* Start of interlace block in the y direction */
1177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
1178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1179a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   /* Offset to next interlace block in the y direction */
1180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
1181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   /* Height of interlace block.  This is not currently used - if you need
1183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    * it, uncomment it here and in png.h
1184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
1185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   */
1186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
1187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->row_number++;
1189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->row_number < png_ptr->num_rows)
1190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      return;
1191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
11925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_INTERLACING_SUPPORTED
1193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->interlaced)
1194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
1195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_ptr->row_number = 0;
1196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
1197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik
1198893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      do
1199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      {
12004215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->pass++;
12014215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
12024215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project             (png_ptr->pass == 3 && png_ptr->width < 3) ||
12034215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project             (png_ptr->pass == 5 && png_ptr->width < 2))
1204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik            png_ptr->pass++;
12054215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project
12064215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         if (png_ptr->pass > 7)
12074215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project            png_ptr->pass--;
1208a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
12094215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         if (png_ptr->pass >= 7)
12104215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project            break;
12114215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project
12124215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->iwidth = (png_ptr->width +
1213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_pass_inc[png_ptr->pass] - 1 -
1214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_pass_start[png_ptr->pass]) /
1215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_pass_inc[png_ptr->pass];
12164215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project
12174215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         if (png_ptr->transformations & PNG_INTERLACE)
12184215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project            break;
12194215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project
12204215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project         png_ptr->num_rows = (png_ptr->height +
1221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_pass_yinc[png_ptr->pass] - 1 -
1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_pass_ystart[png_ptr->pass]) /
1223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik             png_pass_yinc[png_ptr->pass];
1224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
1226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
1227a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott#endif /* PNG_READ_INTERLACING_SUPPORTED */
1228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
1232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->info_fn != NULL)
1234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (*(png_ptr->info_fn))(png_ptr, info_ptr);
1235893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
1238b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
1239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->end_fn != NULL)
1241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (*(png_ptr->end_fn))(png_ptr, info_ptr);
1242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */
1245b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_push_have_row(png_structrp png_ptr, png_bytep row)
1246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (png_ptr->row_fn != NULL)
1248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         (int)png_ptr->pass);
1250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_INTERLACING_SUPPORTED
1253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
1254b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
1255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_const_bytep new_row)
1256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1257a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL)
1258a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
1259a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   /* new_row is a flag here - if it is NULL then the app callback was called
1261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * from an empty row (see the calls to png_struct::row_fn below), otherwise
1262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    * it must be png_ptr->row_buf+1
1263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    */
1264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik   if (new_row != NULL)
1265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik      png_combine_row(png_ptr, old_row, 1/*display*/);
1266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_READ_INTERLACING_SUPPORTED */
1268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI
1270b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
1271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik    png_progressive_end_ptr end_fn)
1273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1274a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL)
1275a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return;
1276a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->info_fn = info_fn;
1278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->row_fn = row_fn;
1279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_ptr->end_fn = end_fn;
1280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
1282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
1284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_voidp PNGAPI
1285b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_get_progressive_ptr(png_const_structrp png_ptr)
1286893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
1287a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott   if (png_ptr == NULL)
1288a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott      return (NULL);
1289a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott
1290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   return png_ptr->io_ptr;
1291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
1292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
1293