xref: /aosp_15_r20/external/libpng/contrib/tools/pngfix.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
1*a67afe4dSAndroid Build Coastguard Worker /* pngfix.c
2*a67afe4dSAndroid Build Coastguard Worker  *
3*a67afe4dSAndroid Build Coastguard Worker  * Copyright (c) 2014-2017,2024 John Cunningham Bowler
4*a67afe4dSAndroid Build Coastguard Worker  *
5*a67afe4dSAndroid Build Coastguard Worker  * This code is released under the libpng license.
6*a67afe4dSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the disclaimer
7*a67afe4dSAndroid Build Coastguard Worker  * and license in png.h
8*a67afe4dSAndroid Build Coastguard Worker  *
9*a67afe4dSAndroid Build Coastguard Worker  * Tool to check and fix the zlib inflate 'too far back' problem.
10*a67afe4dSAndroid Build Coastguard Worker  * See the usage message for more information.
11*a67afe4dSAndroid Build Coastguard Worker  */
12*a67afe4dSAndroid Build Coastguard Worker 
13*a67afe4dSAndroid Build Coastguard Worker #include <stdlib.h>
14*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
15*a67afe4dSAndroid Build Coastguard Worker #include <string.h>
16*a67afe4dSAndroid Build Coastguard Worker #include <ctype.h>
17*a67afe4dSAndroid Build Coastguard Worker #include <limits.h>
18*a67afe4dSAndroid Build Coastguard Worker #include <errno.h>
19*a67afe4dSAndroid Build Coastguard Worker #include <assert.h>
20*a67afe4dSAndroid Build Coastguard Worker 
21*a67afe4dSAndroid Build Coastguard Worker #define implies(x,y) assert(!(x) || (y))
22*a67afe4dSAndroid Build Coastguard Worker 
23*a67afe4dSAndroid Build Coastguard Worker #define PROGRAM_NAME "pngfix"
24*a67afe4dSAndroid Build Coastguard Worker 
25*a67afe4dSAndroid Build Coastguard Worker /* Define the following to use this program against your installed libpng,
26*a67afe4dSAndroid Build Coastguard Worker  * rather than the one being built here:
27*a67afe4dSAndroid Build Coastguard Worker  */
28*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_FREESTANDING_TESTS
29*a67afe4dSAndroid Build Coastguard Worker #  include <png.h>
30*a67afe4dSAndroid Build Coastguard Worker #else
31*a67afe4dSAndroid Build Coastguard Worker #  include "../../png.h"
32*a67afe4dSAndroid Build Coastguard Worker #endif
33*a67afe4dSAndroid Build Coastguard Worker 
34*a67afe4dSAndroid Build Coastguard Worker #if PNG_LIBPNG_VER < 10603 /* 1.6.3 */
35*a67afe4dSAndroid Build Coastguard Worker #  error "pngfix will not work with libpng prior to 1.6.3"
36*a67afe4dSAndroid Build Coastguard Worker #endif
37*a67afe4dSAndroid Build Coastguard Worker 
38*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_SETJMP_SUPPORTED
39*a67afe4dSAndroid Build Coastguard Worker #include <setjmp.h>
40*a67afe4dSAndroid Build Coastguard Worker 
41*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_SUPPORTED) && defined(PNG_EASY_ACCESS_SUPPORTED) &&\
42*a67afe4dSAndroid Build Coastguard Worker    (defined(PNG_READ_DEINTERLACE_SUPPORTED) ||\
43*a67afe4dSAndroid Build Coastguard Worker     defined(PNG_READ_INTERLACING_SUPPORTED))
44*a67afe4dSAndroid Build Coastguard Worker 
45*a67afe4dSAndroid Build Coastguard Worker /* zlib.h defines the structure z_stream, an instance of which is included
46*a67afe4dSAndroid Build Coastguard Worker  * in this structure and is required for decompressing the LZ compressed
47*a67afe4dSAndroid Build Coastguard Worker  * data in PNG files.
48*a67afe4dSAndroid Build Coastguard Worker  */
49*a67afe4dSAndroid Build Coastguard Worker #ifndef ZLIB_CONST
50*a67afe4dSAndroid Build Coastguard Worker    /* We must ensure that zlib uses 'const' in declarations. */
51*a67afe4dSAndroid Build Coastguard Worker #  define ZLIB_CONST
52*a67afe4dSAndroid Build Coastguard Worker #endif
53*a67afe4dSAndroid Build Coastguard Worker #include <zlib.h>
54*a67afe4dSAndroid Build Coastguard Worker #ifdef const
55*a67afe4dSAndroid Build Coastguard Worker    /* zlib.h sometimes #defines const to nothing, undo this. */
56*a67afe4dSAndroid Build Coastguard Worker #  undef const
57*a67afe4dSAndroid Build Coastguard Worker #endif
58*a67afe4dSAndroid Build Coastguard Worker 
59*a67afe4dSAndroid Build Coastguard Worker /* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
60*a67afe4dSAndroid Build Coastguard Worker  * with older builds.
61*a67afe4dSAndroid Build Coastguard Worker  */
62*a67afe4dSAndroid Build Coastguard Worker #if ZLIB_VERNUM < 0x1260
63*a67afe4dSAndroid Build Coastguard Worker #  define PNGZ_MSG_CAST(s) constcast(char*,s)
64*a67afe4dSAndroid Build Coastguard Worker #  define PNGZ_INPUT_CAST(b) constcast(png_bytep,b)
65*a67afe4dSAndroid Build Coastguard Worker #else
66*a67afe4dSAndroid Build Coastguard Worker #  define PNGZ_MSG_CAST(s) (s)
67*a67afe4dSAndroid Build Coastguard Worker #  define PNGZ_INPUT_CAST(b) (b)
68*a67afe4dSAndroid Build Coastguard Worker #endif
69*a67afe4dSAndroid Build Coastguard Worker 
70*a67afe4dSAndroid Build Coastguard Worker #ifndef PNG_MAXIMUM_INFLATE_WINDOW
71*a67afe4dSAndroid Build Coastguard Worker #  error "pngfix not supported in this libpng version"
72*a67afe4dSAndroid Build Coastguard Worker #endif
73*a67afe4dSAndroid Build Coastguard Worker 
74*a67afe4dSAndroid Build Coastguard Worker #if ZLIB_VERNUM >= 0x1240
75*a67afe4dSAndroid Build Coastguard Worker 
76*a67afe4dSAndroid Build Coastguard Worker /* Copied from pngpriv.h */
77*a67afe4dSAndroid Build Coastguard Worker #ifdef __cplusplus
78*a67afe4dSAndroid Build Coastguard Worker #  define voidcast(type, value) static_cast<type>(value)
79*a67afe4dSAndroid Build Coastguard Worker #  define constcast(type, value) const_cast<type>(value)
80*a67afe4dSAndroid Build Coastguard Worker #  define aligncast(type, value) \
81*a67afe4dSAndroid Build Coastguard Worker    static_cast<type>(static_cast<void*>(value))
82*a67afe4dSAndroid Build Coastguard Worker #  define aligncastconst(type, value) \
83*a67afe4dSAndroid Build Coastguard Worker    static_cast<type>(static_cast<const void*>(value))
84*a67afe4dSAndroid Build Coastguard Worker #else
85*a67afe4dSAndroid Build Coastguard Worker #  define voidcast(type, value) (value)
86*a67afe4dSAndroid Build Coastguard Worker #  define constcast(type, value) ((type)(value))
87*a67afe4dSAndroid Build Coastguard Worker #  define aligncast(type, value) ((void*)(value))
88*a67afe4dSAndroid Build Coastguard Worker #  define aligncastconst(type, value) ((const void*)(value))
89*a67afe4dSAndroid Build Coastguard Worker #endif /* __cplusplus */
90*a67afe4dSAndroid Build Coastguard Worker 
91*a67afe4dSAndroid Build Coastguard Worker #if PNG_LIBPNG_VER < 10700
92*a67afe4dSAndroid Build Coastguard Worker /* Chunk tags (copied from pngpriv.h) */
93*a67afe4dSAndroid Build Coastguard Worker #define PNG_32b(b,s) ((png_uint_32)(b) << (s))
94*a67afe4dSAndroid Build Coastguard Worker #define PNG_U32(b1,b2,b3,b4) \
95*a67afe4dSAndroid Build Coastguard Worker    (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
96*a67afe4dSAndroid Build Coastguard Worker 
97*a67afe4dSAndroid Build Coastguard Worker /* Constants for known chunk types. */
98*a67afe4dSAndroid Build Coastguard Worker #define png_IDAT PNG_U32( 73,  68,  65,  84)
99*a67afe4dSAndroid Build Coastguard Worker #define png_IEND PNG_U32( 73,  69,  78,  68)
100*a67afe4dSAndroid Build Coastguard Worker #define png_IHDR PNG_U32( 73,  72,  68,  82)
101*a67afe4dSAndroid Build Coastguard Worker #define png_PLTE PNG_U32( 80,  76,  84,  69)
102*a67afe4dSAndroid Build Coastguard Worker #define png_bKGD PNG_U32( 98,  75,  71,  68)
103*a67afe4dSAndroid Build Coastguard Worker #define png_cHRM PNG_U32( 99,  72,  82,  77)
104*a67afe4dSAndroid Build Coastguard Worker #define png_fRAc PNG_U32(102,  82,  65,  99) /* registered, not defined */
105*a67afe4dSAndroid Build Coastguard Worker #define png_gAMA PNG_U32(103,  65,  77,  65)
106*a67afe4dSAndroid Build Coastguard Worker #define png_gIFg PNG_U32(103,  73,  70, 103)
107*a67afe4dSAndroid Build Coastguard Worker #define png_gIFt PNG_U32(103,  73,  70, 116) /* deprecated */
108*a67afe4dSAndroid Build Coastguard Worker #define png_gIFx PNG_U32(103,  73,  70, 120)
109*a67afe4dSAndroid Build Coastguard Worker #define png_hIST PNG_U32(104,  73,  83,  84)
110*a67afe4dSAndroid Build Coastguard Worker #define png_iCCP PNG_U32(105,  67,  67,  80)
111*a67afe4dSAndroid Build Coastguard Worker #define png_iTXt PNG_U32(105,  84,  88, 116)
112*a67afe4dSAndroid Build Coastguard Worker #define png_oFFs PNG_U32(111,  70,  70, 115)
113*a67afe4dSAndroid Build Coastguard Worker #define png_pCAL PNG_U32(112,  67,  65,  76)
114*a67afe4dSAndroid Build Coastguard Worker #define png_pHYs PNG_U32(112,  72,  89, 115)
115*a67afe4dSAndroid Build Coastguard Worker #define png_sBIT PNG_U32(115,  66,  73,  84)
116*a67afe4dSAndroid Build Coastguard Worker #define png_sCAL PNG_U32(115,  67,  65,  76)
117*a67afe4dSAndroid Build Coastguard Worker #define png_sPLT PNG_U32(115,  80,  76,  84)
118*a67afe4dSAndroid Build Coastguard Worker #define png_sRGB PNG_U32(115,  82,  71,  66)
119*a67afe4dSAndroid Build Coastguard Worker #define png_sTER PNG_U32(115,  84,  69,  82)
120*a67afe4dSAndroid Build Coastguard Worker #define png_tEXt PNG_U32(116,  69,  88, 116)
121*a67afe4dSAndroid Build Coastguard Worker #define png_tIME PNG_U32(116,  73,  77,  69)
122*a67afe4dSAndroid Build Coastguard Worker #define png_tRNS PNG_U32(116,  82,  78,  83)
123*a67afe4dSAndroid Build Coastguard Worker #define png_zTXt PNG_U32(122,  84,  88, 116)
124*a67afe4dSAndroid Build Coastguard Worker #endif
125*a67afe4dSAndroid Build Coastguard Worker 
126*a67afe4dSAndroid Build Coastguard Worker /* The 8-byte signature as a pair of 32-bit quantities */
127*a67afe4dSAndroid Build Coastguard Worker #define sig1 PNG_U32(137,  80,  78,  71)
128*a67afe4dSAndroid Build Coastguard Worker #define sig2 PNG_U32( 13,  10,  26,  10)
129*a67afe4dSAndroid Build Coastguard Worker 
130*a67afe4dSAndroid Build Coastguard Worker /* Is the chunk critical? */
131*a67afe4dSAndroid Build Coastguard Worker #define CRITICAL(chunk) (((chunk) & PNG_U32(32,0,0,0)) == 0)
132*a67afe4dSAndroid Build Coastguard Worker 
133*a67afe4dSAndroid Build Coastguard Worker /* Is it safe to copy? */
134*a67afe4dSAndroid Build Coastguard Worker #define SAFE_TO_COPY(chunk) (((chunk) & PNG_U32(0,0,0,32)) != 0)
135*a67afe4dSAndroid Build Coastguard Worker 
136*a67afe4dSAndroid Build Coastguard Worker /********************************* UTILITIES **********************************/
137*a67afe4dSAndroid Build Coastguard Worker /* UNREACHED is a value to cause an assert to fail. Because of the way the
138*a67afe4dSAndroid Build Coastguard Worker  * assert macro is written the string "UNREACHED" is produced in the error
139*a67afe4dSAndroid Build Coastguard Worker  * message.
140*a67afe4dSAndroid Build Coastguard Worker  */
141*a67afe4dSAndroid Build Coastguard Worker #define UNREACHED 0
142*a67afe4dSAndroid Build Coastguard Worker 
143*a67afe4dSAndroid Build Coastguard Worker /* 80-bit number handling - a PNG image can be up to (2^31-1)x(2^31-1) 8-byte
144*a67afe4dSAndroid Build Coastguard Worker  * (16-bit RGBA) pixels in size; that's less than 2^65 bytes or 2^68 bits, so
145*a67afe4dSAndroid Build Coastguard Worker  * arithmetic of 80-bit numbers is sufficient.  This representation uses an
146*a67afe4dSAndroid Build Coastguard Worker  * arbitrary length array of png_uint_16 digits (0..65535).  The representation
147*a67afe4dSAndroid Build Coastguard Worker  * is little endian.
148*a67afe4dSAndroid Build Coastguard Worker  *
149*a67afe4dSAndroid Build Coastguard Worker  * The arithmetic functions take zero to two uarb values together with the
150*a67afe4dSAndroid Build Coastguard Worker  * number of digits in those values and write the result to the given uarb
151*a67afe4dSAndroid Build Coastguard Worker  * (always the first argument) returning the number of digits in the result.
152*a67afe4dSAndroid Build Coastguard Worker  * If the result is negative the return value is also negative (this would
153*a67afe4dSAndroid Build Coastguard Worker  * normally be an error).
154*a67afe4dSAndroid Build Coastguard Worker  */
155*a67afe4dSAndroid Build Coastguard Worker typedef png_uint_16  udigit; /* A 'unum' is an array of these */
156*a67afe4dSAndroid Build Coastguard Worker typedef png_uint_16p uarb;
157*a67afe4dSAndroid Build Coastguard Worker typedef png_const_uint_16p uarbc;
158*a67afe4dSAndroid Build Coastguard Worker 
159*a67afe4dSAndroid Build Coastguard Worker #define UDIGITS(unum) ((sizeof unum)/(sizeof (udigit))
160*a67afe4dSAndroid Build Coastguard Worker    /* IMPORTANT: only apply this to an array, applied to a pointer the result
161*a67afe4dSAndroid Build Coastguard Worker     * will typically be '2', which is not useful.
162*a67afe4dSAndroid Build Coastguard Worker     */
163*a67afe4dSAndroid Build Coastguard Worker 
164*a67afe4dSAndroid Build Coastguard Worker static int
uarb_set(uarb result,png_alloc_size_t val)165*a67afe4dSAndroid Build Coastguard Worker uarb_set(uarb result, png_alloc_size_t val)
166*a67afe4dSAndroid Build Coastguard Worker    /* Set (initialize) 'result' to 'val'.  The size required for 'result' must
167*a67afe4dSAndroid Build Coastguard Worker     * be determined by the caller from a knowledge of the maximum for 'val'.
168*a67afe4dSAndroid Build Coastguard Worker     */
169*a67afe4dSAndroid Build Coastguard Worker {
170*a67afe4dSAndroid Build Coastguard Worker    int ndigits = 0;
171*a67afe4dSAndroid Build Coastguard Worker 
172*a67afe4dSAndroid Build Coastguard Worker    while (val > 0)
173*a67afe4dSAndroid Build Coastguard Worker    {
174*a67afe4dSAndroid Build Coastguard Worker       result[ndigits++] = (png_uint_16)(val & 0xffff);
175*a67afe4dSAndroid Build Coastguard Worker       val >>= 16;
176*a67afe4dSAndroid Build Coastguard Worker    }
177*a67afe4dSAndroid Build Coastguard Worker 
178*a67afe4dSAndroid Build Coastguard Worker    return ndigits;
179*a67afe4dSAndroid Build Coastguard Worker }
180*a67afe4dSAndroid Build Coastguard Worker 
181*a67afe4dSAndroid Build Coastguard Worker static int
uarb_copy(uarb to,uarb from,int idigits)182*a67afe4dSAndroid Build Coastguard Worker uarb_copy(uarb to, uarb from, int idigits)
183*a67afe4dSAndroid Build Coastguard Worker    /* Copy a uarb, may reduce the digit count */
184*a67afe4dSAndroid Build Coastguard Worker {
185*a67afe4dSAndroid Build Coastguard Worker    int d, odigits;
186*a67afe4dSAndroid Build Coastguard Worker 
187*a67afe4dSAndroid Build Coastguard Worker    for (d=odigits=0; d<idigits; ++d)
188*a67afe4dSAndroid Build Coastguard Worker       if ((to[d] = from[d]) != 0)
189*a67afe4dSAndroid Build Coastguard Worker          odigits = d+1;
190*a67afe4dSAndroid Build Coastguard Worker 
191*a67afe4dSAndroid Build Coastguard Worker    return odigits;
192*a67afe4dSAndroid Build Coastguard Worker }
193*a67afe4dSAndroid Build Coastguard Worker 
194*a67afe4dSAndroid Build Coastguard Worker static int
uarb_inc(uarb num,int in_digits,png_int_32 add)195*a67afe4dSAndroid Build Coastguard Worker uarb_inc(uarb num, int in_digits, png_int_32 add)
196*a67afe4dSAndroid Build Coastguard Worker    /* This is a signed 32-bit add, except that to avoid overflow the value added
197*a67afe4dSAndroid Build Coastguard Worker     * or subtracted must be no more than 2^31-65536.  A negative result
198*a67afe4dSAndroid Build Coastguard Worker     * indicates a negative number (which is an error below).  The size of
199*a67afe4dSAndroid Build Coastguard Worker     * 'num' should be max(in_digits+1,2) for arbitrary 'add' but can be just
200*a67afe4dSAndroid Build Coastguard Worker     * in_digits+1 if add is known to be in the range -65535..65535.
201*a67afe4dSAndroid Build Coastguard Worker     */
202*a67afe4dSAndroid Build Coastguard Worker {
203*a67afe4dSAndroid Build Coastguard Worker    int out_digits = 0;
204*a67afe4dSAndroid Build Coastguard Worker 
205*a67afe4dSAndroid Build Coastguard Worker    while (out_digits < in_digits)
206*a67afe4dSAndroid Build Coastguard Worker    {
207*a67afe4dSAndroid Build Coastguard Worker       add += num[out_digits];
208*a67afe4dSAndroid Build Coastguard Worker       num[out_digits++] = (png_uint_16)(add & 0xffff);
209*a67afe4dSAndroid Build Coastguard Worker       add >>= 16;
210*a67afe4dSAndroid Build Coastguard Worker    }
211*a67afe4dSAndroid Build Coastguard Worker 
212*a67afe4dSAndroid Build Coastguard Worker    while (add != 0 && add != (-1))
213*a67afe4dSAndroid Build Coastguard Worker    {
214*a67afe4dSAndroid Build Coastguard Worker       num[out_digits++] = (png_uint_16)(add & 0xffff);
215*a67afe4dSAndroid Build Coastguard Worker       add >>= 16;
216*a67afe4dSAndroid Build Coastguard Worker    }
217*a67afe4dSAndroid Build Coastguard Worker 
218*a67afe4dSAndroid Build Coastguard Worker    if (add == 0)
219*a67afe4dSAndroid Build Coastguard Worker    {
220*a67afe4dSAndroid Build Coastguard Worker       while (out_digits > 0 && num[out_digits-1] == 0)
221*a67afe4dSAndroid Build Coastguard Worker          --out_digits;
222*a67afe4dSAndroid Build Coastguard Worker       return out_digits; /* may be 0 */
223*a67afe4dSAndroid Build Coastguard Worker    }
224*a67afe4dSAndroid Build Coastguard Worker 
225*a67afe4dSAndroid Build Coastguard Worker    else /* negative result */
226*a67afe4dSAndroid Build Coastguard Worker    {
227*a67afe4dSAndroid Build Coastguard Worker       while (out_digits > 1 && num[out_digits-1] == 0xffff)
228*a67afe4dSAndroid Build Coastguard Worker          --out_digits;
229*a67afe4dSAndroid Build Coastguard Worker 
230*a67afe4dSAndroid Build Coastguard Worker       return -out_digits;
231*a67afe4dSAndroid Build Coastguard Worker    }
232*a67afe4dSAndroid Build Coastguard Worker }
233*a67afe4dSAndroid Build Coastguard Worker 
234*a67afe4dSAndroid Build Coastguard Worker static int
uarb_add32(uarb num,int in_digits,png_uint_32 add)235*a67afe4dSAndroid Build Coastguard Worker uarb_add32(uarb num, int in_digits, png_uint_32 add)
236*a67afe4dSAndroid Build Coastguard Worker    /* As above but this works with any 32-bit value and only does 'add' */
237*a67afe4dSAndroid Build Coastguard Worker {
238*a67afe4dSAndroid Build Coastguard Worker    if (in_digits > 0)
239*a67afe4dSAndroid Build Coastguard Worker    {
240*a67afe4dSAndroid Build Coastguard Worker       in_digits = uarb_inc(num, in_digits, add & 0xffff);
241*a67afe4dSAndroid Build Coastguard Worker       return uarb_inc(num+1, in_digits-1, add >> 16)+1;
242*a67afe4dSAndroid Build Coastguard Worker    }
243*a67afe4dSAndroid Build Coastguard Worker 
244*a67afe4dSAndroid Build Coastguard Worker    return uarb_set(num, add);
245*a67afe4dSAndroid Build Coastguard Worker }
246*a67afe4dSAndroid Build Coastguard Worker 
247*a67afe4dSAndroid Build Coastguard Worker static int
uarb_mult_digit(uarb acc,int a_digits,uarb num,int n_digits,png_uint_16 val)248*a67afe4dSAndroid Build Coastguard Worker uarb_mult_digit(uarb acc, int a_digits, uarb num, int n_digits,
249*a67afe4dSAndroid Build Coastguard Worker    png_uint_16 val)
250*a67afe4dSAndroid Build Coastguard Worker    /* Primitive one-digit multiply - 'val' must be 0..65535. Note that this
251*a67afe4dSAndroid Build Coastguard Worker     * primitive is a multiply and accumulate - the result of *num * val is added
252*a67afe4dSAndroid Build Coastguard Worker     * to *acc.
253*a67afe4dSAndroid Build Coastguard Worker     *
254*a67afe4dSAndroid Build Coastguard Worker     * This is a one-digit multiply, so the product may be up to one digit longer
255*a67afe4dSAndroid Build Coastguard Worker     * than 'num', however the add to 'acc' means that the caller must ensure
256*a67afe4dSAndroid Build Coastguard Worker     * that 'acc' is at least one digit longer than this *and* at least one digit
257*a67afe4dSAndroid Build Coastguard Worker     * longer than the current length of 'acc'.  (Or the caller must otherwise
258*a67afe4dSAndroid Build Coastguard Worker     * ensure 'adigits' is adequate from knowledge of the values.)
259*a67afe4dSAndroid Build Coastguard Worker     */
260*a67afe4dSAndroid Build Coastguard Worker {
261*a67afe4dSAndroid Build Coastguard Worker    /* The digits in *acc, *num and val are in the range 0..65535, so the
262*a67afe4dSAndroid Build Coastguard Worker     * result below is at most (65535*65535)+2*65635 = 65535*(65535+2), which is
263*a67afe4dSAndroid Build Coastguard Worker     * exactly 0xffffffff.
264*a67afe4dSAndroid Build Coastguard Worker     */
265*a67afe4dSAndroid Build Coastguard Worker    if (val > 0 && n_digits > 0) /* Else the product is 0 */
266*a67afe4dSAndroid Build Coastguard Worker    {
267*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 carry = 0;
268*a67afe4dSAndroid Build Coastguard Worker       int out_digits = 0;
269*a67afe4dSAndroid Build Coastguard Worker 
270*a67afe4dSAndroid Build Coastguard Worker       while (out_digits < n_digits || carry > 0)
271*a67afe4dSAndroid Build Coastguard Worker       {
272*a67afe4dSAndroid Build Coastguard Worker          if (out_digits < a_digits)
273*a67afe4dSAndroid Build Coastguard Worker             carry += acc[out_digits];
274*a67afe4dSAndroid Build Coastguard Worker 
275*a67afe4dSAndroid Build Coastguard Worker          if (out_digits < n_digits)
276*a67afe4dSAndroid Build Coastguard Worker             carry += (png_uint_32)num[out_digits] * val;
277*a67afe4dSAndroid Build Coastguard Worker 
278*a67afe4dSAndroid Build Coastguard Worker          acc[out_digits++] = (png_uint_16)(carry & 0xffff);
279*a67afe4dSAndroid Build Coastguard Worker          carry >>= 16;
280*a67afe4dSAndroid Build Coastguard Worker       }
281*a67afe4dSAndroid Build Coastguard Worker 
282*a67afe4dSAndroid Build Coastguard Worker       /* So carry is 0 and all the input digits have been consumed. This means
283*a67afe4dSAndroid Build Coastguard Worker        * that it is possible to skip any remaining digits in acc.
284*a67afe4dSAndroid Build Coastguard Worker        */
285*a67afe4dSAndroid Build Coastguard Worker       if (out_digits > a_digits)
286*a67afe4dSAndroid Build Coastguard Worker          return out_digits;
287*a67afe4dSAndroid Build Coastguard Worker    }
288*a67afe4dSAndroid Build Coastguard Worker 
289*a67afe4dSAndroid Build Coastguard Worker    return a_digits;
290*a67afe4dSAndroid Build Coastguard Worker }
291*a67afe4dSAndroid Build Coastguard Worker 
292*a67afe4dSAndroid Build Coastguard Worker static int
uarb_mult32(uarb acc,int a_digits,uarb num,int n_digits,png_uint_32 val)293*a67afe4dSAndroid Build Coastguard Worker uarb_mult32(uarb acc, int a_digits, uarb num, int n_digits, png_uint_32 val)
294*a67afe4dSAndroid Build Coastguard Worker    /* calculate acc += num * val, 'val' may be any 32-bit value, 'acc' and 'num'
295*a67afe4dSAndroid Build Coastguard Worker     * may be any value, returns the number of digits in 'acc'.
296*a67afe4dSAndroid Build Coastguard Worker     */
297*a67afe4dSAndroid Build Coastguard Worker {
298*a67afe4dSAndroid Build Coastguard Worker    if (n_digits > 0 && val > 0)
299*a67afe4dSAndroid Build Coastguard Worker    {
300*a67afe4dSAndroid Build Coastguard Worker       a_digits = uarb_mult_digit(acc, a_digits, num, n_digits,
301*a67afe4dSAndroid Build Coastguard Worker          (png_uint_16)(val & 0xffff));
302*a67afe4dSAndroid Build Coastguard Worker 
303*a67afe4dSAndroid Build Coastguard Worker       val >>= 16;
304*a67afe4dSAndroid Build Coastguard Worker       if (val > 0)
305*a67afe4dSAndroid Build Coastguard Worker          a_digits = uarb_mult_digit(acc+1, a_digits-1, num, n_digits,
306*a67afe4dSAndroid Build Coastguard Worker             (png_uint_16)val) + 1;
307*a67afe4dSAndroid Build Coastguard Worker 
308*a67afe4dSAndroid Build Coastguard Worker       /* Because n_digits and val are >0 the following must be true: */
309*a67afe4dSAndroid Build Coastguard Worker       assert(a_digits > 0);
310*a67afe4dSAndroid Build Coastguard Worker    }
311*a67afe4dSAndroid Build Coastguard Worker 
312*a67afe4dSAndroid Build Coastguard Worker    return a_digits;
313*a67afe4dSAndroid Build Coastguard Worker }
314*a67afe4dSAndroid Build Coastguard Worker 
315*a67afe4dSAndroid Build Coastguard Worker static int
uarb_shift(uarb inout,int ndigits,unsigned int right_shift)316*a67afe4dSAndroid Build Coastguard Worker uarb_shift(uarb inout, int ndigits, unsigned int right_shift)
317*a67afe4dSAndroid Build Coastguard Worker    /* Shift inout right by right_shift bits, right_shift must be in the range
318*a67afe4dSAndroid Build Coastguard Worker     * 1..15
319*a67afe4dSAndroid Build Coastguard Worker     */
320*a67afe4dSAndroid Build Coastguard Worker {
321*a67afe4dSAndroid Build Coastguard Worker    int i = ndigits;
322*a67afe4dSAndroid Build Coastguard Worker    png_uint_16 carry = 0;
323*a67afe4dSAndroid Build Coastguard Worker 
324*a67afe4dSAndroid Build Coastguard Worker    assert(right_shift >= 1 && right_shift <= 15);
325*a67afe4dSAndroid Build Coastguard Worker 
326*a67afe4dSAndroid Build Coastguard Worker    while (--i >= 0)
327*a67afe4dSAndroid Build Coastguard Worker    {
328*a67afe4dSAndroid Build Coastguard Worker       png_uint_16 temp = (png_uint_16)(carry | (inout[i] >> right_shift));
329*a67afe4dSAndroid Build Coastguard Worker 
330*a67afe4dSAndroid Build Coastguard Worker       /* Bottom bits to top bits of carry */
331*a67afe4dSAndroid Build Coastguard Worker       carry = (png_uint_16)((inout[i] << (16-right_shift)) & 0xffff);
332*a67afe4dSAndroid Build Coastguard Worker 
333*a67afe4dSAndroid Build Coastguard Worker       inout[i] = temp;
334*a67afe4dSAndroid Build Coastguard Worker 
335*a67afe4dSAndroid Build Coastguard Worker       /* The shift may reduce ndigits */
336*a67afe4dSAndroid Build Coastguard Worker       if (i+1 == ndigits && temp == 0)
337*a67afe4dSAndroid Build Coastguard Worker          ndigits = i;
338*a67afe4dSAndroid Build Coastguard Worker    }
339*a67afe4dSAndroid Build Coastguard Worker 
340*a67afe4dSAndroid Build Coastguard Worker    return ndigits;
341*a67afe4dSAndroid Build Coastguard Worker }
342*a67afe4dSAndroid Build Coastguard Worker 
343*a67afe4dSAndroid Build Coastguard Worker static int
uarb_cmp(uarb a,int adigits,uarb b,int bdigits)344*a67afe4dSAndroid Build Coastguard Worker uarb_cmp(uarb a, int adigits, uarb b, int bdigits)
345*a67afe4dSAndroid Build Coastguard Worker    /* Return -1/0/+1 according as a<b/a==b/a>b */
346*a67afe4dSAndroid Build Coastguard Worker {
347*a67afe4dSAndroid Build Coastguard Worker    if (adigits < bdigits)
348*a67afe4dSAndroid Build Coastguard Worker       return -1;
349*a67afe4dSAndroid Build Coastguard Worker 
350*a67afe4dSAndroid Build Coastguard Worker    if (adigits > bdigits)
351*a67afe4dSAndroid Build Coastguard Worker       return 1;
352*a67afe4dSAndroid Build Coastguard Worker 
353*a67afe4dSAndroid Build Coastguard Worker    while (adigits-- > 0)
354*a67afe4dSAndroid Build Coastguard Worker       if (a[adigits] < b[adigits])
355*a67afe4dSAndroid Build Coastguard Worker          return -1;
356*a67afe4dSAndroid Build Coastguard Worker 
357*a67afe4dSAndroid Build Coastguard Worker       else if (a[adigits] > b[adigits])
358*a67afe4dSAndroid Build Coastguard Worker          return 1;
359*a67afe4dSAndroid Build Coastguard Worker 
360*a67afe4dSAndroid Build Coastguard Worker    return 0;
361*a67afe4dSAndroid Build Coastguard Worker }
362*a67afe4dSAndroid Build Coastguard Worker 
363*a67afe4dSAndroid Build Coastguard Worker #if 0 /*UNUSED*/
364*a67afe4dSAndroid Build Coastguard Worker static int
365*a67afe4dSAndroid Build Coastguard Worker uarb_eq32(uarb num, int digits, png_uint_32 val)
366*a67afe4dSAndroid Build Coastguard Worker    /* Return true if the uarb is equal to 'val' */
367*a67afe4dSAndroid Build Coastguard Worker {
368*a67afe4dSAndroid Build Coastguard Worker    switch (digits)
369*a67afe4dSAndroid Build Coastguard Worker    {
370*a67afe4dSAndroid Build Coastguard Worker       case 0:  return val == 0;
371*a67afe4dSAndroid Build Coastguard Worker       case 1:  return val == num[0];
372*a67afe4dSAndroid Build Coastguard Worker       case 2:  return (val & 0xffff) == num[0] && (val >> 16) == num[1];
373*a67afe4dSAndroid Build Coastguard Worker       default: return 0;
374*a67afe4dSAndroid Build Coastguard Worker    }
375*a67afe4dSAndroid Build Coastguard Worker }
376*a67afe4dSAndroid Build Coastguard Worker #endif
377*a67afe4dSAndroid Build Coastguard Worker 
378*a67afe4dSAndroid Build Coastguard Worker static void
uarb_printx(uarb num,int digits,FILE * out)379*a67afe4dSAndroid Build Coastguard Worker uarb_printx(uarb num, int digits, FILE *out)
380*a67afe4dSAndroid Build Coastguard Worker    /* Print 'num' as a hexadecimal number (easier than decimal!) */
381*a67afe4dSAndroid Build Coastguard Worker {
382*a67afe4dSAndroid Build Coastguard Worker    while (digits > 0)
383*a67afe4dSAndroid Build Coastguard Worker       if (num[--digits] > 0)
384*a67afe4dSAndroid Build Coastguard Worker       {
385*a67afe4dSAndroid Build Coastguard Worker          fprintf(out, "0x%x", num[digits]);
386*a67afe4dSAndroid Build Coastguard Worker 
387*a67afe4dSAndroid Build Coastguard Worker          while (digits > 0)
388*a67afe4dSAndroid Build Coastguard Worker             fprintf(out, "%.4x", num[--digits]);
389*a67afe4dSAndroid Build Coastguard Worker       }
390*a67afe4dSAndroid Build Coastguard Worker 
391*a67afe4dSAndroid Build Coastguard Worker       else if (digits == 0) /* the number is 0 */
392*a67afe4dSAndroid Build Coastguard Worker          fputs("0x0", out);
393*a67afe4dSAndroid Build Coastguard Worker }
394*a67afe4dSAndroid Build Coastguard Worker 
395*a67afe4dSAndroid Build Coastguard Worker static void
uarb_print(uarb num,int digits,FILE * out)396*a67afe4dSAndroid Build Coastguard Worker uarb_print(uarb num, int digits, FILE *out)
397*a67afe4dSAndroid Build Coastguard Worker    /* Prints 'num' as a decimal if it will fit in an unsigned long, else as a
398*a67afe4dSAndroid Build Coastguard Worker     * hexadecimal number.  Notice that the results vary for images over 4GByte
399*a67afe4dSAndroid Build Coastguard Worker     * in a system dependent way, and the hexadecimal form doesn't work very well
400*a67afe4dSAndroid Build Coastguard Worker     * in awk script input.
401*a67afe4dSAndroid Build Coastguard Worker     *
402*a67afe4dSAndroid Build Coastguard Worker     *
403*a67afe4dSAndroid Build Coastguard Worker     * TODO: write uarb_div10
404*a67afe4dSAndroid Build Coastguard Worker     */
405*a67afe4dSAndroid Build Coastguard Worker {
406*a67afe4dSAndroid Build Coastguard Worker    if (digits * sizeof (udigit) > sizeof (unsigned long))
407*a67afe4dSAndroid Build Coastguard Worker       uarb_printx(num, digits, out);
408*a67afe4dSAndroid Build Coastguard Worker 
409*a67afe4dSAndroid Build Coastguard Worker    else
410*a67afe4dSAndroid Build Coastguard Worker    {
411*a67afe4dSAndroid Build Coastguard Worker       unsigned long n = 0;
412*a67afe4dSAndroid Build Coastguard Worker 
413*a67afe4dSAndroid Build Coastguard Worker       while (digits > 0)
414*a67afe4dSAndroid Build Coastguard Worker          n = (n << 16) + num[--digits];
415*a67afe4dSAndroid Build Coastguard Worker 
416*a67afe4dSAndroid Build Coastguard Worker       fprintf(out, "%lu", n);
417*a67afe4dSAndroid Build Coastguard Worker    }
418*a67afe4dSAndroid Build Coastguard Worker }
419*a67afe4dSAndroid Build Coastguard Worker 
420*a67afe4dSAndroid Build Coastguard Worker /* Generate random bytes.  This uses a boring repeatable algorithm and it
421*a67afe4dSAndroid Build Coastguard Worker  * is implemented here so that it gives the same set of numbers on every
422*a67afe4dSAndroid Build Coastguard Worker  * architecture.  It's a linear congruential generator (Knuth or Sedgewick
423*a67afe4dSAndroid Build Coastguard Worker  * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
424*a67afe4dSAndroid Build Coastguard Worker  * Hill, "The Art of Electronics" (Pseudo-Random Bit Sequences and Noise
425*a67afe4dSAndroid Build Coastguard Worker  * Generation.)
426*a67afe4dSAndroid Build Coastguard Worker  *
427*a67afe4dSAndroid Build Coastguard Worker  * (Copied from contrib/libtests/pngvalid.c)
428*a67afe4dSAndroid Build Coastguard Worker  */
429*a67afe4dSAndroid Build Coastguard Worker static void
make_random_bytes(png_uint_32 * seed,void * pv,size_t size)430*a67afe4dSAndroid Build Coastguard Worker make_random_bytes(png_uint_32* seed, void* pv, size_t size)
431*a67afe4dSAndroid Build Coastguard Worker {
432*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 u0 = seed[0], u1 = seed[1];
433*a67afe4dSAndroid Build Coastguard Worker    png_bytep bytes = voidcast(png_bytep, pv);
434*a67afe4dSAndroid Build Coastguard Worker 
435*a67afe4dSAndroid Build Coastguard Worker    /* There are thirty-three bits; the next bit in the sequence is bit-33 XOR
436*a67afe4dSAndroid Build Coastguard Worker     * bit-20.  The top 1 bit is in u1, the bottom 32 are in u0.
437*a67afe4dSAndroid Build Coastguard Worker     */
438*a67afe4dSAndroid Build Coastguard Worker    size_t i;
439*a67afe4dSAndroid Build Coastguard Worker    for (i=0; i<size; ++i)
440*a67afe4dSAndroid Build Coastguard Worker    {
441*a67afe4dSAndroid Build Coastguard Worker       /* First generate 8 new bits then shift them in at the end. */
442*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
443*a67afe4dSAndroid Build Coastguard Worker       u1 <<= 8;
444*a67afe4dSAndroid Build Coastguard Worker       u1 |= u0 >> 24;
445*a67afe4dSAndroid Build Coastguard Worker       u0 <<= 8;
446*a67afe4dSAndroid Build Coastguard Worker       u0 |= u;
447*a67afe4dSAndroid Build Coastguard Worker       *bytes++ = (png_byte)u;
448*a67afe4dSAndroid Build Coastguard Worker    }
449*a67afe4dSAndroid Build Coastguard Worker 
450*a67afe4dSAndroid Build Coastguard Worker    seed[0] = u0;
451*a67afe4dSAndroid Build Coastguard Worker    seed[1] = u1;
452*a67afe4dSAndroid Build Coastguard Worker }
453*a67afe4dSAndroid Build Coastguard Worker 
454*a67afe4dSAndroid Build Coastguard Worker /* Clear an object to a random value. */
455*a67afe4dSAndroid Build Coastguard Worker static void
clear(void * pv,size_t size)456*a67afe4dSAndroid Build Coastguard Worker clear(void *pv, size_t size)
457*a67afe4dSAndroid Build Coastguard Worker {
458*a67afe4dSAndroid Build Coastguard Worker    static png_uint_32 clear_seed[2] = { 0x12345678, 0x9abcdef0 };
459*a67afe4dSAndroid Build Coastguard Worker    make_random_bytes(clear_seed, pv, size);
460*a67afe4dSAndroid Build Coastguard Worker }
461*a67afe4dSAndroid Build Coastguard Worker 
462*a67afe4dSAndroid Build Coastguard Worker #define CLEAR(object) clear(&(object), sizeof (object))
463*a67afe4dSAndroid Build Coastguard Worker 
464*a67afe4dSAndroid Build Coastguard Worker /* Copied from unreleased 1.7 code.
465*a67afe4dSAndroid Build Coastguard Worker  *
466*a67afe4dSAndroid Build Coastguard Worker  * CRC checking uses a local pre-built implementation of the Ethernet CRC32.
467*a67afe4dSAndroid Build Coastguard Worker  * This is to avoid a function call to the zlib DLL and to optimize the
468*a67afe4dSAndroid Build Coastguard Worker  * byte-by-byte case.
469*a67afe4dSAndroid Build Coastguard Worker  */
470*a67afe4dSAndroid Build Coastguard Worker static png_uint_32 crc_table[256] =
471*a67afe4dSAndroid Build Coastguard Worker {
472*a67afe4dSAndroid Build Coastguard Worker    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
473*a67afe4dSAndroid Build Coastguard Worker    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
474*a67afe4dSAndroid Build Coastguard Worker    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
475*a67afe4dSAndroid Build Coastguard Worker    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
476*a67afe4dSAndroid Build Coastguard Worker    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
477*a67afe4dSAndroid Build Coastguard Worker    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
478*a67afe4dSAndroid Build Coastguard Worker    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
479*a67afe4dSAndroid Build Coastguard Worker    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
480*a67afe4dSAndroid Build Coastguard Worker    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
481*a67afe4dSAndroid Build Coastguard Worker    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
482*a67afe4dSAndroid Build Coastguard Worker    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
483*a67afe4dSAndroid Build Coastguard Worker    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
484*a67afe4dSAndroid Build Coastguard Worker    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
485*a67afe4dSAndroid Build Coastguard Worker    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
486*a67afe4dSAndroid Build Coastguard Worker    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
487*a67afe4dSAndroid Build Coastguard Worker    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
488*a67afe4dSAndroid Build Coastguard Worker    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
489*a67afe4dSAndroid Build Coastguard Worker    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
490*a67afe4dSAndroid Build Coastguard Worker    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
491*a67afe4dSAndroid Build Coastguard Worker    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
492*a67afe4dSAndroid Build Coastguard Worker    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
493*a67afe4dSAndroid Build Coastguard Worker    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
494*a67afe4dSAndroid Build Coastguard Worker    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
495*a67afe4dSAndroid Build Coastguard Worker    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
496*a67afe4dSAndroid Build Coastguard Worker    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
497*a67afe4dSAndroid Build Coastguard Worker    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
498*a67afe4dSAndroid Build Coastguard Worker    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
499*a67afe4dSAndroid Build Coastguard Worker    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
500*a67afe4dSAndroid Build Coastguard Worker    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
501*a67afe4dSAndroid Build Coastguard Worker    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
502*a67afe4dSAndroid Build Coastguard Worker    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
503*a67afe4dSAndroid Build Coastguard Worker    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
504*a67afe4dSAndroid Build Coastguard Worker    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
505*a67afe4dSAndroid Build Coastguard Worker    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
506*a67afe4dSAndroid Build Coastguard Worker    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
507*a67afe4dSAndroid Build Coastguard Worker    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
508*a67afe4dSAndroid Build Coastguard Worker    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
509*a67afe4dSAndroid Build Coastguard Worker    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
510*a67afe4dSAndroid Build Coastguard Worker    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
511*a67afe4dSAndroid Build Coastguard Worker    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
512*a67afe4dSAndroid Build Coastguard Worker    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
513*a67afe4dSAndroid Build Coastguard Worker    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
514*a67afe4dSAndroid Build Coastguard Worker    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
515*a67afe4dSAndroid Build Coastguard Worker    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
516*a67afe4dSAndroid Build Coastguard Worker    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
517*a67afe4dSAndroid Build Coastguard Worker    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
518*a67afe4dSAndroid Build Coastguard Worker    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
519*a67afe4dSAndroid Build Coastguard Worker    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
520*a67afe4dSAndroid Build Coastguard Worker    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
521*a67afe4dSAndroid Build Coastguard Worker    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
522*a67afe4dSAndroid Build Coastguard Worker    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
523*a67afe4dSAndroid Build Coastguard Worker    0x2d02ef8d
524*a67afe4dSAndroid Build Coastguard Worker };
525*a67afe4dSAndroid Build Coastguard Worker 
526*a67afe4dSAndroid Build Coastguard Worker /* The CRC calculated here *IS* conditioned, the corresponding value used by
527*a67afe4dSAndroid Build Coastguard Worker  * zlib and the result value is obtained by XORing with CRC_INIT, which is also
528*a67afe4dSAndroid Build Coastguard Worker  * the first value that must be passed in (for the first byte) to crc_one_byte.
529*a67afe4dSAndroid Build Coastguard Worker  */
530*a67afe4dSAndroid Build Coastguard Worker #define CRC_INIT 0xffffffff
531*a67afe4dSAndroid Build Coastguard Worker 
532*a67afe4dSAndroid Build Coastguard Worker static png_uint_32
crc_one_byte(png_uint_32 crc,int b)533*a67afe4dSAndroid Build Coastguard Worker crc_one_byte(png_uint_32 crc, int b)
534*a67afe4dSAndroid Build Coastguard Worker {
535*a67afe4dSAndroid Build Coastguard Worker    return crc_table[(crc ^ b) & 0xff] ^ (crc >> 8);
536*a67afe4dSAndroid Build Coastguard Worker }
537*a67afe4dSAndroid Build Coastguard Worker 
538*a67afe4dSAndroid Build Coastguard Worker static png_uint_32
crc_init_4(png_uint_32 value)539*a67afe4dSAndroid Build Coastguard Worker crc_init_4(png_uint_32 value)
540*a67afe4dSAndroid Build Coastguard Worker {
541*a67afe4dSAndroid Build Coastguard Worker    /* This is an alternative to the algorithm used in zlib, which requires four
542*a67afe4dSAndroid Build Coastguard Worker     * separate tables to parallelize the four byte operations, it only works for
543*a67afe4dSAndroid Build Coastguard Worker     * a CRC of the first four bytes of the stream, but this is what happens in
544*a67afe4dSAndroid Build Coastguard Worker     * the parser below where length+chunk-name is read and chunk-name used to
545*a67afe4dSAndroid Build Coastguard Worker     * initialize the CRC.  Notice that the calculation here avoids repeated
546*a67afe4dSAndroid Build Coastguard Worker     * conditioning (xor with 0xffffffff) by storing the conditioned value.
547*a67afe4dSAndroid Build Coastguard Worker     */
548*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 crc = crc_table[(~value >> 24)] ^ 0xffffff;
549*a67afe4dSAndroid Build Coastguard Worker 
550*a67afe4dSAndroid Build Coastguard Worker    crc = crc_table[(crc ^ (value >> 16)) & 0xff] ^ (crc >> 8);
551*a67afe4dSAndroid Build Coastguard Worker    crc = crc_table[(crc ^ (value >> 8)) & 0xff] ^ (crc >> 8);
552*a67afe4dSAndroid Build Coastguard Worker    return crc_table[(crc ^ value) & 0xff] ^ (crc >> 8);
553*a67afe4dSAndroid Build Coastguard Worker }
554*a67afe4dSAndroid Build Coastguard Worker 
555*a67afe4dSAndroid Build Coastguard Worker static int
chunk_type_valid(png_uint_32 c)556*a67afe4dSAndroid Build Coastguard Worker chunk_type_valid(png_uint_32 c)
557*a67afe4dSAndroid Build Coastguard Worker    /* Bit whacking approach to chunk name validation that is intended to avoid
558*a67afe4dSAndroid Build Coastguard Worker     * branches.  The cost is that it uses a lot of 32-bit constants, which might
559*a67afe4dSAndroid Build Coastguard Worker     * be bad on some architectures.
560*a67afe4dSAndroid Build Coastguard Worker     */
561*a67afe4dSAndroid Build Coastguard Worker {
562*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 t;
563*a67afe4dSAndroid Build Coastguard Worker 
564*a67afe4dSAndroid Build Coastguard Worker    /* Remove bit 5 from all but the reserved byte; this means every
565*a67afe4dSAndroid Build Coastguard Worker     * 8-bit unit must be in the range 65-90 to be valid.  So bit 5
566*a67afe4dSAndroid Build Coastguard Worker     * must be zero, bit 6 must be set and bit 7 zero.
567*a67afe4dSAndroid Build Coastguard Worker     */
568*a67afe4dSAndroid Build Coastguard Worker    c &= ~PNG_U32(32,32,0,32);
569*a67afe4dSAndroid Build Coastguard Worker    t = (c & ~0x1f1f1f1f) ^ 0x40404040;
570*a67afe4dSAndroid Build Coastguard Worker 
571*a67afe4dSAndroid Build Coastguard Worker    /* Subtract 65 for each 8-bit quantity, this must not overflow
572*a67afe4dSAndroid Build Coastguard Worker     * and each byte must then be in the range 0-25.
573*a67afe4dSAndroid Build Coastguard Worker     */
574*a67afe4dSAndroid Build Coastguard Worker    c -= PNG_U32(65,65,65,65);
575*a67afe4dSAndroid Build Coastguard Worker    t |=c ;
576*a67afe4dSAndroid Build Coastguard Worker 
577*a67afe4dSAndroid Build Coastguard Worker    /* Subtract 26, handling the overflow which should set the top
578*a67afe4dSAndroid Build Coastguard Worker     * three bits of each byte.
579*a67afe4dSAndroid Build Coastguard Worker     */
580*a67afe4dSAndroid Build Coastguard Worker    c -= PNG_U32(25,25,25,26);
581*a67afe4dSAndroid Build Coastguard Worker    t |= ~c;
582*a67afe4dSAndroid Build Coastguard Worker 
583*a67afe4dSAndroid Build Coastguard Worker    return (t & 0xe0e0e0e0) == 0;
584*a67afe4dSAndroid Build Coastguard Worker }
585*a67afe4dSAndroid Build Coastguard Worker 
586*a67afe4dSAndroid Build Coastguard Worker /**************************** CONTROL INFORMATION *****************************/
587*a67afe4dSAndroid Build Coastguard Worker 
588*a67afe4dSAndroid Build Coastguard Worker /* Information about a sequence of IDAT chunks, the chunks have been re-synced
589*a67afe4dSAndroid Build Coastguard Worker  * using sync_stream below and the new lengths are recorded here.  Because the
590*a67afe4dSAndroid Build Coastguard Worker  * number of chunks is unlimited this is handled using a linked list of these
591*a67afe4dSAndroid Build Coastguard Worker  * structures.
592*a67afe4dSAndroid Build Coastguard Worker  */
593*a67afe4dSAndroid Build Coastguard Worker struct IDAT_list
594*a67afe4dSAndroid Build Coastguard Worker {
595*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *next;     /* Linked list */
596*a67afe4dSAndroid Build Coastguard Worker    unsigned int      length;   /* Actual length of the array below */
597*a67afe4dSAndroid Build Coastguard Worker    unsigned int      count;    /* Number of entries that are valid */
598*a67afe4dSAndroid Build Coastguard Worker #     define IDAT_INIT_LENGTH 16
599*a67afe4dSAndroid Build Coastguard Worker    png_uint_32       lengths[IDAT_INIT_LENGTH];
600*a67afe4dSAndroid Build Coastguard Worker };
601*a67afe4dSAndroid Build Coastguard Worker 
602*a67afe4dSAndroid Build Coastguard Worker static void
IDAT_list_init(struct IDAT_list * list)603*a67afe4dSAndroid Build Coastguard Worker IDAT_list_init(struct IDAT_list *list)
604*a67afe4dSAndroid Build Coastguard Worker {
605*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*list);
606*a67afe4dSAndroid Build Coastguard Worker 
607*a67afe4dSAndroid Build Coastguard Worker    list->next = NULL;
608*a67afe4dSAndroid Build Coastguard Worker    list->length = IDAT_INIT_LENGTH;
609*a67afe4dSAndroid Build Coastguard Worker }
610*a67afe4dSAndroid Build Coastguard Worker 
611*a67afe4dSAndroid Build Coastguard Worker static size_t
IDAT_list_size(struct IDAT_list * list,unsigned int length)612*a67afe4dSAndroid Build Coastguard Worker IDAT_list_size(struct IDAT_list *list, unsigned int length)
613*a67afe4dSAndroid Build Coastguard Worker    /* Return the size in bytes of an IDAT_list of the given length. */
614*a67afe4dSAndroid Build Coastguard Worker {
615*a67afe4dSAndroid Build Coastguard Worker    if (list != NULL)
616*a67afe4dSAndroid Build Coastguard Worker       length = list->length;
617*a67afe4dSAndroid Build Coastguard Worker 
618*a67afe4dSAndroid Build Coastguard Worker    return sizeof *list - sizeof list->lengths +
619*a67afe4dSAndroid Build Coastguard Worker       length * sizeof list->lengths[0];
620*a67afe4dSAndroid Build Coastguard Worker }
621*a67afe4dSAndroid Build Coastguard Worker 
622*a67afe4dSAndroid Build Coastguard Worker static void
IDAT_list_end(struct IDAT_list * IDAT_list)623*a67afe4dSAndroid Build Coastguard Worker IDAT_list_end(struct IDAT_list *IDAT_list)
624*a67afe4dSAndroid Build Coastguard Worker {
625*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *list = IDAT_list->next;
626*a67afe4dSAndroid Build Coastguard Worker 
627*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*IDAT_list);
628*a67afe4dSAndroid Build Coastguard Worker 
629*a67afe4dSAndroid Build Coastguard Worker    while (list != NULL)
630*a67afe4dSAndroid Build Coastguard Worker    {
631*a67afe4dSAndroid Build Coastguard Worker       struct IDAT_list *next = list->next;
632*a67afe4dSAndroid Build Coastguard Worker 
633*a67afe4dSAndroid Build Coastguard Worker       clear(list, IDAT_list_size(list, 0));
634*a67afe4dSAndroid Build Coastguard Worker       free(list);
635*a67afe4dSAndroid Build Coastguard Worker       list = next;
636*a67afe4dSAndroid Build Coastguard Worker    }
637*a67afe4dSAndroid Build Coastguard Worker }
638*a67afe4dSAndroid Build Coastguard Worker 
639*a67afe4dSAndroid Build Coastguard Worker static struct IDAT_list *
IDAT_list_extend(struct IDAT_list * tail)640*a67afe4dSAndroid Build Coastguard Worker IDAT_list_extend(struct IDAT_list *tail)
641*a67afe4dSAndroid Build Coastguard Worker {
642*a67afe4dSAndroid Build Coastguard Worker    /* Use the previous cached value if available. */
643*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *next = tail->next;
644*a67afe4dSAndroid Build Coastguard Worker 
645*a67afe4dSAndroid Build Coastguard Worker    if (next == NULL)
646*a67afe4dSAndroid Build Coastguard Worker    {
647*a67afe4dSAndroid Build Coastguard Worker       /* Insert a new, malloc'ed, block of IDAT information buffers, this
648*a67afe4dSAndroid Build Coastguard Worker        * one twice as large as the previous one:
649*a67afe4dSAndroid Build Coastguard Worker        */
650*a67afe4dSAndroid Build Coastguard Worker       unsigned int length = 2 * tail->length;
651*a67afe4dSAndroid Build Coastguard Worker 
652*a67afe4dSAndroid Build Coastguard Worker       if (length < tail->length) /* arithmetic overflow */
653*a67afe4dSAndroid Build Coastguard Worker          length = tail->length;
654*a67afe4dSAndroid Build Coastguard Worker 
655*a67afe4dSAndroid Build Coastguard Worker       next = voidcast(IDAT_list*, malloc(IDAT_list_size(NULL, length)));
656*a67afe4dSAndroid Build Coastguard Worker       CLEAR(*next);
657*a67afe4dSAndroid Build Coastguard Worker 
658*a67afe4dSAndroid Build Coastguard Worker       /* The caller must handle this: */
659*a67afe4dSAndroid Build Coastguard Worker       if (next == NULL)
660*a67afe4dSAndroid Build Coastguard Worker          return NULL;
661*a67afe4dSAndroid Build Coastguard Worker 
662*a67afe4dSAndroid Build Coastguard Worker       next->next = NULL;
663*a67afe4dSAndroid Build Coastguard Worker       next->length = length;
664*a67afe4dSAndroid Build Coastguard Worker       tail->next = next;
665*a67afe4dSAndroid Build Coastguard Worker    }
666*a67afe4dSAndroid Build Coastguard Worker 
667*a67afe4dSAndroid Build Coastguard Worker    return next;
668*a67afe4dSAndroid Build Coastguard Worker }
669*a67afe4dSAndroid Build Coastguard Worker 
670*a67afe4dSAndroid Build Coastguard Worker /* GLOBAL CONTROL STRUCTURE */
671*a67afe4dSAndroid Build Coastguard Worker struct global
672*a67afe4dSAndroid Build Coastguard Worker {
673*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC GLOBAL VARIABLES: OWNER INITIALIZE */
674*a67afe4dSAndroid Build Coastguard Worker    unsigned int   errors        :1; /* print file errors to stderr */
675*a67afe4dSAndroid Build Coastguard Worker    unsigned int   warnings      :1; /* print libpng warnings to stderr */
676*a67afe4dSAndroid Build Coastguard Worker    unsigned int   optimize_zlib :1; /* Run optimization search */
677*a67afe4dSAndroid Build Coastguard Worker    unsigned int   quiet         :2; /* don't output summaries */
678*a67afe4dSAndroid Build Coastguard Worker    unsigned int   verbose       :3; /* various internal tracking */
679*a67afe4dSAndroid Build Coastguard Worker    unsigned int   skip          :3; /* Non-critical chunks to skip */
680*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_NONE      0
681*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_BAD_CRC   1    /* Chunks with a bad CRC */
682*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_UNSAFE    2    /* Chunks not safe to copy */
683*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_UNUSED    3    /* Chunks not used by libpng */
684*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_TRANSFORM 4    /* Chunks only used in transforms */
685*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_COLOR     5    /* Everything but tRNS, sBIT, gAMA and sRGB */
686*a67afe4dSAndroid Build Coastguard Worker #     define SKIP_ALL       6    /* Everything but tRNS and sBIT */
687*a67afe4dSAndroid Build Coastguard Worker 
688*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    idat_max;         /* 0 to perform no re-chunking */
689*a67afe4dSAndroid Build Coastguard Worker 
690*a67afe4dSAndroid Build Coastguard Worker    int            status_code;      /* Accumulated status code */
691*a67afe4dSAndroid Build Coastguard Worker #     define TOO_FAR_BACK   0x01 /* found a too-far-back error */
692*a67afe4dSAndroid Build Coastguard Worker #     define CRC_ERROR      0x02 /* fixed an invalid CRC */
693*a67afe4dSAndroid Build Coastguard Worker #     define STREAM_ERROR   0x04 /* damaged PNG stream (may be fixable) */
694*a67afe4dSAndroid Build Coastguard Worker #     define TRUNCATED      0x08 /* truncated but still readable */
695*a67afe4dSAndroid Build Coastguard Worker #     define FILE_ERROR     0x10 /* could not read the file */
696*a67afe4dSAndroid Build Coastguard Worker #     define WRITE_ERROR    0x20 /* write error (this terminates the read) */
697*a67afe4dSAndroid Build Coastguard Worker #     define INTERNAL_ERROR 0x40 /* internal limits/errors encountered */
698*a67afe4dSAndroid Build Coastguard Worker 
699*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC GLOBAL VARIABLES: USED INTERNALLY BY IDAT READ CODE */
700*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list idat_cache;  /* Cache of file IDAT information buffers */
701*a67afe4dSAndroid Build Coastguard Worker       /* The structure is shared across all uses of this global control
702*a67afe4dSAndroid Build Coastguard Worker        * structure to avoid reallocation between IDAT streams.
703*a67afe4dSAndroid Build Coastguard Worker        */
704*a67afe4dSAndroid Build Coastguard Worker };
705*a67afe4dSAndroid Build Coastguard Worker 
706*a67afe4dSAndroid Build Coastguard Worker static int
global_end(struct global * global)707*a67afe4dSAndroid Build Coastguard Worker global_end(struct global *global)
708*a67afe4dSAndroid Build Coastguard Worker {
709*a67afe4dSAndroid Build Coastguard Worker 
710*a67afe4dSAndroid Build Coastguard Worker    int rc;
711*a67afe4dSAndroid Build Coastguard Worker 
712*a67afe4dSAndroid Build Coastguard Worker    IDAT_list_end(&global->idat_cache);
713*a67afe4dSAndroid Build Coastguard Worker    rc = global->status_code;
714*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*global);
715*a67afe4dSAndroid Build Coastguard Worker    return rc;
716*a67afe4dSAndroid Build Coastguard Worker }
717*a67afe4dSAndroid Build Coastguard Worker 
718*a67afe4dSAndroid Build Coastguard Worker static void
global_init(struct global * global)719*a67afe4dSAndroid Build Coastguard Worker global_init(struct global *global)
720*a67afe4dSAndroid Build Coastguard Worker    /* Call this once (and only once) to initialize the control */
721*a67afe4dSAndroid Build Coastguard Worker {
722*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*global);
723*a67afe4dSAndroid Build Coastguard Worker 
724*a67afe4dSAndroid Build Coastguard Worker    /* Globals */
725*a67afe4dSAndroid Build Coastguard Worker    global->errors        = 0;
726*a67afe4dSAndroid Build Coastguard Worker    global->warnings      = 0;
727*a67afe4dSAndroid Build Coastguard Worker    global->quiet         = 0;
728*a67afe4dSAndroid Build Coastguard Worker    global->verbose       = 0;
729*a67afe4dSAndroid Build Coastguard Worker    global->idat_max      = 0;         /* no re-chunking of IDAT */
730*a67afe4dSAndroid Build Coastguard Worker    global->optimize_zlib = 0;
731*a67afe4dSAndroid Build Coastguard Worker    global->skip          = SKIP_NONE;
732*a67afe4dSAndroid Build Coastguard Worker    global->status_code   = 0;
733*a67afe4dSAndroid Build Coastguard Worker 
734*a67afe4dSAndroid Build Coastguard Worker    IDAT_list_init(&global->idat_cache);
735*a67afe4dSAndroid Build Coastguard Worker }
736*a67afe4dSAndroid Build Coastguard Worker 
737*a67afe4dSAndroid Build Coastguard Worker static int
skip_chunk_type(const struct global * global,png_uint_32 type)738*a67afe4dSAndroid Build Coastguard Worker skip_chunk_type(const struct global *global, png_uint_32 type)
739*a67afe4dSAndroid Build Coastguard Worker    /* Return true if this chunk is to be skipped according to the --strip
740*a67afe4dSAndroid Build Coastguard Worker     * option.  This code needs to recognize all known ancillary chunks in order
741*a67afe4dSAndroid Build Coastguard Worker     * to handle the --strip=unsafe option.
742*a67afe4dSAndroid Build Coastguard Worker     */
743*a67afe4dSAndroid Build Coastguard Worker {
744*a67afe4dSAndroid Build Coastguard Worker    /* Never strip critical chunks: */
745*a67afe4dSAndroid Build Coastguard Worker    if (CRITICAL(type))
746*a67afe4dSAndroid Build Coastguard Worker       return 0;
747*a67afe4dSAndroid Build Coastguard Worker 
748*a67afe4dSAndroid Build Coastguard Worker    switch (type)
749*a67afe4dSAndroid Build Coastguard Worker    {
750*a67afe4dSAndroid Build Coastguard Worker       /* Chunks that are treated as, effectively, critical because they affect
751*a67afe4dSAndroid Build Coastguard Worker        * correct interpretation of the pixel values:
752*a67afe4dSAndroid Build Coastguard Worker        */
753*a67afe4dSAndroid Build Coastguard Worker       case png_tRNS: case png_sBIT:
754*a67afe4dSAndroid Build Coastguard Worker          return 0;
755*a67afe4dSAndroid Build Coastguard Worker 
756*a67afe4dSAndroid Build Coastguard Worker       /* Chunks that specify gamma encoding which should therefore only be
757*a67afe4dSAndroid Build Coastguard Worker        * removed if the user insists:
758*a67afe4dSAndroid Build Coastguard Worker        */
759*a67afe4dSAndroid Build Coastguard Worker       case png_gAMA: case png_sRGB:
760*a67afe4dSAndroid Build Coastguard Worker          if (global->skip >= SKIP_ALL)
761*a67afe4dSAndroid Build Coastguard Worker             return 1;
762*a67afe4dSAndroid Build Coastguard Worker          return 0;
763*a67afe4dSAndroid Build Coastguard Worker 
764*a67afe4dSAndroid Build Coastguard Worker       /* Chunks that affect color interpretation - not used by libpng and rarely
765*a67afe4dSAndroid Build Coastguard Worker        * used by applications, but technically still required for correct
766*a67afe4dSAndroid Build Coastguard Worker        * interpretation of the image data:
767*a67afe4dSAndroid Build Coastguard Worker        */
768*a67afe4dSAndroid Build Coastguard Worker       case png_cHRM: case png_iCCP:
769*a67afe4dSAndroid Build Coastguard Worker          if (global->skip >= SKIP_COLOR)
770*a67afe4dSAndroid Build Coastguard Worker             return 1;
771*a67afe4dSAndroid Build Coastguard Worker          return 0;
772*a67afe4dSAndroid Build Coastguard Worker 
773*a67afe4dSAndroid Build Coastguard Worker       /* Other chunks that are used by libpng in image transformations (as
774*a67afe4dSAndroid Build Coastguard Worker        * opposed to known chunks that have get/set APIs but are not otherwise
775*a67afe4dSAndroid Build Coastguard Worker        * used.)
776*a67afe4dSAndroid Build Coastguard Worker        */
777*a67afe4dSAndroid Build Coastguard Worker       case png_bKGD:
778*a67afe4dSAndroid Build Coastguard Worker          if (global->skip >= SKIP_TRANSFORM)
779*a67afe4dSAndroid Build Coastguard Worker             return 1;
780*a67afe4dSAndroid Build Coastguard Worker          return 0;
781*a67afe4dSAndroid Build Coastguard Worker 
782*a67afe4dSAndroid Build Coastguard Worker       /* All other chunks that libpng knows about and affect neither image
783*a67afe4dSAndroid Build Coastguard Worker        * interpretation nor libpng transforms - chunks that are effectively
784*a67afe4dSAndroid Build Coastguard Worker        * unused by libpng even though libpng might recognize and store them.
785*a67afe4dSAndroid Build Coastguard Worker        */
786*a67afe4dSAndroid Build Coastguard Worker       case png_fRAc: case png_gIFg: case png_gIFt: case png_gIFx: case png_hIST:
787*a67afe4dSAndroid Build Coastguard Worker       case png_iTXt: case png_oFFs: case png_pCAL: case png_pHYs: case png_sCAL:
788*a67afe4dSAndroid Build Coastguard Worker       case png_sPLT: case png_sTER: case png_tEXt: case png_tIME: case png_zTXt:
789*a67afe4dSAndroid Build Coastguard Worker          if (global->skip >= SKIP_UNUSED)
790*a67afe4dSAndroid Build Coastguard Worker             return 1;
791*a67afe4dSAndroid Build Coastguard Worker          return 0;
792*a67afe4dSAndroid Build Coastguard Worker 
793*a67afe4dSAndroid Build Coastguard Worker       /* Chunks that libpng does not know about (notice that this depends on the
794*a67afe4dSAndroid Build Coastguard Worker        * list above including all known chunks!)  The decision here depends on
795*a67afe4dSAndroid Build Coastguard Worker        * whether the safe-to-copy bit is set in the chunk type.
796*a67afe4dSAndroid Build Coastguard Worker        */
797*a67afe4dSAndroid Build Coastguard Worker       default:
798*a67afe4dSAndroid Build Coastguard Worker          if (SAFE_TO_COPY(type))
799*a67afe4dSAndroid Build Coastguard Worker          {
800*a67afe4dSAndroid Build Coastguard Worker             if (global->skip >= SKIP_UNUSED) /* as above */
801*a67afe4dSAndroid Build Coastguard Worker                return 1;
802*a67afe4dSAndroid Build Coastguard Worker          }
803*a67afe4dSAndroid Build Coastguard Worker 
804*a67afe4dSAndroid Build Coastguard Worker          else if (global->skip >= SKIP_UNSAFE)
805*a67afe4dSAndroid Build Coastguard Worker             return 1;
806*a67afe4dSAndroid Build Coastguard Worker 
807*a67afe4dSAndroid Build Coastguard Worker          return 0;
808*a67afe4dSAndroid Build Coastguard Worker    }
809*a67afe4dSAndroid Build Coastguard Worker }
810*a67afe4dSAndroid Build Coastguard Worker 
811*a67afe4dSAndroid Build Coastguard Worker /* PER-FILE CONTROL STRUCTURE */
812*a67afe4dSAndroid Build Coastguard Worker struct chunk;
813*a67afe4dSAndroid Build Coastguard Worker struct IDAT;
814*a67afe4dSAndroid Build Coastguard Worker struct file
815*a67afe4dSAndroid Build Coastguard Worker {
816*a67afe4dSAndroid Build Coastguard Worker    /* ANCESTORS */
817*a67afe4dSAndroid Build Coastguard Worker    struct global *global;
818*a67afe4dSAndroid Build Coastguard Worker 
819*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC PER-FILE VARIABLES: CALLER INITIALIZE */
820*a67afe4dSAndroid Build Coastguard Worker    const char *   file_name;
821*a67afe4dSAndroid Build Coastguard Worker    const char *   out_name;      /* Name of output file (if required) */
822*a67afe4dSAndroid Build Coastguard Worker 
823*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC PER-FILE VARIABLES: SET BY PNG READ CODE */
824*a67afe4dSAndroid Build Coastguard Worker    /* File specific result codes */
825*a67afe4dSAndroid Build Coastguard Worker    int            status_code;   /* Set to a bit mask of the following: */
826*a67afe4dSAndroid Build Coastguard Worker    int            read_errno;    /* Records a read error errno */
827*a67afe4dSAndroid Build Coastguard Worker    int            write_errno;   /* Records a write error errno */
828*a67afe4dSAndroid Build Coastguard Worker 
829*a67afe4dSAndroid Build Coastguard Worker    /* IHDR information */
830*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    width;
831*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    height;
832*a67afe4dSAndroid Build Coastguard Worker    png_byte       bit_depth;
833*a67afe4dSAndroid Build Coastguard Worker    png_byte       color_type;
834*a67afe4dSAndroid Build Coastguard Worker    png_byte       compression_method;
835*a67afe4dSAndroid Build Coastguard Worker    png_byte       filter_method;
836*a67afe4dSAndroid Build Coastguard Worker    png_byte       interlace_method;
837*a67afe4dSAndroid Build Coastguard Worker 
838*a67afe4dSAndroid Build Coastguard Worker    udigit         image_bytes[5];
839*a67afe4dSAndroid Build Coastguard Worker    int            image_digits;
840*a67afe4dSAndroid Build Coastguard Worker 
841*a67afe4dSAndroid Build Coastguard Worker    /* PROTECTED PER-FILE VARIABLES: USED BY THE READ CODE */
842*a67afe4dSAndroid Build Coastguard Worker    FILE *         file;          /* Original PNG file */
843*a67afe4dSAndroid Build Coastguard Worker    FILE *         out;           /* If a new one is being written */
844*a67afe4dSAndroid Build Coastguard Worker    jmp_buf        jmpbuf;        /* Set while reading a PNG */
845*a67afe4dSAndroid Build Coastguard Worker 
846*a67afe4dSAndroid Build Coastguard Worker    /* PROTECTED CHUNK SPECIFIC VARIABLES: USED BY CHUNK CODE */
847*a67afe4dSAndroid Build Coastguard Worker    /* The following variables are used during reading to record the length, type
848*a67afe4dSAndroid Build Coastguard Worker     * and data position of the *next* chunk or, right at the start, the
849*a67afe4dSAndroid Build Coastguard Worker     * signature (in length,type).
850*a67afe4dSAndroid Build Coastguard Worker     *
851*a67afe4dSAndroid Build Coastguard Worker     * When a chunk control structure is instantiated these values are copied
852*a67afe4dSAndroid Build Coastguard Worker     * into the structure and can then be overwritten with the data for the next
853*a67afe4dSAndroid Build Coastguard Worker     * chunk.
854*a67afe4dSAndroid Build Coastguard Worker     */
855*a67afe4dSAndroid Build Coastguard Worker    fpos_t         data_pos;      /* Position of first byte of chunk data */
856*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    length;        /* First word (length or signature start) */
857*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    type;          /* Second word (type or signature end) */
858*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    crc;           /* Running chunk CRC (used by read_chunk) */
859*a67afe4dSAndroid Build Coastguard Worker 
860*a67afe4dSAndroid Build Coastguard Worker    /* These counts are maintained by the read and write routines below and are
861*a67afe4dSAndroid Build Coastguard Worker     * reset by the chunk handling code.  They record the total number of bytes
862*a67afe4dSAndroid Build Coastguard Worker     * read or written for the chunk, including the header (length,type) bytes.
863*a67afe4dSAndroid Build Coastguard Worker     */
864*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    read_count;    /* Count of bytes read (in the chunk) */
865*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    write_count;   /* Count of bytes written (in the chunk) */
866*a67afe4dSAndroid Build Coastguard Worker    int            state;         /* As defined here: */
867*a67afe4dSAndroid Build Coastguard Worker #     define STATE_SIGNATURE  0  /* The signature is being written */
868*a67afe4dSAndroid Build Coastguard Worker #     define STATE_CHUNKS     1  /* Non-IDAT chunks are being written */
869*a67afe4dSAndroid Build Coastguard Worker #     define STATE_IDAT       2  /* An IDAT stream is being written */
870*a67afe4dSAndroid Build Coastguard Worker 
871*a67afe4dSAndroid Build Coastguard Worker    /* Two pointers used to enable clean-up in the event of fatal errors and to
872*a67afe4dSAndroid Build Coastguard Worker     * hold state about the parser process (only one of each at present.)
873*a67afe4dSAndroid Build Coastguard Worker     */
874*a67afe4dSAndroid Build Coastguard Worker    struct chunk * chunk;
875*a67afe4dSAndroid Build Coastguard Worker    struct IDAT *  idat;
876*a67afe4dSAndroid Build Coastguard Worker 
877*a67afe4dSAndroid Build Coastguard Worker    /* Interface to allocate a new chunk or IDAT control structure.  The result
878*a67afe4dSAndroid Build Coastguard Worker     * is returned by setting one or other of the above variables.  Note that the
879*a67afe4dSAndroid Build Coastguard Worker     * relevant initializer is called by the allocator function.  The alloc_ptr
880*a67afe4dSAndroid Build Coastguard Worker     * is used only by the implementation of the allocate function.
881*a67afe4dSAndroid Build Coastguard Worker     */
882*a67afe4dSAndroid Build Coastguard Worker    void *         alloc_ptr;
883*a67afe4dSAndroid Build Coastguard Worker    void         (*alloc)(struct file*,int idat);
884*a67afe4dSAndroid Build Coastguard Worker                                   /* idat: allocate IDAT not chunk */
885*a67afe4dSAndroid Build Coastguard Worker };
886*a67afe4dSAndroid Build Coastguard Worker 
887*a67afe4dSAndroid Build Coastguard Worker /* Valid longjmp (stop) codes are: */
888*a67afe4dSAndroid Build Coastguard Worker #define LIBPNG_WARNING_CODE   1 /* generic png_error */
889*a67afe4dSAndroid Build Coastguard Worker #define LIBPNG_ERROR_CODE     2 /* generic png_error */
890*a67afe4dSAndroid Build Coastguard Worker #define ZLIB_ERROR_CODE       3 /* generic zlib error */
891*a67afe4dSAndroid Build Coastguard Worker #define INVALID_ERROR_CODE    4 /* detected an invalid PNG */
892*a67afe4dSAndroid Build Coastguard Worker #define READ_ERROR_CODE       5 /* read failed */
893*a67afe4dSAndroid Build Coastguard Worker #define WRITE_ERROR_CODE      6 /* error in write */
894*a67afe4dSAndroid Build Coastguard Worker #define UNEXPECTED_ERROR_CODE 7 /* unexpected (internal?) error */
895*a67afe4dSAndroid Build Coastguard Worker 
896*a67afe4dSAndroid Build Coastguard Worker static void
emit_string(const char * str,FILE * out)897*a67afe4dSAndroid Build Coastguard Worker emit_string(const char *str, FILE *out)
898*a67afe4dSAndroid Build Coastguard Worker    /* Print a string with spaces replaced by '_' and non-printing characters by
899*a67afe4dSAndroid Build Coastguard Worker     * an octal escape.
900*a67afe4dSAndroid Build Coastguard Worker     */
901*a67afe4dSAndroid Build Coastguard Worker {
902*a67afe4dSAndroid Build Coastguard Worker    for (; *str; ++str)
903*a67afe4dSAndroid Build Coastguard Worker       if (isgraph(UCHAR_MAX & *str))
904*a67afe4dSAndroid Build Coastguard Worker          putc(*str, out);
905*a67afe4dSAndroid Build Coastguard Worker 
906*a67afe4dSAndroid Build Coastguard Worker       else if (isspace(UCHAR_MAX & *str))
907*a67afe4dSAndroid Build Coastguard Worker          putc('_', out);
908*a67afe4dSAndroid Build Coastguard Worker 
909*a67afe4dSAndroid Build Coastguard Worker       else
910*a67afe4dSAndroid Build Coastguard Worker          fprintf(out, "\\%.3o", *str);
911*a67afe4dSAndroid Build Coastguard Worker }
912*a67afe4dSAndroid Build Coastguard Worker 
913*a67afe4dSAndroid Build Coastguard Worker static const char *
strcode(int code)914*a67afe4dSAndroid Build Coastguard Worker strcode(int code)
915*a67afe4dSAndroid Build Coastguard Worker {
916*a67afe4dSAndroid Build Coastguard Worker    switch (code)
917*a67afe4dSAndroid Build Coastguard Worker    {
918*a67afe4dSAndroid Build Coastguard Worker       case LIBPNG_WARNING_CODE:   return "warning";
919*a67afe4dSAndroid Build Coastguard Worker       case LIBPNG_ERROR_CODE:     return "libpng";
920*a67afe4dSAndroid Build Coastguard Worker       case ZLIB_ERROR_CODE:       return "zlib";
921*a67afe4dSAndroid Build Coastguard Worker       case INVALID_ERROR_CODE:    return "invalid";
922*a67afe4dSAndroid Build Coastguard Worker       case READ_ERROR_CODE:       return "read";
923*a67afe4dSAndroid Build Coastguard Worker       case WRITE_ERROR_CODE:      return "write";
924*a67afe4dSAndroid Build Coastguard Worker       case UNEXPECTED_ERROR_CODE: return "unexpected";
925*a67afe4dSAndroid Build Coastguard Worker       default:                    return "INVALID";
926*a67afe4dSAndroid Build Coastguard Worker    }
927*a67afe4dSAndroid Build Coastguard Worker }
928*a67afe4dSAndroid Build Coastguard Worker 
929*a67afe4dSAndroid Build Coastguard Worker static void
emit_error(struct file * file,int code,const char * what)930*a67afe4dSAndroid Build Coastguard Worker emit_error(struct file *file, int code, const char *what)
931*a67afe4dSAndroid Build Coastguard Worker    /* Generic error message routine, takes a 'stop' code but can be used
932*a67afe4dSAndroid Build Coastguard Worker     * elsewhere.  Always outputs a message.
933*a67afe4dSAndroid Build Coastguard Worker     */
934*a67afe4dSAndroid Build Coastguard Worker {
935*a67afe4dSAndroid Build Coastguard Worker    const char *reason;
936*a67afe4dSAndroid Build Coastguard Worker    int err = 0;
937*a67afe4dSAndroid Build Coastguard Worker 
938*a67afe4dSAndroid Build Coastguard Worker    switch (code)
939*a67afe4dSAndroid Build Coastguard Worker    {
940*a67afe4dSAndroid Build Coastguard Worker       case LIBPNG_WARNING_CODE:   reason = "libpng warning:"; break;
941*a67afe4dSAndroid Build Coastguard Worker       case LIBPNG_ERROR_CODE:     reason = "libpng error:"; break;
942*a67afe4dSAndroid Build Coastguard Worker       case ZLIB_ERROR_CODE:       reason = "zlib error:"; break;
943*a67afe4dSAndroid Build Coastguard Worker       case INVALID_ERROR_CODE:    reason = "invalid"; break;
944*a67afe4dSAndroid Build Coastguard Worker       case READ_ERROR_CODE:       reason = "read failure:";
945*a67afe4dSAndroid Build Coastguard Worker                                   err = file->read_errno;
946*a67afe4dSAndroid Build Coastguard Worker                                   break;
947*a67afe4dSAndroid Build Coastguard Worker       case WRITE_ERROR_CODE:      reason = "write error";
948*a67afe4dSAndroid Build Coastguard Worker                                   err = file->write_errno;
949*a67afe4dSAndroid Build Coastguard Worker                                   break;
950*a67afe4dSAndroid Build Coastguard Worker       case UNEXPECTED_ERROR_CODE: reason = "unexpected error:";
951*a67afe4dSAndroid Build Coastguard Worker                                   err = file->read_errno;
952*a67afe4dSAndroid Build Coastguard Worker                                   if (err == 0)
953*a67afe4dSAndroid Build Coastguard Worker                                      err = file->write_errno;
954*a67afe4dSAndroid Build Coastguard Worker                                   break;
955*a67afe4dSAndroid Build Coastguard Worker       default:                    reason = "INVALID (internal error):"; break;
956*a67afe4dSAndroid Build Coastguard Worker    }
957*a67afe4dSAndroid Build Coastguard Worker 
958*a67afe4dSAndroid Build Coastguard Worker    if (err != 0)
959*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, "%s: %s %s [%s]\n", file->file_name, reason, what,
960*a67afe4dSAndroid Build Coastguard Worker          strerror(err));
961*a67afe4dSAndroid Build Coastguard Worker 
962*a67afe4dSAndroid Build Coastguard Worker    else
963*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, "%s: %s %s\n", file->file_name, reason, what);
964*a67afe4dSAndroid Build Coastguard Worker }
965*a67afe4dSAndroid Build Coastguard Worker 
966*a67afe4dSAndroid Build Coastguard Worker static void chunk_end(struct chunk **);
967*a67afe4dSAndroid Build Coastguard Worker static void IDAT_end(struct IDAT **);
968*a67afe4dSAndroid Build Coastguard Worker 
969*a67afe4dSAndroid Build Coastguard Worker static int
file_end(struct file * file)970*a67afe4dSAndroid Build Coastguard Worker file_end(struct file *file)
971*a67afe4dSAndroid Build Coastguard Worker {
972*a67afe4dSAndroid Build Coastguard Worker    int rc;
973*a67afe4dSAndroid Build Coastguard Worker 
974*a67afe4dSAndroid Build Coastguard Worker    /* If either of the chunk pointers are set end them here, the IDAT structure
975*a67afe4dSAndroid Build Coastguard Worker     * must be deallocated first as it may deallocate the chunk structure.
976*a67afe4dSAndroid Build Coastguard Worker     */
977*a67afe4dSAndroid Build Coastguard Worker    if (file->idat != NULL)
978*a67afe4dSAndroid Build Coastguard Worker       IDAT_end(&file->idat);
979*a67afe4dSAndroid Build Coastguard Worker 
980*a67afe4dSAndroid Build Coastguard Worker    if (file->chunk != NULL)
981*a67afe4dSAndroid Build Coastguard Worker       chunk_end(&file->chunk);
982*a67afe4dSAndroid Build Coastguard Worker 
983*a67afe4dSAndroid Build Coastguard Worker    rc = file->status_code;
984*a67afe4dSAndroid Build Coastguard Worker 
985*a67afe4dSAndroid Build Coastguard Worker    if (file->file != NULL)
986*a67afe4dSAndroid Build Coastguard Worker       (void)fclose(file->file);
987*a67afe4dSAndroid Build Coastguard Worker 
988*a67afe4dSAndroid Build Coastguard Worker    if (file->out != NULL)
989*a67afe4dSAndroid Build Coastguard Worker    {
990*a67afe4dSAndroid Build Coastguard Worker       /* On some systems 'fclose' deletes the FILE struct (making it
991*a67afe4dSAndroid Build Coastguard Worker        * inaccessbile).  There is no guarantee that fclose returns an error
992*a67afe4dSAndroid Build Coastguard Worker        * code from fflush or, indeed, from the FILE error indicator.  There is
993*a67afe4dSAndroid Build Coastguard Worker        * also no explicit (or clear) guarantee in the standard that anything
994*a67afe4dSAndroid Build Coastguard Worker        * other than a read or write operation sets the error indicator; fflush
995*a67afe4dSAndroid Build Coastguard Worker        * is not a read or write operation, so both conditions must be checked
996*a67afe4dSAndroid Build Coastguard Worker        * to ensure the close succeeded and in ANSI-C conformant code they must
997*a67afe4dSAndroid Build Coastguard Worker        * be checked before the fclose call.
998*a67afe4dSAndroid Build Coastguard Worker        */
999*a67afe4dSAndroid Build Coastguard Worker       const int err = fflush(file->out) || ferror(file->out);
1000*a67afe4dSAndroid Build Coastguard Worker 
1001*a67afe4dSAndroid Build Coastguard Worker       if (fclose(file->out) || err)
1002*a67afe4dSAndroid Build Coastguard Worker       {
1003*a67afe4dSAndroid Build Coastguard Worker          perror(file->out_name);
1004*a67afe4dSAndroid Build Coastguard Worker          emit_error(file, READ_ERROR_CODE, "output write error");
1005*a67afe4dSAndroid Build Coastguard Worker          rc |= WRITE_ERROR;
1006*a67afe4dSAndroid Build Coastguard Worker       }
1007*a67afe4dSAndroid Build Coastguard Worker    }
1008*a67afe4dSAndroid Build Coastguard Worker 
1009*a67afe4dSAndroid Build Coastguard Worker    /* Accumulate the result codes */
1010*a67afe4dSAndroid Build Coastguard Worker    file->global->status_code |= rc;
1011*a67afe4dSAndroid Build Coastguard Worker 
1012*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*file);
1013*a67afe4dSAndroid Build Coastguard Worker 
1014*a67afe4dSAndroid Build Coastguard Worker    return rc; /* status code: non-zero on read or write error */
1015*a67afe4dSAndroid Build Coastguard Worker }
1016*a67afe4dSAndroid Build Coastguard Worker 
1017*a67afe4dSAndroid Build Coastguard Worker static int
file_init(struct file * file,struct global * global,const char * file_name,const char * out_name,void * alloc_ptr,void (* alloc)(struct file *,int))1018*a67afe4dSAndroid Build Coastguard Worker file_init(struct file *file, struct global *global, const char *file_name,
1019*a67afe4dSAndroid Build Coastguard Worker    const char *out_name, void *alloc_ptr, void (*alloc)(struct file*,int))
1020*a67afe4dSAndroid Build Coastguard Worker    /* Initialize a file control structure.  This will open the given files as
1021*a67afe4dSAndroid Build Coastguard Worker     * well.  The status code returned is 0 on success, non zero (using the flags
1022*a67afe4dSAndroid Build Coastguard Worker     * above) on a file open error.
1023*a67afe4dSAndroid Build Coastguard Worker     */
1024*a67afe4dSAndroid Build Coastguard Worker {
1025*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*file);
1026*a67afe4dSAndroid Build Coastguard Worker    file->global = global;
1027*a67afe4dSAndroid Build Coastguard Worker 
1028*a67afe4dSAndroid Build Coastguard Worker    file->file_name = file_name;
1029*a67afe4dSAndroid Build Coastguard Worker    file->out_name = out_name;
1030*a67afe4dSAndroid Build Coastguard Worker    file->status_code = 0;
1031*a67afe4dSAndroid Build Coastguard Worker    file->read_errno = 0;
1032*a67afe4dSAndroid Build Coastguard Worker    file->write_errno = 0;
1033*a67afe4dSAndroid Build Coastguard Worker 
1034*a67afe4dSAndroid Build Coastguard Worker    file->file = NULL;
1035*a67afe4dSAndroid Build Coastguard Worker    file->out = NULL;
1036*a67afe4dSAndroid Build Coastguard Worker    /* jmpbuf is garbage: must be set by read_png */
1037*a67afe4dSAndroid Build Coastguard Worker 
1038*a67afe4dSAndroid Build Coastguard Worker    file->read_count = 0;
1039*a67afe4dSAndroid Build Coastguard Worker    file->state = STATE_SIGNATURE;
1040*a67afe4dSAndroid Build Coastguard Worker 
1041*a67afe4dSAndroid Build Coastguard Worker    file->chunk = NULL;
1042*a67afe4dSAndroid Build Coastguard Worker    file->idat = NULL;
1043*a67afe4dSAndroid Build Coastguard Worker 
1044*a67afe4dSAndroid Build Coastguard Worker    file->alloc_ptr = alloc_ptr;
1045*a67afe4dSAndroid Build Coastguard Worker    file->alloc = alloc;
1046*a67afe4dSAndroid Build Coastguard Worker 
1047*a67afe4dSAndroid Build Coastguard Worker    /* Open the files: */
1048*a67afe4dSAndroid Build Coastguard Worker    assert(file_name != NULL);
1049*a67afe4dSAndroid Build Coastguard Worker    file->file = fopen(file_name, "rb");
1050*a67afe4dSAndroid Build Coastguard Worker 
1051*a67afe4dSAndroid Build Coastguard Worker    if (file->file == NULL)
1052*a67afe4dSAndroid Build Coastguard Worker    {
1053*a67afe4dSAndroid Build Coastguard Worker       file->read_errno = errno;
1054*a67afe4dSAndroid Build Coastguard Worker       file->status_code |= FILE_ERROR;
1055*a67afe4dSAndroid Build Coastguard Worker       /* Always output: please give a readable file! */
1056*a67afe4dSAndroid Build Coastguard Worker       perror(file_name);
1057*a67afe4dSAndroid Build Coastguard Worker       return FILE_ERROR;
1058*a67afe4dSAndroid Build Coastguard Worker    }
1059*a67afe4dSAndroid Build Coastguard Worker 
1060*a67afe4dSAndroid Build Coastguard Worker    if (out_name != NULL)
1061*a67afe4dSAndroid Build Coastguard Worker    {
1062*a67afe4dSAndroid Build Coastguard Worker       file->out = fopen(out_name, "wb");
1063*a67afe4dSAndroid Build Coastguard Worker 
1064*a67afe4dSAndroid Build Coastguard Worker       if (file->out == NULL)
1065*a67afe4dSAndroid Build Coastguard Worker       {
1066*a67afe4dSAndroid Build Coastguard Worker          file->write_errno = errno;
1067*a67afe4dSAndroid Build Coastguard Worker          file->status_code |= WRITE_ERROR;
1068*a67afe4dSAndroid Build Coastguard Worker          perror(out_name);
1069*a67afe4dSAndroid Build Coastguard Worker          return WRITE_ERROR;
1070*a67afe4dSAndroid Build Coastguard Worker       }
1071*a67afe4dSAndroid Build Coastguard Worker    }
1072*a67afe4dSAndroid Build Coastguard Worker 
1073*a67afe4dSAndroid Build Coastguard Worker    return 0;
1074*a67afe4dSAndroid Build Coastguard Worker }
1075*a67afe4dSAndroid Build Coastguard Worker 
1076*a67afe4dSAndroid Build Coastguard Worker static void
log_error(struct file * file,int code,const char * what)1077*a67afe4dSAndroid Build Coastguard Worker log_error(struct file *file, int code, const char *what)
1078*a67afe4dSAndroid Build Coastguard Worker    /* Like emit_error but checks the global 'errors' flag */
1079*a67afe4dSAndroid Build Coastguard Worker {
1080*a67afe4dSAndroid Build Coastguard Worker    if (file->global->errors)
1081*a67afe4dSAndroid Build Coastguard Worker       emit_error(file, code, what);
1082*a67afe4dSAndroid Build Coastguard Worker }
1083*a67afe4dSAndroid Build Coastguard Worker 
1084*a67afe4dSAndroid Build Coastguard Worker static char
type_char(png_uint_32 v)1085*a67afe4dSAndroid Build Coastguard Worker type_char(png_uint_32 v)
1086*a67afe4dSAndroid Build Coastguard Worker {
1087*a67afe4dSAndroid Build Coastguard Worker    /* In fact because chunk::chunk_type is validated prior to any call to this
1088*a67afe4dSAndroid Build Coastguard Worker     * function it will always return a-zA-Z, but the extra codes are just there
1089*a67afe4dSAndroid Build Coastguard Worker     * to help in finding internal (programming) errors.  Note that the code only
1090*a67afe4dSAndroid Build Coastguard Worker     * ever considers the low 7 bits of the value (so it is not necessary for the
1091*a67afe4dSAndroid Build Coastguard Worker     * type_name function to mask of the byte.)
1092*a67afe4dSAndroid Build Coastguard Worker     */
1093*a67afe4dSAndroid Build Coastguard Worker    if (v & 32)
1094*a67afe4dSAndroid Build Coastguard Worker       return "!abcdefghijklmnopqrstuvwxyz56789"[(v-96)&31];
1095*a67afe4dSAndroid Build Coastguard Worker 
1096*a67afe4dSAndroid Build Coastguard Worker    else
1097*a67afe4dSAndroid Build Coastguard Worker       return "@ABCDEFGHIJKLMNOPQRSTUVWXYZ01234"[(v-64)&31];
1098*a67afe4dSAndroid Build Coastguard Worker }
1099*a67afe4dSAndroid Build Coastguard Worker 
1100*a67afe4dSAndroid Build Coastguard Worker static void
type_name(png_uint_32 type,FILE * out)1101*a67afe4dSAndroid Build Coastguard Worker type_name(png_uint_32 type, FILE *out)
1102*a67afe4dSAndroid Build Coastguard Worker {
1103*a67afe4dSAndroid Build Coastguard Worker    putc(type_char(type >> 24), out);
1104*a67afe4dSAndroid Build Coastguard Worker    putc(type_char(type >> 16), out);
1105*a67afe4dSAndroid Build Coastguard Worker    putc(type_char(type >>  8), out);
1106*a67afe4dSAndroid Build Coastguard Worker    putc(type_char(type      ), out);
1107*a67afe4dSAndroid Build Coastguard Worker }
1108*a67afe4dSAndroid Build Coastguard Worker 
1109*a67afe4dSAndroid Build Coastguard Worker static void
type_sep(FILE * out)1110*a67afe4dSAndroid Build Coastguard Worker type_sep(FILE *out)
1111*a67afe4dSAndroid Build Coastguard Worker {
1112*a67afe4dSAndroid Build Coastguard Worker    putc(':', out);
1113*a67afe4dSAndroid Build Coastguard Worker    putc(' ', out);
1114*a67afe4dSAndroid Build Coastguard Worker }
1115*a67afe4dSAndroid Build Coastguard Worker 
1116*a67afe4dSAndroid Build Coastguard Worker static png_uint_32 current_type(struct file *file, int code);
1117*a67afe4dSAndroid Build Coastguard Worker 
1118*a67afe4dSAndroid Build Coastguard Worker PNG_NORETURN static void
stop(struct file * file,int code,const char * what)1119*a67afe4dSAndroid Build Coastguard Worker stop(struct file *file, int code, const char *what)
1120*a67afe4dSAndroid Build Coastguard Worker    /* Return control when a PNG file cannot be read. This outputs an 'ERR'
1121*a67afe4dSAndroid Build Coastguard Worker     * summary line too.
1122*a67afe4dSAndroid Build Coastguard Worker     */
1123*a67afe4dSAndroid Build Coastguard Worker {
1124*a67afe4dSAndroid Build Coastguard Worker    log_error(file, code, what);
1125*a67afe4dSAndroid Build Coastguard Worker 
1126*a67afe4dSAndroid Build Coastguard Worker    /* The chunk being read is typically identified by file->chunk or, if this is
1127*a67afe4dSAndroid Build Coastguard Worker     * NULL, by file->type.  This may be wrong if libpng reads ahead, but this
1128*a67afe4dSAndroid Build Coastguard Worker     * only happens with IDAT where libpng reads the header then jumps around
1129*a67afe4dSAndroid Build Coastguard Worker     * finding errors in the previous chunks.  We know that is happening because
1130*a67afe4dSAndroid Build Coastguard Worker     * we are at the start of the IDAT (i.e. no IDAT data has yet been written.)
1131*a67afe4dSAndroid Build Coastguard Worker     *
1132*a67afe4dSAndroid Build Coastguard Worker     * SUMMARY FORMAT (stop):
1133*a67afe4dSAndroid Build Coastguard Worker     *
1134*a67afe4dSAndroid Build Coastguard Worker     * IDAT ERR status code read-errno write-errno message file
1135*a67afe4dSAndroid Build Coastguard Worker     *
1136*a67afe4dSAndroid Build Coastguard Worker     * 'uncompressed' will be 0 if there was a problem in the IHDR.  The errno
1137*a67afe4dSAndroid Build Coastguard Worker     * values are emit_string(strerror(errno)).
1138*a67afe4dSAndroid Build Coastguard Worker     */
1139*a67afe4dSAndroid Build Coastguard Worker    if (file->global->quiet < 2) /* need two quiets to stop this. */
1140*a67afe4dSAndroid Build Coastguard Worker    {
1141*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 type;
1142*a67afe4dSAndroid Build Coastguard Worker 
1143*a67afe4dSAndroid Build Coastguard Worker       if (file->chunk != NULL)
1144*a67afe4dSAndroid Build Coastguard Worker          type = current_type(file, code); /* Gropes in struct chunk and IDAT */
1145*a67afe4dSAndroid Build Coastguard Worker 
1146*a67afe4dSAndroid Build Coastguard Worker       else
1147*a67afe4dSAndroid Build Coastguard Worker          type = file->type;
1148*a67afe4dSAndroid Build Coastguard Worker 
1149*a67afe4dSAndroid Build Coastguard Worker       if (type)
1150*a67afe4dSAndroid Build Coastguard Worker          type_name(type, stdout);
1151*a67afe4dSAndroid Build Coastguard Worker 
1152*a67afe4dSAndroid Build Coastguard Worker       else /* magic: an IDAT header, produces bogons for too many IDATs */
1153*a67afe4dSAndroid Build Coastguard Worker          fputs("HEAD", stdout); /* not a registered chunk! */
1154*a67afe4dSAndroid Build Coastguard Worker 
1155*a67afe4dSAndroid Build Coastguard Worker       printf(" ERR %.2x %s ", file->status_code, strcode(code));
1156*a67afe4dSAndroid Build Coastguard Worker       /* This only works one strerror at a time, because of the way strerror is
1157*a67afe4dSAndroid Build Coastguard Worker        * implemented.
1158*a67afe4dSAndroid Build Coastguard Worker        */
1159*a67afe4dSAndroid Build Coastguard Worker       emit_string(strerror(file->read_errno), stdout);
1160*a67afe4dSAndroid Build Coastguard Worker       putc(' ', stdout);
1161*a67afe4dSAndroid Build Coastguard Worker       emit_string(strerror(file->write_errno), stdout);
1162*a67afe4dSAndroid Build Coastguard Worker       putc(' ', stdout);
1163*a67afe4dSAndroid Build Coastguard Worker       emit_string(what, stdout);
1164*a67afe4dSAndroid Build Coastguard Worker       putc(' ', stdout);
1165*a67afe4dSAndroid Build Coastguard Worker       fputs(file->file_name, stdout);
1166*a67afe4dSAndroid Build Coastguard Worker       putc('\n', stdout);
1167*a67afe4dSAndroid Build Coastguard Worker    }
1168*a67afe4dSAndroid Build Coastguard Worker 
1169*a67afe4dSAndroid Build Coastguard Worker    file->status_code |= FILE_ERROR;
1170*a67afe4dSAndroid Build Coastguard Worker    longjmp(file->jmpbuf, code);
1171*a67afe4dSAndroid Build Coastguard Worker }
1172*a67afe4dSAndroid Build Coastguard Worker 
1173*a67afe4dSAndroid Build Coastguard Worker PNG_NORETURN static void
stop_invalid(struct file * file,const char * what)1174*a67afe4dSAndroid Build Coastguard Worker stop_invalid(struct file *file, const char *what)
1175*a67afe4dSAndroid Build Coastguard Worker {
1176*a67afe4dSAndroid Build Coastguard Worker    stop(file, INVALID_ERROR_CODE, what);
1177*a67afe4dSAndroid Build Coastguard Worker }
1178*a67afe4dSAndroid Build Coastguard Worker 
1179*a67afe4dSAndroid Build Coastguard Worker static void
type_message(struct file * file,png_uint_32 type,const char * what)1180*a67afe4dSAndroid Build Coastguard Worker type_message(struct file *file, png_uint_32 type, const char *what)
1181*a67afe4dSAndroid Build Coastguard Worker    /* Error message for a chunk; the chunk name comes from 'type' */
1182*a67afe4dSAndroid Build Coastguard Worker {
1183*a67afe4dSAndroid Build Coastguard Worker    if (file->global->errors)
1184*a67afe4dSAndroid Build Coastguard Worker    {
1185*a67afe4dSAndroid Build Coastguard Worker       fputs(file->file_name, stderr);
1186*a67afe4dSAndroid Build Coastguard Worker       type_sep(stderr);
1187*a67afe4dSAndroid Build Coastguard Worker       type_name(type, stderr);
1188*a67afe4dSAndroid Build Coastguard Worker       type_sep(stderr);
1189*a67afe4dSAndroid Build Coastguard Worker       fputs(what, stderr);
1190*a67afe4dSAndroid Build Coastguard Worker       putc('\n', stderr);
1191*a67afe4dSAndroid Build Coastguard Worker    }
1192*a67afe4dSAndroid Build Coastguard Worker }
1193*a67afe4dSAndroid Build Coastguard Worker 
1194*a67afe4dSAndroid Build Coastguard Worker /* Input file positioning - we jump around in the input file while reading
1195*a67afe4dSAndroid Build Coastguard Worker  * stuff, these wrappers deal with the error handling.
1196*a67afe4dSAndroid Build Coastguard Worker  */
1197*a67afe4dSAndroid Build Coastguard Worker static void
file_getpos(struct file * file,fpos_t * pos)1198*a67afe4dSAndroid Build Coastguard Worker file_getpos(struct file *file, fpos_t *pos)
1199*a67afe4dSAndroid Build Coastguard Worker {
1200*a67afe4dSAndroid Build Coastguard Worker    if (fgetpos(file->file, pos))
1201*a67afe4dSAndroid Build Coastguard Worker    {
1202*a67afe4dSAndroid Build Coastguard Worker       /* This is unexpected, so perror it */
1203*a67afe4dSAndroid Build Coastguard Worker       perror(file->file_name);
1204*a67afe4dSAndroid Build Coastguard Worker       stop(file, READ_ERROR_CODE, "fgetpos");
1205*a67afe4dSAndroid Build Coastguard Worker    }
1206*a67afe4dSAndroid Build Coastguard Worker }
1207*a67afe4dSAndroid Build Coastguard Worker 
1208*a67afe4dSAndroid Build Coastguard Worker static void
file_setpos(struct file * file,const fpos_t * pos)1209*a67afe4dSAndroid Build Coastguard Worker file_setpos(struct file *file, const fpos_t *pos)
1210*a67afe4dSAndroid Build Coastguard Worker {
1211*a67afe4dSAndroid Build Coastguard Worker    if (fsetpos(file->file, pos))
1212*a67afe4dSAndroid Build Coastguard Worker    {
1213*a67afe4dSAndroid Build Coastguard Worker       perror(file->file_name);
1214*a67afe4dSAndroid Build Coastguard Worker       stop(file, READ_ERROR_CODE, "fsetpos");
1215*a67afe4dSAndroid Build Coastguard Worker    }
1216*a67afe4dSAndroid Build Coastguard Worker }
1217*a67afe4dSAndroid Build Coastguard Worker 
1218*a67afe4dSAndroid Build Coastguard Worker static void
getpos(struct file * file)1219*a67afe4dSAndroid Build Coastguard Worker getpos(struct file *file)
1220*a67afe4dSAndroid Build Coastguard Worker    /* Get the current position and store it in 'data_pos'.  The corresponding
1221*a67afe4dSAndroid Build Coastguard Worker     * setpos() function is chunk specific because it uses the copy of the
1222*a67afe4dSAndroid Build Coastguard Worker     * position for the specific chunk.
1223*a67afe4dSAndroid Build Coastguard Worker     */
1224*a67afe4dSAndroid Build Coastguard Worker {
1225*a67afe4dSAndroid Build Coastguard Worker    file_getpos(file, &file->data_pos);
1226*a67afe4dSAndroid Build Coastguard Worker }
1227*a67afe4dSAndroid Build Coastguard Worker 
1228*a67afe4dSAndroid Build Coastguard Worker 
1229*a67afe4dSAndroid Build Coastguard Worker /* Read utility - read a single byte, returns a value in the range 0..255 or EOF
1230*a67afe4dSAndroid Build Coastguard Worker  * on a read error.  In the latter case status_code and read_errno are updated
1231*a67afe4dSAndroid Build Coastguard Worker  * appropriately.
1232*a67afe4dSAndroid Build Coastguard Worker  */
1233*a67afe4dSAndroid Build Coastguard Worker static int
read_byte(struct file * file)1234*a67afe4dSAndroid Build Coastguard Worker read_byte(struct file *file)
1235*a67afe4dSAndroid Build Coastguard Worker {
1236*a67afe4dSAndroid Build Coastguard Worker    int ch = getc(file->file);
1237*a67afe4dSAndroid Build Coastguard Worker 
1238*a67afe4dSAndroid Build Coastguard Worker    if (ch >= 0 && ch <= 255)
1239*a67afe4dSAndroid Build Coastguard Worker    {
1240*a67afe4dSAndroid Build Coastguard Worker       ++(file->read_count);
1241*a67afe4dSAndroid Build Coastguard Worker       return ch;
1242*a67afe4dSAndroid Build Coastguard Worker    }
1243*a67afe4dSAndroid Build Coastguard Worker 
1244*a67afe4dSAndroid Build Coastguard Worker    else if (ch != EOF)
1245*a67afe4dSAndroid Build Coastguard Worker    {
1246*a67afe4dSAndroid Build Coastguard Worker       file->status_code |= INTERNAL_ERROR;
1247*a67afe4dSAndroid Build Coastguard Worker       file->read_errno = ERANGE; /* out of range character */
1248*a67afe4dSAndroid Build Coastguard Worker 
1249*a67afe4dSAndroid Build Coastguard Worker       /* This is very unexpected; an error message is always output: */
1250*a67afe4dSAndroid Build Coastguard Worker       emit_error(file, UNEXPECTED_ERROR_CODE, "file read");
1251*a67afe4dSAndroid Build Coastguard Worker    }
1252*a67afe4dSAndroid Build Coastguard Worker 
1253*a67afe4dSAndroid Build Coastguard Worker #  ifdef EINTR
1254*a67afe4dSAndroid Build Coastguard Worker       else if (errno == EINTR) /* Interrupted, try again */
1255*a67afe4dSAndroid Build Coastguard Worker       {
1256*a67afe4dSAndroid Build Coastguard Worker          errno = 0;
1257*a67afe4dSAndroid Build Coastguard Worker          return read_byte(file);
1258*a67afe4dSAndroid Build Coastguard Worker       }
1259*a67afe4dSAndroid Build Coastguard Worker #  endif
1260*a67afe4dSAndroid Build Coastguard Worker 
1261*a67afe4dSAndroid Build Coastguard Worker    else
1262*a67afe4dSAndroid Build Coastguard Worker    {
1263*a67afe4dSAndroid Build Coastguard Worker       /* An error, it doesn't really matter what the error is but it gets
1264*a67afe4dSAndroid Build Coastguard Worker        * recorded anyway.
1265*a67afe4dSAndroid Build Coastguard Worker        */
1266*a67afe4dSAndroid Build Coastguard Worker       if (ferror(file->file))
1267*a67afe4dSAndroid Build Coastguard Worker          file->read_errno = errno;
1268*a67afe4dSAndroid Build Coastguard Worker 
1269*a67afe4dSAndroid Build Coastguard Worker       else if (feof(file->file))
1270*a67afe4dSAndroid Build Coastguard Worker          file->read_errno = 0; /* I.e. a regular EOF, no error */
1271*a67afe4dSAndroid Build Coastguard Worker 
1272*a67afe4dSAndroid Build Coastguard Worker       else /* unexpected */
1273*a67afe4dSAndroid Build Coastguard Worker          file->read_errno = EDOM;
1274*a67afe4dSAndroid Build Coastguard Worker    }
1275*a67afe4dSAndroid Build Coastguard Worker 
1276*a67afe4dSAndroid Build Coastguard Worker    /* 'TRUNCATED' is used for all cases of failure to read a byte, because of
1277*a67afe4dSAndroid Build Coastguard Worker     * the way libpng works a byte read is never attempted unless the byte is
1278*a67afe4dSAndroid Build Coastguard Worker     * expected to be there, so EOF should not occur.
1279*a67afe4dSAndroid Build Coastguard Worker     */
1280*a67afe4dSAndroid Build Coastguard Worker    file->status_code |= TRUNCATED;
1281*a67afe4dSAndroid Build Coastguard Worker    return EOF;
1282*a67afe4dSAndroid Build Coastguard Worker }
1283*a67afe4dSAndroid Build Coastguard Worker 
1284*a67afe4dSAndroid Build Coastguard Worker static png_byte
reread_byte(struct file * file)1285*a67afe4dSAndroid Build Coastguard Worker reread_byte(struct file *file)
1286*a67afe4dSAndroid Build Coastguard Worker    /* Read a byte when an error is not expected to happen because the byte has
1287*a67afe4dSAndroid Build Coastguard Worker     * been read before without error.
1288*a67afe4dSAndroid Build Coastguard Worker     */
1289*a67afe4dSAndroid Build Coastguard Worker {
1290*a67afe4dSAndroid Build Coastguard Worker    int ch = getc(file->file);
1291*a67afe4dSAndroid Build Coastguard Worker 
1292*a67afe4dSAndroid Build Coastguard Worker    if (errno != 0)
1293*a67afe4dSAndroid Build Coastguard Worker       file->read_errno = errno;
1294*a67afe4dSAndroid Build Coastguard Worker 
1295*a67afe4dSAndroid Build Coastguard Worker    if (ch < 0 || ch > 255)
1296*a67afe4dSAndroid Build Coastguard Worker       stop(file, UNEXPECTED_ERROR_CODE, "reread");
1297*a67afe4dSAndroid Build Coastguard Worker 
1298*a67afe4dSAndroid Build Coastguard Worker    return (png_byte)ch;
1299*a67afe4dSAndroid Build Coastguard Worker }
1300*a67afe4dSAndroid Build Coastguard Worker 
1301*a67afe4dSAndroid Build Coastguard Worker static png_uint_32
reread_4(struct file * file)1302*a67afe4dSAndroid Build Coastguard Worker reread_4(struct file *file)
1303*a67afe4dSAndroid Build Coastguard Worker    /* The same but for a four byte quantity */
1304*a67afe4dSAndroid Build Coastguard Worker {
1305*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 result = 0;
1306*a67afe4dSAndroid Build Coastguard Worker    int i = 0;
1307*a67afe4dSAndroid Build Coastguard Worker 
1308*a67afe4dSAndroid Build Coastguard Worker    while (++i <= 4)
1309*a67afe4dSAndroid Build Coastguard Worker       result = (result << 8) + reread_byte(file);
1310*a67afe4dSAndroid Build Coastguard Worker 
1311*a67afe4dSAndroid Build Coastguard Worker    return result;
1312*a67afe4dSAndroid Build Coastguard Worker }
1313*a67afe4dSAndroid Build Coastguard Worker 
1314*a67afe4dSAndroid Build Coastguard Worker static void
skip_12(struct file * file)1315*a67afe4dSAndroid Build Coastguard Worker skip_12(struct file *file)
1316*a67afe4dSAndroid Build Coastguard Worker    /* Skip exactly 12 bytes in the input stream - used to skip a CRC and chunk
1317*a67afe4dSAndroid Build Coastguard Worker     * header that has been read before.
1318*a67afe4dSAndroid Build Coastguard Worker     */
1319*a67afe4dSAndroid Build Coastguard Worker {
1320*a67afe4dSAndroid Build Coastguard Worker    /* Since the chunks were read before this shouldn't fail: */
1321*a67afe4dSAndroid Build Coastguard Worker    if (fseek(file->file, 12, SEEK_CUR) != 0)
1322*a67afe4dSAndroid Build Coastguard Worker    {
1323*a67afe4dSAndroid Build Coastguard Worker       if (errno != 0)
1324*a67afe4dSAndroid Build Coastguard Worker          file->read_errno = errno;
1325*a67afe4dSAndroid Build Coastguard Worker 
1326*a67afe4dSAndroid Build Coastguard Worker       stop(file, UNEXPECTED_ERROR_CODE, "reskip");
1327*a67afe4dSAndroid Build Coastguard Worker    }
1328*a67afe4dSAndroid Build Coastguard Worker }
1329*a67afe4dSAndroid Build Coastguard Worker 
1330*a67afe4dSAndroid Build Coastguard Worker static void
write_byte(struct file * file,int b)1331*a67afe4dSAndroid Build Coastguard Worker write_byte(struct file *file, int b)
1332*a67afe4dSAndroid Build Coastguard Worker    /* Write one byte to the output - this causes a fatal error if the write
1333*a67afe4dSAndroid Build Coastguard Worker     * fails and the read of this PNG file immediately terminates.  Just
1334*a67afe4dSAndroid Build Coastguard Worker     * increments the write count if there is no output file.
1335*a67afe4dSAndroid Build Coastguard Worker     */
1336*a67afe4dSAndroid Build Coastguard Worker {
1337*a67afe4dSAndroid Build Coastguard Worker    if (file->out != NULL)
1338*a67afe4dSAndroid Build Coastguard Worker    {
1339*a67afe4dSAndroid Build Coastguard Worker       if (putc(b, file->out) != b)
1340*a67afe4dSAndroid Build Coastguard Worker       {
1341*a67afe4dSAndroid Build Coastguard Worker          file->write_errno = errno;
1342*a67afe4dSAndroid Build Coastguard Worker          file->status_code |= WRITE_ERROR;
1343*a67afe4dSAndroid Build Coastguard Worker          stop(file, WRITE_ERROR_CODE, "write byte");
1344*a67afe4dSAndroid Build Coastguard Worker       }
1345*a67afe4dSAndroid Build Coastguard Worker    }
1346*a67afe4dSAndroid Build Coastguard Worker 
1347*a67afe4dSAndroid Build Coastguard Worker    ++(file->write_count);
1348*a67afe4dSAndroid Build Coastguard Worker }
1349*a67afe4dSAndroid Build Coastguard Worker 
1350*a67afe4dSAndroid Build Coastguard Worker /* Derivatives of the read/write functions. */
1351*a67afe4dSAndroid Build Coastguard Worker static unsigned int
read_4(struct file * file,png_uint_32 * pu)1352*a67afe4dSAndroid Build Coastguard Worker read_4(struct file *file, png_uint_32 *pu)
1353*a67afe4dSAndroid Build Coastguard Worker    /* Read four bytes, returns the number of bytes read successfully and, if all
1354*a67afe4dSAndroid Build Coastguard Worker     * four bytes are read, assigns the result to *pu.
1355*a67afe4dSAndroid Build Coastguard Worker     */
1356*a67afe4dSAndroid Build Coastguard Worker {
1357*a67afe4dSAndroid Build Coastguard Worker    unsigned int i = 0;
1358*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 val = 0;
1359*a67afe4dSAndroid Build Coastguard Worker 
1360*a67afe4dSAndroid Build Coastguard Worker    do
1361*a67afe4dSAndroid Build Coastguard Worker    {
1362*a67afe4dSAndroid Build Coastguard Worker       int ch = read_byte(file);
1363*a67afe4dSAndroid Build Coastguard Worker 
1364*a67afe4dSAndroid Build Coastguard Worker       if (ch == EOF)
1365*a67afe4dSAndroid Build Coastguard Worker          return i;
1366*a67afe4dSAndroid Build Coastguard Worker 
1367*a67afe4dSAndroid Build Coastguard Worker       val = (val << 8) + ch;
1368*a67afe4dSAndroid Build Coastguard Worker    } while (++i < 4);
1369*a67afe4dSAndroid Build Coastguard Worker 
1370*a67afe4dSAndroid Build Coastguard Worker    *pu = val;
1371*a67afe4dSAndroid Build Coastguard Worker    return i;
1372*a67afe4dSAndroid Build Coastguard Worker }
1373*a67afe4dSAndroid Build Coastguard Worker 
1374*a67afe4dSAndroid Build Coastguard Worker /* CRC handling - read but calculate the CRC while doing so. */
1375*a67afe4dSAndroid Build Coastguard Worker static int
crc_read_many(struct file * file,png_uint_32 length)1376*a67afe4dSAndroid Build Coastguard Worker crc_read_many(struct file *file, png_uint_32 length)
1377*a67afe4dSAndroid Build Coastguard Worker    /* Reads 'length' bytes and updates the CRC, returns true on success, false
1378*a67afe4dSAndroid Build Coastguard Worker     * if the input is truncated.
1379*a67afe4dSAndroid Build Coastguard Worker     */
1380*a67afe4dSAndroid Build Coastguard Worker {
1381*a67afe4dSAndroid Build Coastguard Worker    if (length > 0)
1382*a67afe4dSAndroid Build Coastguard Worker    {
1383*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 crc = file->crc;
1384*a67afe4dSAndroid Build Coastguard Worker 
1385*a67afe4dSAndroid Build Coastguard Worker       do
1386*a67afe4dSAndroid Build Coastguard Worker       {
1387*a67afe4dSAndroid Build Coastguard Worker          int ch = read_byte(file);
1388*a67afe4dSAndroid Build Coastguard Worker 
1389*a67afe4dSAndroid Build Coastguard Worker          if (ch == EOF)
1390*a67afe4dSAndroid Build Coastguard Worker             return 0; /* Truncated */
1391*a67afe4dSAndroid Build Coastguard Worker 
1392*a67afe4dSAndroid Build Coastguard Worker          crc = crc_one_byte(crc, ch);
1393*a67afe4dSAndroid Build Coastguard Worker       }
1394*a67afe4dSAndroid Build Coastguard Worker       while (--length > 0);
1395*a67afe4dSAndroid Build Coastguard Worker 
1396*a67afe4dSAndroid Build Coastguard Worker       file->crc = crc;
1397*a67afe4dSAndroid Build Coastguard Worker    }
1398*a67afe4dSAndroid Build Coastguard Worker 
1399*a67afe4dSAndroid Build Coastguard Worker    return 1; /* OK */
1400*a67afe4dSAndroid Build Coastguard Worker }
1401*a67afe4dSAndroid Build Coastguard Worker 
1402*a67afe4dSAndroid Build Coastguard Worker static int
calc_image_size(struct file * file)1403*a67afe4dSAndroid Build Coastguard Worker calc_image_size(struct file *file)
1404*a67afe4dSAndroid Build Coastguard Worker    /* Fill in the image_bytes field given the IHDR information, calls stop on
1405*a67afe4dSAndroid Build Coastguard Worker     * error.
1406*a67afe4dSAndroid Build Coastguard Worker     */
1407*a67afe4dSAndroid Build Coastguard Worker {
1408*a67afe4dSAndroid Build Coastguard Worker    png_uint_16 pd = file->bit_depth;
1409*a67afe4dSAndroid Build Coastguard Worker 
1410*a67afe4dSAndroid Build Coastguard Worker    switch (file->color_type)
1411*a67afe4dSAndroid Build Coastguard Worker    {
1412*a67afe4dSAndroid Build Coastguard Worker       default:
1413*a67afe4dSAndroid Build Coastguard Worker          stop_invalid(file, "IHDR: colour type");
1414*a67afe4dSAndroid Build Coastguard Worker 
1415*a67afe4dSAndroid Build Coastguard Worker       invalid_bit_depth:
1416*a67afe4dSAndroid Build Coastguard Worker          stop_invalid(file, "IHDR: bit depth");
1417*a67afe4dSAndroid Build Coastguard Worker 
1418*a67afe4dSAndroid Build Coastguard Worker       case 0: /* g */
1419*a67afe4dSAndroid Build Coastguard Worker          if (pd != 1 && pd != 2 && pd != 4 && pd != 8 && pd != 16)
1420*a67afe4dSAndroid Build Coastguard Worker             goto invalid_bit_depth;
1421*a67afe4dSAndroid Build Coastguard Worker          break;
1422*a67afe4dSAndroid Build Coastguard Worker 
1423*a67afe4dSAndroid Build Coastguard Worker       case 3:
1424*a67afe4dSAndroid Build Coastguard Worker          if (pd != 1 && pd != 2 && pd != 4 && pd != 8)
1425*a67afe4dSAndroid Build Coastguard Worker             goto invalid_bit_depth;
1426*a67afe4dSAndroid Build Coastguard Worker          break;
1427*a67afe4dSAndroid Build Coastguard Worker 
1428*a67afe4dSAndroid Build Coastguard Worker       case 2: /* rgb */
1429*a67afe4dSAndroid Build Coastguard Worker          if (pd != 8 && pd != 16)
1430*a67afe4dSAndroid Build Coastguard Worker             goto invalid_bit_depth;
1431*a67afe4dSAndroid Build Coastguard Worker 
1432*a67afe4dSAndroid Build Coastguard Worker          pd = (png_uint_16)(pd * 3);
1433*a67afe4dSAndroid Build Coastguard Worker          break;
1434*a67afe4dSAndroid Build Coastguard Worker 
1435*a67afe4dSAndroid Build Coastguard Worker       case 4: /* ga */
1436*a67afe4dSAndroid Build Coastguard Worker          if (pd != 8 && pd != 16)
1437*a67afe4dSAndroid Build Coastguard Worker             goto invalid_bit_depth;
1438*a67afe4dSAndroid Build Coastguard Worker 
1439*a67afe4dSAndroid Build Coastguard Worker          pd = (png_uint_16)(pd * 2);
1440*a67afe4dSAndroid Build Coastguard Worker          break;
1441*a67afe4dSAndroid Build Coastguard Worker 
1442*a67afe4dSAndroid Build Coastguard Worker       case 6: /* rgba */
1443*a67afe4dSAndroid Build Coastguard Worker          if (pd != 8 && pd != 16)
1444*a67afe4dSAndroid Build Coastguard Worker             goto invalid_bit_depth;
1445*a67afe4dSAndroid Build Coastguard Worker 
1446*a67afe4dSAndroid Build Coastguard Worker          pd = (png_uint_16)(pd * 4);
1447*a67afe4dSAndroid Build Coastguard Worker          break;
1448*a67afe4dSAndroid Build Coastguard Worker    }
1449*a67afe4dSAndroid Build Coastguard Worker 
1450*a67afe4dSAndroid Build Coastguard Worker    if (file->width < 1 || file->width > 0x7fffffff)
1451*a67afe4dSAndroid Build Coastguard Worker       stop_invalid(file, "IHDR: width");
1452*a67afe4dSAndroid Build Coastguard Worker 
1453*a67afe4dSAndroid Build Coastguard Worker    else if (file->height < 1 || file->height > 0x7fffffff)
1454*a67afe4dSAndroid Build Coastguard Worker       stop_invalid(file, "IHDR: height");
1455*a67afe4dSAndroid Build Coastguard Worker 
1456*a67afe4dSAndroid Build Coastguard Worker    else if (file->compression_method != 0)
1457*a67afe4dSAndroid Build Coastguard Worker       stop_invalid(file, "IHDR: compression method");
1458*a67afe4dSAndroid Build Coastguard Worker 
1459*a67afe4dSAndroid Build Coastguard Worker    else if (file->filter_method != 0)
1460*a67afe4dSAndroid Build Coastguard Worker       stop_invalid(file, "IHDR: filter method");
1461*a67afe4dSAndroid Build Coastguard Worker 
1462*a67afe4dSAndroid Build Coastguard Worker    else switch (file->interlace_method)
1463*a67afe4dSAndroid Build Coastguard Worker    {
1464*a67afe4dSAndroid Build Coastguard Worker       case PNG_INTERLACE_ADAM7:
1465*a67afe4dSAndroid Build Coastguard Worker          /* Interlacing makes the image larger because of the replication of
1466*a67afe4dSAndroid Build Coastguard Worker           * both the filter byte and the padding to a byte boundary.
1467*a67afe4dSAndroid Build Coastguard Worker           */
1468*a67afe4dSAndroid Build Coastguard Worker          {
1469*a67afe4dSAndroid Build Coastguard Worker             int pass;
1470*a67afe4dSAndroid Build Coastguard Worker             int image_digits = 0;
1471*a67afe4dSAndroid Build Coastguard Worker             udigit row_width[2], row_bytes[3];
1472*a67afe4dSAndroid Build Coastguard Worker 
1473*a67afe4dSAndroid Build Coastguard Worker             for (pass=0; pass<=6; ++pass)
1474*a67afe4dSAndroid Build Coastguard Worker             {
1475*a67afe4dSAndroid Build Coastguard Worker                png_uint_32 pw = PNG_PASS_COLS(file->width, pass);
1476*a67afe4dSAndroid Build Coastguard Worker 
1477*a67afe4dSAndroid Build Coastguard Worker                if (pw > 0)
1478*a67afe4dSAndroid Build Coastguard Worker                {
1479*a67afe4dSAndroid Build Coastguard Worker                   int  digits;
1480*a67afe4dSAndroid Build Coastguard Worker 
1481*a67afe4dSAndroid Build Coastguard Worker                   /* calculate 1+((pw*pd+7)>>3) in row_bytes */
1482*a67afe4dSAndroid Build Coastguard Worker                   digits = uarb_mult_digit(row_bytes, uarb_set(row_bytes, 7),
1483*a67afe4dSAndroid Build Coastguard Worker                      row_width, uarb_set(row_width, pw), pd);
1484*a67afe4dSAndroid Build Coastguard Worker                   digits = uarb_shift(row_bytes, digits, 3);
1485*a67afe4dSAndroid Build Coastguard Worker                   digits = uarb_inc(row_bytes, digits, 1);
1486*a67afe4dSAndroid Build Coastguard Worker 
1487*a67afe4dSAndroid Build Coastguard Worker                   /* Add row_bytes * pass-height to the file image_bytes field
1488*a67afe4dSAndroid Build Coastguard Worker                    */
1489*a67afe4dSAndroid Build Coastguard Worker                   image_digits = uarb_mult32(file->image_bytes, image_digits,
1490*a67afe4dSAndroid Build Coastguard Worker                      row_bytes, digits,
1491*a67afe4dSAndroid Build Coastguard Worker                      PNG_PASS_ROWS(file->height, pass));
1492*a67afe4dSAndroid Build Coastguard Worker                }
1493*a67afe4dSAndroid Build Coastguard Worker             }
1494*a67afe4dSAndroid Build Coastguard Worker 
1495*a67afe4dSAndroid Build Coastguard Worker             file->image_digits = image_digits;
1496*a67afe4dSAndroid Build Coastguard Worker          }
1497*a67afe4dSAndroid Build Coastguard Worker          break;
1498*a67afe4dSAndroid Build Coastguard Worker 
1499*a67afe4dSAndroid Build Coastguard Worker       case PNG_INTERLACE_NONE:
1500*a67afe4dSAndroid Build Coastguard Worker          {
1501*a67afe4dSAndroid Build Coastguard Worker             int  digits;
1502*a67afe4dSAndroid Build Coastguard Worker             udigit row_width[2], row_bytes[3];
1503*a67afe4dSAndroid Build Coastguard Worker 
1504*a67afe4dSAndroid Build Coastguard Worker             /* As above, but use image_width in place of the pass width: */
1505*a67afe4dSAndroid Build Coastguard Worker             digits = uarb_mult_digit(row_bytes, uarb_set(row_bytes, 7),
1506*a67afe4dSAndroid Build Coastguard Worker                row_width, uarb_set(row_width, file->width), pd);
1507*a67afe4dSAndroid Build Coastguard Worker             digits = uarb_shift(row_bytes, digits, 3);
1508*a67afe4dSAndroid Build Coastguard Worker             digits = uarb_inc(row_bytes, digits, 1);
1509*a67afe4dSAndroid Build Coastguard Worker 
1510*a67afe4dSAndroid Build Coastguard Worker             /* Set row_bytes * image-height to the file image_bytes field */
1511*a67afe4dSAndroid Build Coastguard Worker             file->image_digits = uarb_mult32(file->image_bytes, 0,
1512*a67afe4dSAndroid Build Coastguard Worker                row_bytes, digits, file->height);
1513*a67afe4dSAndroid Build Coastguard Worker          }
1514*a67afe4dSAndroid Build Coastguard Worker          break;
1515*a67afe4dSAndroid Build Coastguard Worker 
1516*a67afe4dSAndroid Build Coastguard Worker       default:
1517*a67afe4dSAndroid Build Coastguard Worker          stop_invalid(file, "IHDR: interlace method");
1518*a67afe4dSAndroid Build Coastguard Worker    }
1519*a67afe4dSAndroid Build Coastguard Worker 
1520*a67afe4dSAndroid Build Coastguard Worker    assert(file->image_digits >= 1 && file->image_digits <= 5);
1521*a67afe4dSAndroid Build Coastguard Worker    return 1;
1522*a67afe4dSAndroid Build Coastguard Worker }
1523*a67afe4dSAndroid Build Coastguard Worker 
1524*a67afe4dSAndroid Build Coastguard Worker /* PER-CHUNK CONTROL STRUCTURE
1525*a67afe4dSAndroid Build Coastguard Worker  * This structure is instantiated for each chunk, except for the IDAT chunks
1526*a67afe4dSAndroid Build Coastguard Worker  * where one chunk control structure is used for the whole of a single stream of
1527*a67afe4dSAndroid Build Coastguard Worker  * IDAT chunks (see the IDAT control structure below).
1528*a67afe4dSAndroid Build Coastguard Worker  */
1529*a67afe4dSAndroid Build Coastguard Worker struct chunk
1530*a67afe4dSAndroid Build Coastguard Worker {
1531*a67afe4dSAndroid Build Coastguard Worker    /* ANCESTORS */
1532*a67afe4dSAndroid Build Coastguard Worker    struct file *         file;
1533*a67afe4dSAndroid Build Coastguard Worker    struct global *       global;
1534*a67afe4dSAndroid Build Coastguard Worker 
1535*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC IDAT INFORMATION: SET BY THE ZLIB CODE */
1536*a67afe4dSAndroid Build Coastguard Worker    udigit         uncompressed_bytes[5];
1537*a67afe4dSAndroid Build Coastguard Worker    int            uncompressed_digits;
1538*a67afe4dSAndroid Build Coastguard Worker    udigit         compressed_bytes[5];
1539*a67afe4dSAndroid Build Coastguard Worker    int            compressed_digits;
1540*a67afe4dSAndroid Build Coastguard Worker 
1541*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC PER-CHUNK INFORMATION: USED BY CHUNK READ CODE */
1542*a67afe4dSAndroid Build Coastguard Worker    /* This information is filled in by chunk_init from the data in the file
1543*a67afe4dSAndroid Build Coastguard Worker     * control structure, but chunk_length may be changed later.
1544*a67afe4dSAndroid Build Coastguard Worker     */
1545*a67afe4dSAndroid Build Coastguard Worker    fpos_t         chunk_data_pos;    /* Position of first byte of chunk data */
1546*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    chunk_length;      /* From header (or modified below) */
1547*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    chunk_type;        /* From header */
1548*a67afe4dSAndroid Build Coastguard Worker 
1549*a67afe4dSAndroid Build Coastguard Worker    /* PUBLIC PER-CHUNK INFORMATION: FOR THE CHUNK WRITE CODE */
1550*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    write_crc;         /* Output CRC (may differ from read_crc) */
1551*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    rewrite_offset;    /* Count of bytes before rewrite. */
1552*a67afe4dSAndroid Build Coastguard Worker    int            rewrite_length;    /* Number of bytes left to change */
1553*a67afe4dSAndroid Build Coastguard Worker    png_byte       rewrite_buffer[2]; /* Buffer of new byte values */
1554*a67afe4dSAndroid Build Coastguard Worker };
1555*a67afe4dSAndroid Build Coastguard Worker 
1556*a67afe4dSAndroid Build Coastguard Worker static void
chunk_message(struct chunk * chunk,const char * message)1557*a67afe4dSAndroid Build Coastguard Worker chunk_message(struct chunk *chunk, const char *message)
1558*a67afe4dSAndroid Build Coastguard Worker {
1559*a67afe4dSAndroid Build Coastguard Worker    type_message(chunk->file, chunk->chunk_type, message);
1560*a67afe4dSAndroid Build Coastguard Worker }
1561*a67afe4dSAndroid Build Coastguard Worker 
1562*a67afe4dSAndroid Build Coastguard Worker static void
chunk_end(struct chunk ** chunk_var)1563*a67afe4dSAndroid Build Coastguard Worker chunk_end(struct chunk **chunk_var)
1564*a67afe4dSAndroid Build Coastguard Worker {
1565*a67afe4dSAndroid Build Coastguard Worker    struct chunk *chunk = *chunk_var;
1566*a67afe4dSAndroid Build Coastguard Worker 
1567*a67afe4dSAndroid Build Coastguard Worker    *chunk_var = NULL;
1568*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*chunk);
1569*a67afe4dSAndroid Build Coastguard Worker }
1570*a67afe4dSAndroid Build Coastguard Worker 
1571*a67afe4dSAndroid Build Coastguard Worker static void
chunk_init(struct chunk * const chunk,struct file * const file)1572*a67afe4dSAndroid Build Coastguard Worker chunk_init(struct chunk * const chunk, struct file * const file)
1573*a67afe4dSAndroid Build Coastguard Worker    /* When a chunk is initialized the file length/type/pos are copied into the
1574*a67afe4dSAndroid Build Coastguard Worker     * corresponding chunk fields and the new chunk is registered in the file
1575*a67afe4dSAndroid Build Coastguard Worker     * structure.  There can only be one chunk at a time.
1576*a67afe4dSAndroid Build Coastguard Worker     *
1577*a67afe4dSAndroid Build Coastguard Worker     * NOTE: this routine must onely be called from the file alloc routine!
1578*a67afe4dSAndroid Build Coastguard Worker     */
1579*a67afe4dSAndroid Build Coastguard Worker {
1580*a67afe4dSAndroid Build Coastguard Worker    assert(file->chunk == NULL);
1581*a67afe4dSAndroid Build Coastguard Worker 
1582*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*chunk);
1583*a67afe4dSAndroid Build Coastguard Worker 
1584*a67afe4dSAndroid Build Coastguard Worker    chunk->file = file;
1585*a67afe4dSAndroid Build Coastguard Worker    chunk->global = file->global;
1586*a67afe4dSAndroid Build Coastguard Worker 
1587*a67afe4dSAndroid Build Coastguard Worker    chunk->chunk_data_pos = file->data_pos;
1588*a67afe4dSAndroid Build Coastguard Worker    chunk->chunk_length = file->length;
1589*a67afe4dSAndroid Build Coastguard Worker    chunk->chunk_type = file->type;
1590*a67afe4dSAndroid Build Coastguard Worker 
1591*a67afe4dSAndroid Build Coastguard Worker    /* Compressed/uncompressed size information (from the zlib control structure
1592*a67afe4dSAndroid Build Coastguard Worker     * that is used to check the compressed data in a chunk.)
1593*a67afe4dSAndroid Build Coastguard Worker     */
1594*a67afe4dSAndroid Build Coastguard Worker    chunk->uncompressed_digits = 0;
1595*a67afe4dSAndroid Build Coastguard Worker    chunk->compressed_digits = 0;
1596*a67afe4dSAndroid Build Coastguard Worker 
1597*a67afe4dSAndroid Build Coastguard Worker    file->chunk = chunk;
1598*a67afe4dSAndroid Build Coastguard Worker }
1599*a67afe4dSAndroid Build Coastguard Worker 
1600*a67afe4dSAndroid Build Coastguard Worker static png_uint_32
current_type(struct file * file,int code)1601*a67afe4dSAndroid Build Coastguard Worker current_type(struct file *file, int code)
1602*a67afe4dSAndroid Build Coastguard Worker    /* Guess the actual chunk type that causes a stop() */
1603*a67afe4dSAndroid Build Coastguard Worker {
1604*a67afe4dSAndroid Build Coastguard Worker    /* This may return png_IDAT for errors detected (late) in the header; that
1605*a67afe4dSAndroid Build Coastguard Worker     * includes any inter-chunk consistency check that libpng performs.  Assume
1606*a67afe4dSAndroid Build Coastguard Worker     * that if the chunk_type is png_IDAT and the file write count is 8 this is
1607*a67afe4dSAndroid Build Coastguard Worker     * what is happening.
1608*a67afe4dSAndroid Build Coastguard Worker     */
1609*a67afe4dSAndroid Build Coastguard Worker    if (file->chunk != NULL)
1610*a67afe4dSAndroid Build Coastguard Worker    {
1611*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 type = file->chunk->chunk_type;
1612*a67afe4dSAndroid Build Coastguard Worker 
1613*a67afe4dSAndroid Build Coastguard Worker       /* This is probably wrong for the excess IDATs case, because then libpng
1614*a67afe4dSAndroid Build Coastguard Worker        * whines about too many of them (apparently in some cases erroneously)
1615*a67afe4dSAndroid Build Coastguard Worker        * when the header is read.
1616*a67afe4dSAndroid Build Coastguard Worker        */
1617*a67afe4dSAndroid Build Coastguard Worker       if (code <= LIBPNG_ERROR_CODE && type == png_IDAT &&
1618*a67afe4dSAndroid Build Coastguard Worker          file->write_count == 8)
1619*a67afe4dSAndroid Build Coastguard Worker          type = 0; /* magic */
1620*a67afe4dSAndroid Build Coastguard Worker 
1621*a67afe4dSAndroid Build Coastguard Worker       return type;
1622*a67afe4dSAndroid Build Coastguard Worker    }
1623*a67afe4dSAndroid Build Coastguard Worker 
1624*a67afe4dSAndroid Build Coastguard Worker    else
1625*a67afe4dSAndroid Build Coastguard Worker       return file->type;
1626*a67afe4dSAndroid Build Coastguard Worker }
1627*a67afe4dSAndroid Build Coastguard Worker 
1628*a67afe4dSAndroid Build Coastguard Worker static void
setpos(struct chunk * chunk)1629*a67afe4dSAndroid Build Coastguard Worker setpos(struct chunk *chunk)
1630*a67afe4dSAndroid Build Coastguard Worker    /* Reset the position to 'chunk_data_pos' - the start of the data for this
1631*a67afe4dSAndroid Build Coastguard Worker     * chunk.  As a side effect the read_count in the file is reset to 8, just
1632*a67afe4dSAndroid Build Coastguard Worker     * after the length/type header.
1633*a67afe4dSAndroid Build Coastguard Worker     */
1634*a67afe4dSAndroid Build Coastguard Worker {
1635*a67afe4dSAndroid Build Coastguard Worker    chunk->file->read_count = 8;
1636*a67afe4dSAndroid Build Coastguard Worker    file_setpos(chunk->file, &chunk->chunk_data_pos);
1637*a67afe4dSAndroid Build Coastguard Worker }
1638*a67afe4dSAndroid Build Coastguard Worker 
1639*a67afe4dSAndroid Build Coastguard Worker /* Specific chunk handling - called for each chunk header, all special chunk
1640*a67afe4dSAndroid Build Coastguard Worker  * processing is initiated in these functions.
1641*a67afe4dSAndroid Build Coastguard Worker  */
1642*a67afe4dSAndroid Build Coastguard Worker /* The next functions handle special processing for those chunks with LZ data,
1643*a67afe4dSAndroid Build Coastguard Worker  * the data is identified and checked for validity.  If there are problems which
1644*a67afe4dSAndroid Build Coastguard Worker  * cannot be corrected the routines return false, otherwise true (although
1645*a67afe4dSAndroid Build Coastguard Worker  * modification to the zlib header may be required.)
1646*a67afe4dSAndroid Build Coastguard Worker  *
1647*a67afe4dSAndroid Build Coastguard Worker  * The compressed data is in zlib format (RFC1950) and consequently has a
1648*a67afe4dSAndroid Build Coastguard Worker  * minimum length of 7 bytes.
1649*a67afe4dSAndroid Build Coastguard Worker  */
1650*a67afe4dSAndroid Build Coastguard Worker static int zlib_check(struct file *file, png_uint_32 offset);
1651*a67afe4dSAndroid Build Coastguard Worker 
1652*a67afe4dSAndroid Build Coastguard Worker static int
process_zTXt_iCCP(struct file * file)1653*a67afe4dSAndroid Build Coastguard Worker process_zTXt_iCCP(struct file *file)
1654*a67afe4dSAndroid Build Coastguard Worker    /* zTXt and iCCP have exactly the same form - keyword, null, compression
1655*a67afe4dSAndroid Build Coastguard Worker     * method then compressed data.
1656*a67afe4dSAndroid Build Coastguard Worker     */
1657*a67afe4dSAndroid Build Coastguard Worker {
1658*a67afe4dSAndroid Build Coastguard Worker    struct chunk *chunk = file->chunk;
1659*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 length;
1660*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 index = 0;
1661*a67afe4dSAndroid Build Coastguard Worker 
1662*a67afe4dSAndroid Build Coastguard Worker    assert(chunk != NULL && file->idat == NULL);
1663*a67afe4dSAndroid Build Coastguard Worker    length = chunk->chunk_length;
1664*a67afe4dSAndroid Build Coastguard Worker    setpos(chunk);
1665*a67afe4dSAndroid Build Coastguard Worker 
1666*a67afe4dSAndroid Build Coastguard Worker    while (length >= 9)
1667*a67afe4dSAndroid Build Coastguard Worker    {
1668*a67afe4dSAndroid Build Coastguard Worker       --length;
1669*a67afe4dSAndroid Build Coastguard Worker       ++index;
1670*a67afe4dSAndroid Build Coastguard Worker       if (reread_byte(file) == 0) /* keyword null terminator */
1671*a67afe4dSAndroid Build Coastguard Worker       {
1672*a67afe4dSAndroid Build Coastguard Worker          --length;
1673*a67afe4dSAndroid Build Coastguard Worker          ++index;
1674*a67afe4dSAndroid Build Coastguard Worker          (void)reread_byte(file); /* compression method */
1675*a67afe4dSAndroid Build Coastguard Worker          return zlib_check(file, index);
1676*a67afe4dSAndroid Build Coastguard Worker       }
1677*a67afe4dSAndroid Build Coastguard Worker    }
1678*a67afe4dSAndroid Build Coastguard Worker 
1679*a67afe4dSAndroid Build Coastguard Worker    chunk_message(chunk, "too short");
1680*a67afe4dSAndroid Build Coastguard Worker    return 0; /* skip */
1681*a67afe4dSAndroid Build Coastguard Worker }
1682*a67afe4dSAndroid Build Coastguard Worker 
1683*a67afe4dSAndroid Build Coastguard Worker static int
process_iTXt(struct file * file)1684*a67afe4dSAndroid Build Coastguard Worker process_iTXt(struct file *file)
1685*a67afe4dSAndroid Build Coastguard Worker {
1686*a67afe4dSAndroid Build Coastguard Worker    /* Like zTXt but more fields. */
1687*a67afe4dSAndroid Build Coastguard Worker    struct chunk *chunk = file->chunk;
1688*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 length;
1689*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 index = 0;
1690*a67afe4dSAndroid Build Coastguard Worker 
1691*a67afe4dSAndroid Build Coastguard Worker    assert(chunk != NULL && file->idat == NULL);
1692*a67afe4dSAndroid Build Coastguard Worker    length = chunk->chunk_length;
1693*a67afe4dSAndroid Build Coastguard Worker    setpos(chunk);
1694*a67afe4dSAndroid Build Coastguard Worker 
1695*a67afe4dSAndroid Build Coastguard Worker    while (length >= 5)
1696*a67afe4dSAndroid Build Coastguard Worker    {
1697*a67afe4dSAndroid Build Coastguard Worker       --length;
1698*a67afe4dSAndroid Build Coastguard Worker       ++index;
1699*a67afe4dSAndroid Build Coastguard Worker       if (reread_byte(file) == 0) /* keyword null terminator */
1700*a67afe4dSAndroid Build Coastguard Worker       {
1701*a67afe4dSAndroid Build Coastguard Worker          --length;
1702*a67afe4dSAndroid Build Coastguard Worker          ++index;
1703*a67afe4dSAndroid Build Coastguard Worker          if (reread_byte(file) == 0) /* uncompressed text */
1704*a67afe4dSAndroid Build Coastguard Worker             return 1; /* nothing to check */
1705*a67afe4dSAndroid Build Coastguard Worker 
1706*a67afe4dSAndroid Build Coastguard Worker          --length;
1707*a67afe4dSAndroid Build Coastguard Worker          ++index;
1708*a67afe4dSAndroid Build Coastguard Worker          (void)reread_byte(file); /* compression method */
1709*a67afe4dSAndroid Build Coastguard Worker 
1710*a67afe4dSAndroid Build Coastguard Worker          /* Skip the language tag (null terminated). */
1711*a67afe4dSAndroid Build Coastguard Worker          while (length >= 9)
1712*a67afe4dSAndroid Build Coastguard Worker          {
1713*a67afe4dSAndroid Build Coastguard Worker             --length;
1714*a67afe4dSAndroid Build Coastguard Worker             ++index;
1715*a67afe4dSAndroid Build Coastguard Worker             if (reread_byte(file) == 0) /* terminator */
1716*a67afe4dSAndroid Build Coastguard Worker             {
1717*a67afe4dSAndroid Build Coastguard Worker                /* Skip the translated keyword */
1718*a67afe4dSAndroid Build Coastguard Worker                while (length >= 8)
1719*a67afe4dSAndroid Build Coastguard Worker                {
1720*a67afe4dSAndroid Build Coastguard Worker                   --length;
1721*a67afe4dSAndroid Build Coastguard Worker                   ++index;
1722*a67afe4dSAndroid Build Coastguard Worker                   if (reread_byte(file) == 0) /* terminator */
1723*a67afe4dSAndroid Build Coastguard Worker                      return zlib_check(file, index);
1724*a67afe4dSAndroid Build Coastguard Worker                }
1725*a67afe4dSAndroid Build Coastguard Worker             }
1726*a67afe4dSAndroid Build Coastguard Worker          }
1727*a67afe4dSAndroid Build Coastguard Worker 
1728*a67afe4dSAndroid Build Coastguard Worker          /* Ran out of bytes in the compressed case. */
1729*a67afe4dSAndroid Build Coastguard Worker          break;
1730*a67afe4dSAndroid Build Coastguard Worker       }
1731*a67afe4dSAndroid Build Coastguard Worker    }
1732*a67afe4dSAndroid Build Coastguard Worker 
1733*a67afe4dSAndroid Build Coastguard Worker    log_error(file, INVALID_ERROR_CODE, "iTXt chunk length");
1734*a67afe4dSAndroid Build Coastguard Worker 
1735*a67afe4dSAndroid Build Coastguard Worker    return 0; /* skip */
1736*a67afe4dSAndroid Build Coastguard Worker }
1737*a67afe4dSAndroid Build Coastguard Worker 
1738*a67afe4dSAndroid Build Coastguard Worker /* IDAT READ/WRITE CONTROL STRUCTURE */
1739*a67afe4dSAndroid Build Coastguard Worker struct IDAT
1740*a67afe4dSAndroid Build Coastguard Worker {
1741*a67afe4dSAndroid Build Coastguard Worker    /* ANCESTORS */
1742*a67afe4dSAndroid Build Coastguard Worker    struct file *         file;
1743*a67afe4dSAndroid Build Coastguard Worker    struct global *       global;
1744*a67afe4dSAndroid Build Coastguard Worker 
1745*a67afe4dSAndroid Build Coastguard Worker    /* PROTECTED IDAT INFORMATION: SET BY THE IDAT READ CODE */
1746*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *idat_list_head; /* START of the list of IDAT information */
1747*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *idat_list_tail; /* *END* of the list of IDAT information */
1748*a67afe4dSAndroid Build Coastguard Worker 
1749*a67afe4dSAndroid Build Coastguard Worker    /* PROTECTED IDAT INFORMATION: USED BY THE IDAT WRITE CODE */
1750*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *idat_cur;       /* Current list entry */
1751*a67afe4dSAndroid Build Coastguard Worker    unsigned int      idat_count;     /* And the *current* index into the list */
1752*a67afe4dSAndroid Build Coastguard Worker    png_uint_32       idat_index;     /* Index of *next* input byte to write */
1753*a67afe4dSAndroid Build Coastguard Worker    png_uint_32       idat_length;    /* Cache of current chunk length */
1754*a67afe4dSAndroid Build Coastguard Worker };
1755*a67afe4dSAndroid Build Coastguard Worker 
1756*a67afe4dSAndroid Build Coastguard Worker /* NOTE: there is currently no IDAT_reset, so a stream cannot contain more than
1757*a67afe4dSAndroid Build Coastguard Worker  * one IDAT sequence (i.e. MNG is not supported).
1758*a67afe4dSAndroid Build Coastguard Worker  */
1759*a67afe4dSAndroid Build Coastguard Worker 
1760*a67afe4dSAndroid Build Coastguard Worker static void
IDAT_end(struct IDAT ** idat_var)1761*a67afe4dSAndroid Build Coastguard Worker IDAT_end(struct IDAT **idat_var)
1762*a67afe4dSAndroid Build Coastguard Worker {
1763*a67afe4dSAndroid Build Coastguard Worker    struct IDAT *idat = *idat_var;
1764*a67afe4dSAndroid Build Coastguard Worker    struct file *file = idat->file;
1765*a67afe4dSAndroid Build Coastguard Worker 
1766*a67afe4dSAndroid Build Coastguard Worker    *idat_var = NULL;
1767*a67afe4dSAndroid Build Coastguard Worker 
1768*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*idat);
1769*a67afe4dSAndroid Build Coastguard Worker 
1770*a67afe4dSAndroid Build Coastguard Worker    assert(file->chunk != NULL);
1771*a67afe4dSAndroid Build Coastguard Worker    chunk_end(&file->chunk);
1772*a67afe4dSAndroid Build Coastguard Worker 
1773*a67afe4dSAndroid Build Coastguard Worker    /* Regardless of why the IDAT was killed set the state back to CHUNKS (it may
1774*a67afe4dSAndroid Build Coastguard Worker     * already be CHUNKS because the state isn't changed until process_IDAT
1775*a67afe4dSAndroid Build Coastguard Worker     * returns; a stop will cause IDAT_end to be entered in state CHUNKS!)
1776*a67afe4dSAndroid Build Coastguard Worker     */
1777*a67afe4dSAndroid Build Coastguard Worker    file->state = STATE_CHUNKS;
1778*a67afe4dSAndroid Build Coastguard Worker }
1779*a67afe4dSAndroid Build Coastguard Worker 
1780*a67afe4dSAndroid Build Coastguard Worker static void
IDAT_init(struct IDAT * const idat,struct file * const file)1781*a67afe4dSAndroid Build Coastguard Worker IDAT_init(struct IDAT * const idat, struct file * const file)
1782*a67afe4dSAndroid Build Coastguard Worker    /* When the chunk is png_IDAT instantiate an IDAT control structure in place
1783*a67afe4dSAndroid Build Coastguard Worker     * of a chunk control structure.  The IDAT will instantiate a chunk control
1784*a67afe4dSAndroid Build Coastguard Worker     * structure using the file alloc routine.
1785*a67afe4dSAndroid Build Coastguard Worker     *
1786*a67afe4dSAndroid Build Coastguard Worker     * NOTE: this routine must only be called from the file alloc routine!
1787*a67afe4dSAndroid Build Coastguard Worker     */
1788*a67afe4dSAndroid Build Coastguard Worker {
1789*a67afe4dSAndroid Build Coastguard Worker    assert(file->chunk == NULL);
1790*a67afe4dSAndroid Build Coastguard Worker    assert(file->idat == NULL);
1791*a67afe4dSAndroid Build Coastguard Worker 
1792*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*idat);
1793*a67afe4dSAndroid Build Coastguard Worker 
1794*a67afe4dSAndroid Build Coastguard Worker    idat->file = file;
1795*a67afe4dSAndroid Build Coastguard Worker    idat->global = file->global;
1796*a67afe4dSAndroid Build Coastguard Worker 
1797*a67afe4dSAndroid Build Coastguard Worker    /* Initialize the tail to the pre-allocated buffer and set the count to 0
1798*a67afe4dSAndroid Build Coastguard Worker     * (empty.)
1799*a67afe4dSAndroid Build Coastguard Worker     */
1800*a67afe4dSAndroid Build Coastguard Worker    idat->global->idat_cache.count = 0;
1801*a67afe4dSAndroid Build Coastguard Worker    idat->idat_list_head = idat->idat_list_tail = &idat->global->idat_cache;
1802*a67afe4dSAndroid Build Coastguard Worker 
1803*a67afe4dSAndroid Build Coastguard Worker    /* Now the chunk.  The allocator calls the initializer of the new chunk and
1804*a67afe4dSAndroid Build Coastguard Worker     * stores the result in file->chunk:
1805*a67afe4dSAndroid Build Coastguard Worker     */
1806*a67afe4dSAndroid Build Coastguard Worker    file->alloc(file, 0/*chunk*/);
1807*a67afe4dSAndroid Build Coastguard Worker    assert(file->chunk != NULL);
1808*a67afe4dSAndroid Build Coastguard Worker 
1809*a67afe4dSAndroid Build Coastguard Worker    /* And store this for cleanup (and to check for double alloc or failure to
1810*a67afe4dSAndroid Build Coastguard Worker     * free.)
1811*a67afe4dSAndroid Build Coastguard Worker     */
1812*a67afe4dSAndroid Build Coastguard Worker    file->idat = idat;
1813*a67afe4dSAndroid Build Coastguard Worker }
1814*a67afe4dSAndroid Build Coastguard Worker 
1815*a67afe4dSAndroid Build Coastguard Worker static png_uint_32
rechunk_length(struct IDAT * idat,int start)1816*a67afe4dSAndroid Build Coastguard Worker rechunk_length(struct IDAT *idat, int start)
1817*a67afe4dSAndroid Build Coastguard Worker    /* Return the length for the next IDAT chunk, taking into account
1818*a67afe4dSAndroid Build Coastguard Worker     * rechunking.
1819*a67afe4dSAndroid Build Coastguard Worker     */
1820*a67afe4dSAndroid Build Coastguard Worker {
1821*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 len = idat->global->idat_max;
1822*a67afe4dSAndroid Build Coastguard Worker 
1823*a67afe4dSAndroid Build Coastguard Worker    if (len == 0) /* use original chunk lengths */
1824*a67afe4dSAndroid Build Coastguard Worker    {
1825*a67afe4dSAndroid Build Coastguard Worker       const struct IDAT_list *cur;
1826*a67afe4dSAndroid Build Coastguard Worker       unsigned int count;
1827*a67afe4dSAndroid Build Coastguard Worker 
1828*a67afe4dSAndroid Build Coastguard Worker       if (start)
1829*a67afe4dSAndroid Build Coastguard Worker          return idat->idat_length; /* use the cache */
1830*a67afe4dSAndroid Build Coastguard Worker 
1831*a67afe4dSAndroid Build Coastguard Worker       /* Otherwise rechunk_length is called at the end of a chunk for the length
1832*a67afe4dSAndroid Build Coastguard Worker        * of the next one.
1833*a67afe4dSAndroid Build Coastguard Worker        */
1834*a67afe4dSAndroid Build Coastguard Worker       cur = idat->idat_cur;
1835*a67afe4dSAndroid Build Coastguard Worker       count = idat->idat_count;
1836*a67afe4dSAndroid Build Coastguard Worker 
1837*a67afe4dSAndroid Build Coastguard Worker       assert(idat->idat_index == idat->idat_length &&
1838*a67afe4dSAndroid Build Coastguard Worker          idat->idat_length == cur->lengths[count]);
1839*a67afe4dSAndroid Build Coastguard Worker 
1840*a67afe4dSAndroid Build Coastguard Worker       /* Return length of the *next* chunk */
1841*a67afe4dSAndroid Build Coastguard Worker       if (++count < cur->count)
1842*a67afe4dSAndroid Build Coastguard Worker          return cur->lengths[count];
1843*a67afe4dSAndroid Build Coastguard Worker 
1844*a67afe4dSAndroid Build Coastguard Worker       /* End of this list */
1845*a67afe4dSAndroid Build Coastguard Worker       assert(cur != idat->idat_list_tail);
1846*a67afe4dSAndroid Build Coastguard Worker       cur = cur->next;
1847*a67afe4dSAndroid Build Coastguard Worker       assert(cur != NULL && cur->count > 0);
1848*a67afe4dSAndroid Build Coastguard Worker       return cur->lengths[0];
1849*a67afe4dSAndroid Build Coastguard Worker    }
1850*a67afe4dSAndroid Build Coastguard Worker 
1851*a67afe4dSAndroid Build Coastguard Worker    else /* rechunking */
1852*a67afe4dSAndroid Build Coastguard Worker    {
1853*a67afe4dSAndroid Build Coastguard Worker       /* The chunk size is the lesser of file->idat_max and the number
1854*a67afe4dSAndroid Build Coastguard Worker        * of remaining bytes.
1855*a67afe4dSAndroid Build Coastguard Worker        */
1856*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 have = idat->idat_length - idat->idat_index;
1857*a67afe4dSAndroid Build Coastguard Worker 
1858*a67afe4dSAndroid Build Coastguard Worker       if (len > have)
1859*a67afe4dSAndroid Build Coastguard Worker       {
1860*a67afe4dSAndroid Build Coastguard Worker          struct IDAT_list *cur = idat->idat_cur;
1861*a67afe4dSAndroid Build Coastguard Worker          unsigned int j = idat->idat_count+1; /* the next IDAT in the list */
1862*a67afe4dSAndroid Build Coastguard Worker 
1863*a67afe4dSAndroid Build Coastguard Worker          do
1864*a67afe4dSAndroid Build Coastguard Worker          {
1865*a67afe4dSAndroid Build Coastguard Worker             /* Add up the remaining bytes.  This can't overflow because the
1866*a67afe4dSAndroid Build Coastguard Worker              * individual lengths are always <= 0x7fffffff, so when we add two
1867*a67afe4dSAndroid Build Coastguard Worker              * of them overflow is not possible.
1868*a67afe4dSAndroid Build Coastguard Worker              */
1869*a67afe4dSAndroid Build Coastguard Worker             assert(cur != NULL);
1870*a67afe4dSAndroid Build Coastguard Worker 
1871*a67afe4dSAndroid Build Coastguard Worker             for (;;)
1872*a67afe4dSAndroid Build Coastguard Worker             {
1873*a67afe4dSAndroid Build Coastguard Worker                /* NOTE: IDAT_list::count here, not IDAT_list::length */
1874*a67afe4dSAndroid Build Coastguard Worker                for (; j < cur->count; ++j)
1875*a67afe4dSAndroid Build Coastguard Worker                {
1876*a67afe4dSAndroid Build Coastguard Worker                   have += cur->lengths[j];
1877*a67afe4dSAndroid Build Coastguard Worker                   if (len <= have)
1878*a67afe4dSAndroid Build Coastguard Worker                      return len;
1879*a67afe4dSAndroid Build Coastguard Worker                }
1880*a67afe4dSAndroid Build Coastguard Worker 
1881*a67afe4dSAndroid Build Coastguard Worker                /* If this was the end return the count of the available bytes */
1882*a67afe4dSAndroid Build Coastguard Worker                if (cur == idat->idat_list_tail)
1883*a67afe4dSAndroid Build Coastguard Worker                   return have;
1884*a67afe4dSAndroid Build Coastguard Worker 
1885*a67afe4dSAndroid Build Coastguard Worker                cur = cur->next;
1886*a67afe4dSAndroid Build Coastguard Worker                j = 0;
1887*a67afe4dSAndroid Build Coastguard Worker             }
1888*a67afe4dSAndroid Build Coastguard Worker          }
1889*a67afe4dSAndroid Build Coastguard Worker          while (len > have);
1890*a67afe4dSAndroid Build Coastguard Worker       }
1891*a67afe4dSAndroid Build Coastguard Worker 
1892*a67afe4dSAndroid Build Coastguard Worker       return len;
1893*a67afe4dSAndroid Build Coastguard Worker    }
1894*a67afe4dSAndroid Build Coastguard Worker }
1895*a67afe4dSAndroid Build Coastguard Worker 
1896*a67afe4dSAndroid Build Coastguard Worker static int
process_IDAT(struct file * file)1897*a67afe4dSAndroid Build Coastguard Worker process_IDAT(struct file *file)
1898*a67afe4dSAndroid Build Coastguard Worker    /* Process the IDAT stream, this is the more complex than the preceding
1899*a67afe4dSAndroid Build Coastguard Worker     * cases because the compressed data is spread across multiple IDAT chunks
1900*a67afe4dSAndroid Build Coastguard Worker     * (typically).  Rechunking of the data is not handled here; all this
1901*a67afe4dSAndroid Build Coastguard Worker     * function does is establish whether the zlib header needs to be modified.
1902*a67afe4dSAndroid Build Coastguard Worker     *
1903*a67afe4dSAndroid Build Coastguard Worker     * Initially the function returns false, indicating that the chunk should not
1904*a67afe4dSAndroid Build Coastguard Worker     * be written.  It does this until the last IDAT chunk is passed in, then it
1905*a67afe4dSAndroid Build Coastguard Worker     * checks the zlib data and returns true.
1906*a67afe4dSAndroid Build Coastguard Worker     *
1907*a67afe4dSAndroid Build Coastguard Worker     * It does not return false on a fatal error; it calls stop instead.
1908*a67afe4dSAndroid Build Coastguard Worker     *
1909*a67afe4dSAndroid Build Coastguard Worker     * The caller must have an instantiated (IDAT) control structure and it must
1910*a67afe4dSAndroid Build Coastguard Worker     * have extent over the whole read of the IDAT stream.  For a PNG this means
1911*a67afe4dSAndroid Build Coastguard Worker     * the whole PNG read, for MNG it could have lesser extent.
1912*a67afe4dSAndroid Build Coastguard Worker     */
1913*a67afe4dSAndroid Build Coastguard Worker {
1914*a67afe4dSAndroid Build Coastguard Worker    struct IDAT_list *list;
1915*a67afe4dSAndroid Build Coastguard Worker 
1916*a67afe4dSAndroid Build Coastguard Worker    assert(file->idat != NULL && file->chunk != NULL);
1917*a67afe4dSAndroid Build Coastguard Worker 
1918*a67afe4dSAndroid Build Coastguard Worker    /* We need to first check the entire sequence of IDAT chunks to ensure the
1919*a67afe4dSAndroid Build Coastguard Worker     * stream is in sync.  Do this by building a list of all the chunks and
1920*a67afe4dSAndroid Build Coastguard Worker     * recording the length of each because the length may have been fixed up by
1921*a67afe4dSAndroid Build Coastguard Worker     * sync_stream below.
1922*a67afe4dSAndroid Build Coastguard Worker     *
1923*a67afe4dSAndroid Build Coastguard Worker     * At the end of the list of chunks, where the type of the next chunk is not
1924*a67afe4dSAndroid Build Coastguard Worker     * png_IDAT, process the whole stream using the list data to check validity
1925*a67afe4dSAndroid Build Coastguard Worker     * then return control to the start and rewrite everything.
1926*a67afe4dSAndroid Build Coastguard Worker     */
1927*a67afe4dSAndroid Build Coastguard Worker    list = file->idat->idat_list_tail;
1928*a67afe4dSAndroid Build Coastguard Worker 
1929*a67afe4dSAndroid Build Coastguard Worker    if (list->count == list->length)
1930*a67afe4dSAndroid Build Coastguard Worker    {
1931*a67afe4dSAndroid Build Coastguard Worker       list = IDAT_list_extend(list);
1932*a67afe4dSAndroid Build Coastguard Worker 
1933*a67afe4dSAndroid Build Coastguard Worker       if (list == NULL)
1934*a67afe4dSAndroid Build Coastguard Worker          stop(file, READ_ERROR_CODE, "out of memory");
1935*a67afe4dSAndroid Build Coastguard Worker 
1936*a67afe4dSAndroid Build Coastguard Worker       /* Move to the next block */
1937*a67afe4dSAndroid Build Coastguard Worker       list->count = 0;
1938*a67afe4dSAndroid Build Coastguard Worker       file->idat->idat_list_tail = list;
1939*a67afe4dSAndroid Build Coastguard Worker    }
1940*a67afe4dSAndroid Build Coastguard Worker 
1941*a67afe4dSAndroid Build Coastguard Worker    /* And fill in the next IDAT information buffer. */
1942*a67afe4dSAndroid Build Coastguard Worker    list->lengths[(list->count)++] = file->chunk->chunk_length;
1943*a67afe4dSAndroid Build Coastguard Worker 
1944*a67afe4dSAndroid Build Coastguard Worker    /* The type of the next chunk was recorded in the file control structure by
1945*a67afe4dSAndroid Build Coastguard Worker     * the caller, if this is png_IDAT return 'skip' to the caller.
1946*a67afe4dSAndroid Build Coastguard Worker     */
1947*a67afe4dSAndroid Build Coastguard Worker    if (file->type == png_IDAT)
1948*a67afe4dSAndroid Build Coastguard Worker       return 0; /* skip this for the moment */
1949*a67afe4dSAndroid Build Coastguard Worker 
1950*a67afe4dSAndroid Build Coastguard Worker    /* This is the final IDAT chunk, so run the tests to check for the too far
1951*a67afe4dSAndroid Build Coastguard Worker     * back error and possibly optimize the window bits.  This means going back
1952*a67afe4dSAndroid Build Coastguard Worker     * to the start of the first chunk data, which is stored in the original
1953*a67afe4dSAndroid Build Coastguard Worker     * chunk allocation.
1954*a67afe4dSAndroid Build Coastguard Worker     */
1955*a67afe4dSAndroid Build Coastguard Worker    setpos(file->chunk);
1956*a67afe4dSAndroid Build Coastguard Worker 
1957*a67afe4dSAndroid Build Coastguard Worker    if (zlib_check(file, 0))
1958*a67afe4dSAndroid Build Coastguard Worker    {
1959*a67afe4dSAndroid Build Coastguard Worker       struct IDAT *idat;
1960*a67afe4dSAndroid Build Coastguard Worker       int cmp;
1961*a67afe4dSAndroid Build Coastguard Worker 
1962*a67afe4dSAndroid Build Coastguard Worker       /* The IDAT stream was successfully uncompressed; see whether it
1963*a67afe4dSAndroid Build Coastguard Worker        * contained the correct number of bytes of image data.
1964*a67afe4dSAndroid Build Coastguard Worker        */
1965*a67afe4dSAndroid Build Coastguard Worker       cmp = uarb_cmp(file->image_bytes, file->image_digits,
1966*a67afe4dSAndroid Build Coastguard Worker          file->chunk->uncompressed_bytes, file->chunk->uncompressed_digits);
1967*a67afe4dSAndroid Build Coastguard Worker 
1968*a67afe4dSAndroid Build Coastguard Worker       if (cmp < 0)
1969*a67afe4dSAndroid Build Coastguard Worker          type_message(file, png_IDAT, "extra uncompressed data");
1970*a67afe4dSAndroid Build Coastguard Worker 
1971*a67afe4dSAndroid Build Coastguard Worker       else if (cmp > 0)
1972*a67afe4dSAndroid Build Coastguard Worker          stop(file, LIBPNG_ERROR_CODE, "IDAT: uncompressed data too small");
1973*a67afe4dSAndroid Build Coastguard Worker 
1974*a67afe4dSAndroid Build Coastguard Worker       /* Return the stream to the start of the first IDAT chunk; the length
1975*a67afe4dSAndroid Build Coastguard Worker        * is set in the write case below but the input chunk variables must be
1976*a67afe4dSAndroid Build Coastguard Worker        * set (once) here:
1977*a67afe4dSAndroid Build Coastguard Worker        */
1978*a67afe4dSAndroid Build Coastguard Worker       setpos(file->chunk);
1979*a67afe4dSAndroid Build Coastguard Worker 
1980*a67afe4dSAndroid Build Coastguard Worker       idat = file->idat;
1981*a67afe4dSAndroid Build Coastguard Worker       idat->idat_cur = idat->idat_list_head;
1982*a67afe4dSAndroid Build Coastguard Worker       idat->idat_length = idat->idat_cur->lengths[0];
1983*a67afe4dSAndroid Build Coastguard Worker       idat->idat_count = 0; /* Count of chunks read in current list */
1984*a67afe4dSAndroid Build Coastguard Worker       idat->idat_index = 0; /* Index into chunk data */
1985*a67afe4dSAndroid Build Coastguard Worker 
1986*a67afe4dSAndroid Build Coastguard Worker       /* Update the chunk length to the correct value for the IDAT chunk: */
1987*a67afe4dSAndroid Build Coastguard Worker       file->chunk->chunk_length = rechunk_length(idat, 1/*start*/);
1988*a67afe4dSAndroid Build Coastguard Worker 
1989*a67afe4dSAndroid Build Coastguard Worker       /* Change the state to writing IDAT chunks */
1990*a67afe4dSAndroid Build Coastguard Worker       file->state = STATE_IDAT;
1991*a67afe4dSAndroid Build Coastguard Worker 
1992*a67afe4dSAndroid Build Coastguard Worker       return 1;
1993*a67afe4dSAndroid Build Coastguard Worker    }
1994*a67afe4dSAndroid Build Coastguard Worker 
1995*a67afe4dSAndroid Build Coastguard Worker    else /* Failure to decompress the IDAT stream; give up. */
1996*a67afe4dSAndroid Build Coastguard Worker       stop(file, ZLIB_ERROR_CODE, "could not uncompress IDAT");
1997*a67afe4dSAndroid Build Coastguard Worker }
1998*a67afe4dSAndroid Build Coastguard Worker 
1999*a67afe4dSAndroid Build Coastguard Worker /* ZLIB CONTROL STRUCTURE */
2000*a67afe4dSAndroid Build Coastguard Worker struct zlib
2001*a67afe4dSAndroid Build Coastguard Worker {
2002*a67afe4dSAndroid Build Coastguard Worker    /* ANCESTORS */
2003*a67afe4dSAndroid Build Coastguard Worker    struct IDAT *  idat;          /* NOTE: May be NULL */
2004*a67afe4dSAndroid Build Coastguard Worker    struct chunk * chunk;
2005*a67afe4dSAndroid Build Coastguard Worker    struct file *  file;
2006*a67afe4dSAndroid Build Coastguard Worker    struct global *global;
2007*a67afe4dSAndroid Build Coastguard Worker 
2008*a67afe4dSAndroid Build Coastguard Worker    /* GLOBAL ZLIB INFORMATION: SET BY THE CALLER */
2009*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    rewrite_offset;
2010*a67afe4dSAndroid Build Coastguard Worker 
2011*a67afe4dSAndroid Build Coastguard Worker    /* GLOBAL ZLIB INFORMATION: SET BY THE ZLIB READ CODE */
2012*a67afe4dSAndroid Build Coastguard Worker    udigit         compressed_bytes[5];
2013*a67afe4dSAndroid Build Coastguard Worker    int            compressed_digits;
2014*a67afe4dSAndroid Build Coastguard Worker    udigit         uncompressed_bytes[5];
2015*a67afe4dSAndroid Build Coastguard Worker    int            uncompressed_digits;
2016*a67afe4dSAndroid Build Coastguard Worker    int            file_bits;             /* window bits from the file */
2017*a67afe4dSAndroid Build Coastguard Worker    int            ok_bits;               /* Set <16 on a successful read */
2018*a67afe4dSAndroid Build Coastguard Worker    int            cksum;                 /* Set on a checksum error */
2019*a67afe4dSAndroid Build Coastguard Worker 
2020*a67afe4dSAndroid Build Coastguard Worker    /* PROTECTED ZLIB INFORMATION: USED BY THE ZLIB ROUTINES */
2021*a67afe4dSAndroid Build Coastguard Worker    z_stream       z;
2022*a67afe4dSAndroid Build Coastguard Worker    png_uint_32    extra_bytes;   /* Count of extra compressed bytes */
2023*a67afe4dSAndroid Build Coastguard Worker    int            state;
2024*a67afe4dSAndroid Build Coastguard Worker    int            rc;            /* Last return code */
2025*a67afe4dSAndroid Build Coastguard Worker    int            window_bits;   /* 0 if no change */
2026*a67afe4dSAndroid Build Coastguard Worker    png_byte       header[2];
2027*a67afe4dSAndroid Build Coastguard Worker };
2028*a67afe4dSAndroid Build Coastguard Worker 
2029*a67afe4dSAndroid Build Coastguard Worker static const char *
zlib_flevel(struct zlib * zlib)2030*a67afe4dSAndroid Build Coastguard Worker zlib_flevel(struct zlib *zlib)
2031*a67afe4dSAndroid Build Coastguard Worker {
2032*a67afe4dSAndroid Build Coastguard Worker    switch (zlib->header[1] >> 6)
2033*a67afe4dSAndroid Build Coastguard Worker    {
2034*a67afe4dSAndroid Build Coastguard Worker       case 0:  return "supfast";
2035*a67afe4dSAndroid Build Coastguard Worker       case 1:  return "stdfast";
2036*a67afe4dSAndroid Build Coastguard Worker       case 2:  return "default";
2037*a67afe4dSAndroid Build Coastguard Worker       case 3:  return "maximum";
2038*a67afe4dSAndroid Build Coastguard Worker       default: assert(UNREACHED);
2039*a67afe4dSAndroid Build Coastguard Worker    }
2040*a67afe4dSAndroid Build Coastguard Worker 
2041*a67afe4dSAndroid Build Coastguard Worker    return "COMPILER BUG";
2042*a67afe4dSAndroid Build Coastguard Worker }
2043*a67afe4dSAndroid Build Coastguard Worker 
2044*a67afe4dSAndroid Build Coastguard Worker static const char *
zlib_rc(struct zlib * zlib)2045*a67afe4dSAndroid Build Coastguard Worker zlib_rc(struct zlib *zlib)
2046*a67afe4dSAndroid Build Coastguard Worker    /* Return a string for the zlib return code */
2047*a67afe4dSAndroid Build Coastguard Worker {
2048*a67afe4dSAndroid Build Coastguard Worker    switch (zlib->rc)
2049*a67afe4dSAndroid Build Coastguard Worker    {
2050*a67afe4dSAndroid Build Coastguard Worker       case Z_OK:              return "Z_OK";
2051*a67afe4dSAndroid Build Coastguard Worker       case Z_STREAM_END:      return "Z_STREAM_END";
2052*a67afe4dSAndroid Build Coastguard Worker       case Z_NEED_DICT:       return "Z_NEED_DICT";
2053*a67afe4dSAndroid Build Coastguard Worker       case Z_ERRNO:           return "Z_ERRNO";
2054*a67afe4dSAndroid Build Coastguard Worker       case Z_STREAM_ERROR:    return "Z_STREAM_ERROR";
2055*a67afe4dSAndroid Build Coastguard Worker       case Z_DATA_ERROR:      return "Z_DATA_ERROR";
2056*a67afe4dSAndroid Build Coastguard Worker       case Z_MEM_ERROR:       return "Z_MEM_ERROR";
2057*a67afe4dSAndroid Build Coastguard Worker       case Z_BUF_ERROR:       return "Z_BUF_ERROR";
2058*a67afe4dSAndroid Build Coastguard Worker       case Z_VERSION_ERROR:   return "Z_VERSION_ERROR";
2059*a67afe4dSAndroid Build Coastguard Worker       default:                return "Z_*INVALID_RC*";
2060*a67afe4dSAndroid Build Coastguard Worker    }
2061*a67afe4dSAndroid Build Coastguard Worker }
2062*a67afe4dSAndroid Build Coastguard Worker 
2063*a67afe4dSAndroid Build Coastguard Worker static void
zlib_message(struct zlib * zlib,int unexpected)2064*a67afe4dSAndroid Build Coastguard Worker zlib_message(struct zlib *zlib, int unexpected)
2065*a67afe4dSAndroid Build Coastguard Worker    /* Output a message given a zlib rc */
2066*a67afe4dSAndroid Build Coastguard Worker {
2067*a67afe4dSAndroid Build Coastguard Worker    if (zlib->global->errors)
2068*a67afe4dSAndroid Build Coastguard Worker    {
2069*a67afe4dSAndroid Build Coastguard Worker       const char *reason = zlib->z.msg;
2070*a67afe4dSAndroid Build Coastguard Worker 
2071*a67afe4dSAndroid Build Coastguard Worker       if (reason == NULL)
2072*a67afe4dSAndroid Build Coastguard Worker          reason = "[no message]";
2073*a67afe4dSAndroid Build Coastguard Worker 
2074*a67afe4dSAndroid Build Coastguard Worker       fputs(zlib->file->file_name, stderr);
2075*a67afe4dSAndroid Build Coastguard Worker       type_sep(stderr);
2076*a67afe4dSAndroid Build Coastguard Worker       type_name(zlib->chunk->chunk_type, stderr);
2077*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, ": %szlib error: %d (%s) (%s)\n",
2078*a67afe4dSAndroid Build Coastguard Worker          unexpected ? "unexpected " : "", zlib->rc, zlib_rc(zlib), reason);
2079*a67afe4dSAndroid Build Coastguard Worker    }
2080*a67afe4dSAndroid Build Coastguard Worker }
2081*a67afe4dSAndroid Build Coastguard Worker 
2082*a67afe4dSAndroid Build Coastguard Worker static void
zlib_end(struct zlib * zlib)2083*a67afe4dSAndroid Build Coastguard Worker zlib_end(struct zlib *zlib)
2084*a67afe4dSAndroid Build Coastguard Worker {
2085*a67afe4dSAndroid Build Coastguard Worker    /* Output the summary line now; this ensures a summary line always gets
2086*a67afe4dSAndroid Build Coastguard Worker     * output regardless of the manner of exit.
2087*a67afe4dSAndroid Build Coastguard Worker     */
2088*a67afe4dSAndroid Build Coastguard Worker    if (!zlib->global->quiet)
2089*a67afe4dSAndroid Build Coastguard Worker    {
2090*a67afe4dSAndroid Build Coastguard Worker       if (zlib->ok_bits < 16) /* stream was read ok */
2091*a67afe4dSAndroid Build Coastguard Worker       {
2092*a67afe4dSAndroid Build Coastguard Worker          const char *reason;
2093*a67afe4dSAndroid Build Coastguard Worker 
2094*a67afe4dSAndroid Build Coastguard Worker          if (zlib->cksum)
2095*a67afe4dSAndroid Build Coastguard Worker             reason = "CHK"; /* checksum error */
2096*a67afe4dSAndroid Build Coastguard Worker 
2097*a67afe4dSAndroid Build Coastguard Worker          else if (zlib->ok_bits > zlib->file_bits)
2098*a67afe4dSAndroid Build Coastguard Worker             reason = "TFB"; /* fixing a too-far-back error */
2099*a67afe4dSAndroid Build Coastguard Worker 
2100*a67afe4dSAndroid Build Coastguard Worker          else if (zlib->ok_bits == zlib->file_bits)
2101*a67afe4dSAndroid Build Coastguard Worker             reason = "OK ";
2102*a67afe4dSAndroid Build Coastguard Worker 
2103*a67afe4dSAndroid Build Coastguard Worker          else
2104*a67afe4dSAndroid Build Coastguard Worker             reason = "OPT"; /* optimizing window bits */
2105*a67afe4dSAndroid Build Coastguard Worker 
2106*a67afe4dSAndroid Build Coastguard Worker          /* SUMMARY FORMAT (for a successful zlib inflate):
2107*a67afe4dSAndroid Build Coastguard Worker           *
2108*a67afe4dSAndroid Build Coastguard Worker           * IDAT reason flevel file-bits ok-bits compressed uncompressed file
2109*a67afe4dSAndroid Build Coastguard Worker           */
2110*a67afe4dSAndroid Build Coastguard Worker          type_name(zlib->chunk->chunk_type, stdout);
2111*a67afe4dSAndroid Build Coastguard Worker          printf(" %s %s %d %d ", reason, zlib_flevel(zlib), zlib->file_bits,
2112*a67afe4dSAndroid Build Coastguard Worker             zlib->ok_bits);
2113*a67afe4dSAndroid Build Coastguard Worker          uarb_print(zlib->compressed_bytes, zlib->compressed_digits, stdout);
2114*a67afe4dSAndroid Build Coastguard Worker          putc(' ', stdout);
2115*a67afe4dSAndroid Build Coastguard Worker          uarb_print(zlib->uncompressed_bytes, zlib->uncompressed_digits,
2116*a67afe4dSAndroid Build Coastguard Worker             stdout);
2117*a67afe4dSAndroid Build Coastguard Worker          putc(' ', stdout);
2118*a67afe4dSAndroid Build Coastguard Worker          fputs(zlib->file->file_name, stdout);
2119*a67afe4dSAndroid Build Coastguard Worker          putc('\n', stdout);
2120*a67afe4dSAndroid Build Coastguard Worker       }
2121*a67afe4dSAndroid Build Coastguard Worker 
2122*a67afe4dSAndroid Build Coastguard Worker       else
2123*a67afe4dSAndroid Build Coastguard Worker       {
2124*a67afe4dSAndroid Build Coastguard Worker          /* This is a zlib read error; the chunk will be skipped.  For an IDAT
2125*a67afe4dSAndroid Build Coastguard Worker           * stream this will also cause a fatal read error (via stop()).
2126*a67afe4dSAndroid Build Coastguard Worker           *
2127*a67afe4dSAndroid Build Coastguard Worker           * SUMMARY FORMAT:
2128*a67afe4dSAndroid Build Coastguard Worker           *
2129*a67afe4dSAndroid Build Coastguard Worker           * IDAT SKP flevel file-bits z-rc compressed message file
2130*a67afe4dSAndroid Build Coastguard Worker           *
2131*a67afe4dSAndroid Build Coastguard Worker           * z-rc is the zlib failure code; message is the error message with
2132*a67afe4dSAndroid Build Coastguard Worker           * spaces replaced by '-'.  The compressed byte count indicates where
2133*a67afe4dSAndroid Build Coastguard Worker           * in the zlib stream the error occurred.
2134*a67afe4dSAndroid Build Coastguard Worker           */
2135*a67afe4dSAndroid Build Coastguard Worker          type_name(zlib->chunk->chunk_type, stdout);
2136*a67afe4dSAndroid Build Coastguard Worker          printf(" SKP %s %d %s ", zlib_flevel(zlib), zlib->file_bits,
2137*a67afe4dSAndroid Build Coastguard Worker             zlib_rc(zlib));
2138*a67afe4dSAndroid Build Coastguard Worker          uarb_print(zlib->compressed_bytes, zlib->compressed_digits, stdout);
2139*a67afe4dSAndroid Build Coastguard Worker          putc(' ', stdout);
2140*a67afe4dSAndroid Build Coastguard Worker          emit_string(zlib->z.msg ? zlib->z.msg : "[no_message]", stdout);
2141*a67afe4dSAndroid Build Coastguard Worker          putc(' ', stdout);
2142*a67afe4dSAndroid Build Coastguard Worker          fputs(zlib->file->file_name, stdout);
2143*a67afe4dSAndroid Build Coastguard Worker          putc('\n', stdout);
2144*a67afe4dSAndroid Build Coastguard Worker       }
2145*a67afe4dSAndroid Build Coastguard Worker    }
2146*a67afe4dSAndroid Build Coastguard Worker 
2147*a67afe4dSAndroid Build Coastguard Worker    if (zlib->state >= 0)
2148*a67afe4dSAndroid Build Coastguard Worker    {
2149*a67afe4dSAndroid Build Coastguard Worker       zlib->rc = inflateEnd(&zlib->z);
2150*a67afe4dSAndroid Build Coastguard Worker 
2151*a67afe4dSAndroid Build Coastguard Worker       if (zlib->rc != Z_OK)
2152*a67afe4dSAndroid Build Coastguard Worker          zlib_message(zlib, 1/*unexpected*/);
2153*a67afe4dSAndroid Build Coastguard Worker    }
2154*a67afe4dSAndroid Build Coastguard Worker 
2155*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*zlib);
2156*a67afe4dSAndroid Build Coastguard Worker }
2157*a67afe4dSAndroid Build Coastguard Worker 
2158*a67afe4dSAndroid Build Coastguard Worker static int
zlib_reset(struct zlib * zlib,int window_bits)2159*a67afe4dSAndroid Build Coastguard Worker zlib_reset(struct zlib *zlib, int window_bits)
2160*a67afe4dSAndroid Build Coastguard Worker    /* Reinitializes a zlib with a different window_bits */
2161*a67afe4dSAndroid Build Coastguard Worker {
2162*a67afe4dSAndroid Build Coastguard Worker    assert(zlib->state >= 0); /* initialized by zlib_init */
2163*a67afe4dSAndroid Build Coastguard Worker 
2164*a67afe4dSAndroid Build Coastguard Worker    zlib->z.next_in = Z_NULL;
2165*a67afe4dSAndroid Build Coastguard Worker    zlib->z.avail_in = 0;
2166*a67afe4dSAndroid Build Coastguard Worker    zlib->z.next_out = Z_NULL;
2167*a67afe4dSAndroid Build Coastguard Worker    zlib->z.avail_out = 0;
2168*a67afe4dSAndroid Build Coastguard Worker 
2169*a67afe4dSAndroid Build Coastguard Worker    zlib->window_bits = window_bits;
2170*a67afe4dSAndroid Build Coastguard Worker    zlib->compressed_digits = 0;
2171*a67afe4dSAndroid Build Coastguard Worker    zlib->uncompressed_digits = 0;
2172*a67afe4dSAndroid Build Coastguard Worker 
2173*a67afe4dSAndroid Build Coastguard Worker    zlib->state = 0; /* initialized, once */
2174*a67afe4dSAndroid Build Coastguard Worker    zlib->rc = inflateReset2(&zlib->z, 0);
2175*a67afe4dSAndroid Build Coastguard Worker    if (zlib->rc != Z_OK)
2176*a67afe4dSAndroid Build Coastguard Worker    {
2177*a67afe4dSAndroid Build Coastguard Worker       zlib_message(zlib, 1/*unexpected*/);
2178*a67afe4dSAndroid Build Coastguard Worker       return 0;
2179*a67afe4dSAndroid Build Coastguard Worker    }
2180*a67afe4dSAndroid Build Coastguard Worker 
2181*a67afe4dSAndroid Build Coastguard Worker    return 1;
2182*a67afe4dSAndroid Build Coastguard Worker }
2183*a67afe4dSAndroid Build Coastguard Worker 
2184*a67afe4dSAndroid Build Coastguard Worker static int
zlib_init(struct zlib * zlib,struct IDAT * idat,struct chunk * chunk,int window_bits,png_uint_32 offset)2185*a67afe4dSAndroid Build Coastguard Worker zlib_init(struct zlib *zlib, struct IDAT *idat, struct chunk *chunk,
2186*a67afe4dSAndroid Build Coastguard Worker    int window_bits, png_uint_32 offset)
2187*a67afe4dSAndroid Build Coastguard Worker    /* Initialize a zlib_control; the result is true/false */
2188*a67afe4dSAndroid Build Coastguard Worker {
2189*a67afe4dSAndroid Build Coastguard Worker    CLEAR(*zlib);
2190*a67afe4dSAndroid Build Coastguard Worker 
2191*a67afe4dSAndroid Build Coastguard Worker    zlib->idat = idat;
2192*a67afe4dSAndroid Build Coastguard Worker    zlib->chunk = chunk;
2193*a67afe4dSAndroid Build Coastguard Worker    zlib->file = chunk->file;
2194*a67afe4dSAndroid Build Coastguard Worker    zlib->global = chunk->global;
2195*a67afe4dSAndroid Build Coastguard Worker    zlib->rewrite_offset = offset; /* never changed for this zlib */
2196*a67afe4dSAndroid Build Coastguard Worker 
2197*a67afe4dSAndroid Build Coastguard Worker    /* *_out does not need to be set: */
2198*a67afe4dSAndroid Build Coastguard Worker    zlib->z.next_in = Z_NULL;
2199*a67afe4dSAndroid Build Coastguard Worker    zlib->z.avail_in = 0;
2200*a67afe4dSAndroid Build Coastguard Worker    zlib->z.zalloc = Z_NULL;
2201*a67afe4dSAndroid Build Coastguard Worker    zlib->z.zfree = Z_NULL;
2202*a67afe4dSAndroid Build Coastguard Worker    zlib->z.opaque = Z_NULL;
2203*a67afe4dSAndroid Build Coastguard Worker 
2204*a67afe4dSAndroid Build Coastguard Worker    zlib->state = -1;
2205*a67afe4dSAndroid Build Coastguard Worker    zlib->window_bits = window_bits;
2206*a67afe4dSAndroid Build Coastguard Worker 
2207*a67afe4dSAndroid Build Coastguard Worker    zlib->compressed_digits = 0;
2208*a67afe4dSAndroid Build Coastguard Worker    zlib->uncompressed_digits = 0;
2209*a67afe4dSAndroid Build Coastguard Worker 
2210*a67afe4dSAndroid Build Coastguard Worker    /* These values are sticky across reset (in addition to the stuff in the
2211*a67afe4dSAndroid Build Coastguard Worker     * first block, which is actually constant.)
2212*a67afe4dSAndroid Build Coastguard Worker     */
2213*a67afe4dSAndroid Build Coastguard Worker    zlib->file_bits = 24;
2214*a67afe4dSAndroid Build Coastguard Worker    zlib->ok_bits = 16; /* unset */
2215*a67afe4dSAndroid Build Coastguard Worker    zlib->cksum = 0; /* set when a checksum error is detected */
2216*a67afe4dSAndroid Build Coastguard Worker 
2217*a67afe4dSAndroid Build Coastguard Worker    /* '0' means use the header; inflateInit2 should always succeed because it
2218*a67afe4dSAndroid Build Coastguard Worker     * does nothing apart from allocating the internal zstate.
2219*a67afe4dSAndroid Build Coastguard Worker     */
2220*a67afe4dSAndroid Build Coastguard Worker    zlib->rc = inflateInit2(&zlib->z, 0);
2221*a67afe4dSAndroid Build Coastguard Worker    if (zlib->rc != Z_OK)
2222*a67afe4dSAndroid Build Coastguard Worker    {
2223*a67afe4dSAndroid Build Coastguard Worker       zlib_message(zlib, 1/*unexpected*/);
2224*a67afe4dSAndroid Build Coastguard Worker       return 0;
2225*a67afe4dSAndroid Build Coastguard Worker    }
2226*a67afe4dSAndroid Build Coastguard Worker 
2227*a67afe4dSAndroid Build Coastguard Worker    else
2228*a67afe4dSAndroid Build Coastguard Worker    {
2229*a67afe4dSAndroid Build Coastguard Worker       zlib->state = 0; /* initialized */
2230*a67afe4dSAndroid Build Coastguard Worker       return 1;
2231*a67afe4dSAndroid Build Coastguard Worker    }
2232*a67afe4dSAndroid Build Coastguard Worker }
2233*a67afe4dSAndroid Build Coastguard Worker 
2234*a67afe4dSAndroid Build Coastguard Worker static int
max_window_bits(uarbc size,int ndigits)2235*a67afe4dSAndroid Build Coastguard Worker max_window_bits(uarbc size, int ndigits)
2236*a67afe4dSAndroid Build Coastguard Worker    /* Return the zlib stream window bits required for data of the given size. */
2237*a67afe4dSAndroid Build Coastguard Worker {
2238*a67afe4dSAndroid Build Coastguard Worker    png_uint_16 cb;
2239*a67afe4dSAndroid Build Coastguard Worker 
2240*a67afe4dSAndroid Build Coastguard Worker    if (ndigits > 1)
2241*a67afe4dSAndroid Build Coastguard Worker       return 15;
2242*a67afe4dSAndroid Build Coastguard Worker 
2243*a67afe4dSAndroid Build Coastguard Worker    cb = size[0];
2244*a67afe4dSAndroid Build Coastguard Worker 
2245*a67afe4dSAndroid Build Coastguard Worker    if (cb > 16384) return 15;
2246*a67afe4dSAndroid Build Coastguard Worker    if (cb >  8192) return 14;
2247*a67afe4dSAndroid Build Coastguard Worker    if (cb >  4096) return 13;
2248*a67afe4dSAndroid Build Coastguard Worker    if (cb >  2048) return 12;
2249*a67afe4dSAndroid Build Coastguard Worker    if (cb >  1024) return 11;
2250*a67afe4dSAndroid Build Coastguard Worker    if (cb >   512) return 10;
2251*a67afe4dSAndroid Build Coastguard Worker    if (cb >   256) return  9;
2252*a67afe4dSAndroid Build Coastguard Worker    return 8;
2253*a67afe4dSAndroid Build Coastguard Worker }
2254*a67afe4dSAndroid Build Coastguard Worker 
2255*a67afe4dSAndroid Build Coastguard Worker static int
zlib_advance(struct zlib * zlib,png_uint_32 nbytes)2256*a67afe4dSAndroid Build Coastguard Worker zlib_advance(struct zlib *zlib, png_uint_32 nbytes)
2257*a67afe4dSAndroid Build Coastguard Worker    /* Read nbytes compressed bytes; the stream will be initialized if required.
2258*a67afe4dSAndroid Build Coastguard Worker     * Bytes are always being reread and errors are fatal.  The return code is as
2259*a67afe4dSAndroid Build Coastguard Worker     * follows:
2260*a67afe4dSAndroid Build Coastguard Worker     *
2261*a67afe4dSAndroid Build Coastguard Worker     *    -1: saw the "too far back" error
2262*a67afe4dSAndroid Build Coastguard Worker     *     0: ok, keep going
2263*a67afe4dSAndroid Build Coastguard Worker     *     1: saw Z_STREAM_END (zlib->extra_bytes indicates too much data)
2264*a67afe4dSAndroid Build Coastguard Worker     *     2: a zlib error that cannot be corrected (error message already
2265*a67afe4dSAndroid Build Coastguard Worker     *        output if required.)
2266*a67afe4dSAndroid Build Coastguard Worker     */
2267*a67afe4dSAndroid Build Coastguard Worker #  define ZLIB_TOO_FAR_BACK (-1)
2268*a67afe4dSAndroid Build Coastguard Worker #  define ZLIB_OK           0
2269*a67afe4dSAndroid Build Coastguard Worker #  define ZLIB_STREAM_END   1
2270*a67afe4dSAndroid Build Coastguard Worker #  define ZLIB_FATAL        2
2271*a67afe4dSAndroid Build Coastguard Worker {
2272*a67afe4dSAndroid Build Coastguard Worker    int state = zlib->state;
2273*a67afe4dSAndroid Build Coastguard Worker    int endrc = ZLIB_OK;
2274*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 in_bytes = 0;
2275*a67afe4dSAndroid Build Coastguard Worker    struct file *file = zlib->file;
2276*a67afe4dSAndroid Build Coastguard Worker 
2277*a67afe4dSAndroid Build Coastguard Worker    assert(state >= 0);
2278*a67afe4dSAndroid Build Coastguard Worker 
2279*a67afe4dSAndroid Build Coastguard Worker    while (in_bytes < nbytes && endrc == ZLIB_OK)
2280*a67afe4dSAndroid Build Coastguard Worker    {
2281*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 out_bytes;
2282*a67afe4dSAndroid Build Coastguard Worker       int flush;
2283*a67afe4dSAndroid Build Coastguard Worker       png_byte bIn = reread_byte(file);
2284*a67afe4dSAndroid Build Coastguard Worker       png_byte bOut;
2285*a67afe4dSAndroid Build Coastguard Worker 
2286*a67afe4dSAndroid Build Coastguard Worker       switch (state)
2287*a67afe4dSAndroid Build Coastguard Worker       {
2288*a67afe4dSAndroid Build Coastguard Worker          case 0: /* first header byte */
2289*a67afe4dSAndroid Build Coastguard Worker             {
2290*a67afe4dSAndroid Build Coastguard Worker                int file_bits = 8+(bIn >> 4);
2291*a67afe4dSAndroid Build Coastguard Worker                int new_bits = zlib->window_bits;
2292*a67afe4dSAndroid Build Coastguard Worker 
2293*a67afe4dSAndroid Build Coastguard Worker                zlib->file_bits = file_bits;
2294*a67afe4dSAndroid Build Coastguard Worker 
2295*a67afe4dSAndroid Build Coastguard Worker                /* Check against the existing value - it may not need to be
2296*a67afe4dSAndroid Build Coastguard Worker                 * changed.  Note that a bogus file_bits is allowed through once,
2297*a67afe4dSAndroid Build Coastguard Worker                 * to see if it works, but the window_bits value is set to 15,
2298*a67afe4dSAndroid Build Coastguard Worker                 * the maximum.
2299*a67afe4dSAndroid Build Coastguard Worker                 */
2300*a67afe4dSAndroid Build Coastguard Worker                if (new_bits == 0) /* no change */
2301*a67afe4dSAndroid Build Coastguard Worker                   zlib->window_bits = ((file_bits > 15) ? 15 : file_bits);
2302*a67afe4dSAndroid Build Coastguard Worker 
2303*a67afe4dSAndroid Build Coastguard Worker                else if (new_bits != file_bits) /* rewrite required */
2304*a67afe4dSAndroid Build Coastguard Worker                   bIn = (png_byte)((bIn & 0xf) + ((new_bits-8) << 4));
2305*a67afe4dSAndroid Build Coastguard Worker             }
2306*a67afe4dSAndroid Build Coastguard Worker 
2307*a67afe4dSAndroid Build Coastguard Worker             zlib->header[0] = bIn;
2308*a67afe4dSAndroid Build Coastguard Worker             zlib->state = state = 1;
2309*a67afe4dSAndroid Build Coastguard Worker             break;
2310*a67afe4dSAndroid Build Coastguard Worker 
2311*a67afe4dSAndroid Build Coastguard Worker          case 1: /* second header byte */
2312*a67afe4dSAndroid Build Coastguard Worker             {
2313*a67afe4dSAndroid Build Coastguard Worker                int b2 = bIn & 0xe0; /* top 3 bits */
2314*a67afe4dSAndroid Build Coastguard Worker 
2315*a67afe4dSAndroid Build Coastguard Worker                /* The checksum calculation, on the first 11 bits: */
2316*a67afe4dSAndroid Build Coastguard Worker                b2 += 0x1f - ((zlib->header[0] << 8) + b2) % 0x1f;
2317*a67afe4dSAndroid Build Coastguard Worker 
2318*a67afe4dSAndroid Build Coastguard Worker                /* Update the checksum byte if required: */
2319*a67afe4dSAndroid Build Coastguard Worker                if (bIn != b2)
2320*a67afe4dSAndroid Build Coastguard Worker                {
2321*a67afe4dSAndroid Build Coastguard Worker                   /* If the first byte wasn't changed this indicates an error in
2322*a67afe4dSAndroid Build Coastguard Worker                    * the checksum calculation; signal this by setting 'cksum'.
2323*a67afe4dSAndroid Build Coastguard Worker                    */
2324*a67afe4dSAndroid Build Coastguard Worker                   if (zlib->file_bits == zlib->window_bits)
2325*a67afe4dSAndroid Build Coastguard Worker                      zlib->cksum = 1;
2326*a67afe4dSAndroid Build Coastguard Worker 
2327*a67afe4dSAndroid Build Coastguard Worker                   bIn = (png_byte)b2;
2328*a67afe4dSAndroid Build Coastguard Worker                }
2329*a67afe4dSAndroid Build Coastguard Worker             }
2330*a67afe4dSAndroid Build Coastguard Worker 
2331*a67afe4dSAndroid Build Coastguard Worker             zlib->header[1] = bIn;
2332*a67afe4dSAndroid Build Coastguard Worker             zlib->state = state = 2;
2333*a67afe4dSAndroid Build Coastguard Worker             break;
2334*a67afe4dSAndroid Build Coastguard Worker 
2335*a67afe4dSAndroid Build Coastguard Worker          default: /* After the header bytes */
2336*a67afe4dSAndroid Build Coastguard Worker             break;
2337*a67afe4dSAndroid Build Coastguard Worker       }
2338*a67afe4dSAndroid Build Coastguard Worker 
2339*a67afe4dSAndroid Build Coastguard Worker       /* For some streams, perhaps only those compressed with 'superfast
2340*a67afe4dSAndroid Build Coastguard Worker        * compression' (which results in a lot of copying) Z_BUF_ERROR can happen
2341*a67afe4dSAndroid Build Coastguard Worker        * immediately after all output has been flushed on the next input byte.
2342*a67afe4dSAndroid Build Coastguard Worker        * This is handled below when Z_BUF_ERROR is detected by adding an output
2343*a67afe4dSAndroid Build Coastguard Worker        * byte.
2344*a67afe4dSAndroid Build Coastguard Worker        */
2345*a67afe4dSAndroid Build Coastguard Worker       zlib->z.next_in = &bIn;
2346*a67afe4dSAndroid Build Coastguard Worker       zlib->z.avail_in = 1;
2347*a67afe4dSAndroid Build Coastguard Worker       zlib->z.next_out = &bOut;
2348*a67afe4dSAndroid Build Coastguard Worker       zlib->z.avail_out = 0;     /* Initially */
2349*a67afe4dSAndroid Build Coastguard Worker 
2350*a67afe4dSAndroid Build Coastguard Worker       /* Initially use Z_NO_FLUSH in an attempt to persuade zlib to look at this
2351*a67afe4dSAndroid Build Coastguard Worker        * byte without confusing what is going on with output.
2352*a67afe4dSAndroid Build Coastguard Worker        */
2353*a67afe4dSAndroid Build Coastguard Worker       flush = Z_NO_FLUSH;
2354*a67afe4dSAndroid Build Coastguard Worker       out_bytes = 0;
2355*a67afe4dSAndroid Build Coastguard Worker 
2356*a67afe4dSAndroid Build Coastguard Worker       /* NOTE: expression 3 is only evaluated on 'continue', because of the
2357*a67afe4dSAndroid Build Coastguard Worker        * 'break' at the end of this loop below.
2358*a67afe4dSAndroid Build Coastguard Worker        */
2359*a67afe4dSAndroid Build Coastguard Worker       for (;endrc == ZLIB_OK;
2360*a67afe4dSAndroid Build Coastguard Worker          flush = Z_SYNC_FLUSH,
2361*a67afe4dSAndroid Build Coastguard Worker          zlib->z.next_out = &bOut,
2362*a67afe4dSAndroid Build Coastguard Worker          zlib->z.avail_out = 1,
2363*a67afe4dSAndroid Build Coastguard Worker          ++out_bytes)
2364*a67afe4dSAndroid Build Coastguard Worker       {
2365*a67afe4dSAndroid Build Coastguard Worker          zlib->rc = inflate(&zlib->z, flush);
2366*a67afe4dSAndroid Build Coastguard Worker          out_bytes -= zlib->z.avail_out;
2367*a67afe4dSAndroid Build Coastguard Worker 
2368*a67afe4dSAndroid Build Coastguard Worker          switch (zlib->rc)
2369*a67afe4dSAndroid Build Coastguard Worker          {
2370*a67afe4dSAndroid Build Coastguard Worker             case Z_BUF_ERROR:
2371*a67afe4dSAndroid Build Coastguard Worker                if (zlib->z.avail_out == 0)
2372*a67afe4dSAndroid Build Coastguard Worker                   continue; /* Try another output byte. */
2373*a67afe4dSAndroid Build Coastguard Worker 
2374*a67afe4dSAndroid Build Coastguard Worker                if (zlib->z.avail_in == 0)
2375*a67afe4dSAndroid Build Coastguard Worker                   break; /* Try another input byte */
2376*a67afe4dSAndroid Build Coastguard Worker 
2377*a67afe4dSAndroid Build Coastguard Worker                /* Both avail_out and avail_in are 1 yet zlib returned a code
2378*a67afe4dSAndroid Build Coastguard Worker                 * indicating no progress was possible.  This is unexpected.
2379*a67afe4dSAndroid Build Coastguard Worker                 */
2380*a67afe4dSAndroid Build Coastguard Worker                zlib_message(zlib, 1/*unexpected*/);
2381*a67afe4dSAndroid Build Coastguard Worker                endrc = ZLIB_FATAL; /* stop processing */
2382*a67afe4dSAndroid Build Coastguard Worker                break;
2383*a67afe4dSAndroid Build Coastguard Worker 
2384*a67afe4dSAndroid Build Coastguard Worker             case Z_OK:
2385*a67afe4dSAndroid Build Coastguard Worker                /* Zlib is supposed to have made progress: */
2386*a67afe4dSAndroid Build Coastguard Worker                assert(zlib->z.avail_out == 0 || zlib->z.avail_in == 0);
2387*a67afe4dSAndroid Build Coastguard Worker                continue;
2388*a67afe4dSAndroid Build Coastguard Worker 
2389*a67afe4dSAndroid Build Coastguard Worker             case Z_STREAM_END:
2390*a67afe4dSAndroid Build Coastguard Worker                /* This is the successful end. */
2391*a67afe4dSAndroid Build Coastguard Worker                zlib->state = 3; /* end of stream */
2392*a67afe4dSAndroid Build Coastguard Worker                endrc = ZLIB_STREAM_END;
2393*a67afe4dSAndroid Build Coastguard Worker                break;
2394*a67afe4dSAndroid Build Coastguard Worker 
2395*a67afe4dSAndroid Build Coastguard Worker             case Z_NEED_DICT:
2396*a67afe4dSAndroid Build Coastguard Worker                zlib_message(zlib, 0/*stream error*/);
2397*a67afe4dSAndroid Build Coastguard Worker                endrc = ZLIB_FATAL;
2398*a67afe4dSAndroid Build Coastguard Worker                break;
2399*a67afe4dSAndroid Build Coastguard Worker 
2400*a67afe4dSAndroid Build Coastguard Worker             case Z_DATA_ERROR:
2401*a67afe4dSAndroid Build Coastguard Worker                /* The too far back error can be corrected, others cannot: */
2402*a67afe4dSAndroid Build Coastguard Worker                if (zlib->z.msg != NULL &&
2403*a67afe4dSAndroid Build Coastguard Worker                   strcmp(zlib->z.msg, "invalid distance too far back") == 0)
2404*a67afe4dSAndroid Build Coastguard Worker                {
2405*a67afe4dSAndroid Build Coastguard Worker                   endrc = ZLIB_TOO_FAR_BACK;
2406*a67afe4dSAndroid Build Coastguard Worker                   break;
2407*a67afe4dSAndroid Build Coastguard Worker                }
2408*a67afe4dSAndroid Build Coastguard Worker                /* FALLTHROUGH */
2409*a67afe4dSAndroid Build Coastguard Worker 
2410*a67afe4dSAndroid Build Coastguard Worker             default:
2411*a67afe4dSAndroid Build Coastguard Worker                zlib_message(zlib, 0/*stream error*/);
2412*a67afe4dSAndroid Build Coastguard Worker                endrc = ZLIB_FATAL;
2413*a67afe4dSAndroid Build Coastguard Worker                break;
2414*a67afe4dSAndroid Build Coastguard Worker          } /* switch (inflate rc) */
2415*a67afe4dSAndroid Build Coastguard Worker 
2416*a67afe4dSAndroid Build Coastguard Worker          /* Control gets here when further output is not possible; endrc may
2417*a67afe4dSAndroid Build Coastguard Worker           * still be ZLIB_OK if more input is required.
2418*a67afe4dSAndroid Build Coastguard Worker           */
2419*a67afe4dSAndroid Build Coastguard Worker          break;
2420*a67afe4dSAndroid Build Coastguard Worker       } /* for (output bytes) */
2421*a67afe4dSAndroid Build Coastguard Worker 
2422*a67afe4dSAndroid Build Coastguard Worker       /* Keep a running count of output byte produced: */
2423*a67afe4dSAndroid Build Coastguard Worker       zlib->uncompressed_digits = uarb_add32(zlib->uncompressed_bytes,
2424*a67afe4dSAndroid Build Coastguard Worker          zlib->uncompressed_digits, out_bytes);
2425*a67afe4dSAndroid Build Coastguard Worker 
2426*a67afe4dSAndroid Build Coastguard Worker       /* Keep going, the loop will terminate when endrc is no longer set to
2427*a67afe4dSAndroid Build Coastguard Worker        * ZLIB_OK or all the input bytes have been consumed; meanwhile keep
2428*a67afe4dSAndroid Build Coastguard Worker        * adding input bytes.
2429*a67afe4dSAndroid Build Coastguard Worker        */
2430*a67afe4dSAndroid Build Coastguard Worker       assert(zlib->z.avail_in == 0 || endrc != ZLIB_OK);
2431*a67afe4dSAndroid Build Coastguard Worker 
2432*a67afe4dSAndroid Build Coastguard Worker       in_bytes += 1 - zlib->z.avail_in;
2433*a67afe4dSAndroid Build Coastguard Worker    } /* while (input bytes) */
2434*a67afe4dSAndroid Build Coastguard Worker 
2435*a67afe4dSAndroid Build Coastguard Worker    assert(in_bytes == nbytes || endrc != ZLIB_OK);
2436*a67afe4dSAndroid Build Coastguard Worker 
2437*a67afe4dSAndroid Build Coastguard Worker    /* Update the running total of input bytes consumed */
2438*a67afe4dSAndroid Build Coastguard Worker    zlib->compressed_digits = uarb_add32(zlib->compressed_bytes,
2439*a67afe4dSAndroid Build Coastguard Worker       zlib->compressed_digits, in_bytes - zlib->z.avail_in);
2440*a67afe4dSAndroid Build Coastguard Worker 
2441*a67afe4dSAndroid Build Coastguard Worker    /* At the end of the stream update the chunk with the accumulated
2442*a67afe4dSAndroid Build Coastguard Worker     * information if it is an improvement:
2443*a67afe4dSAndroid Build Coastguard Worker     */
2444*a67afe4dSAndroid Build Coastguard Worker    if (endrc == ZLIB_STREAM_END && zlib->window_bits < zlib->ok_bits)
2445*a67afe4dSAndroid Build Coastguard Worker    {
2446*a67afe4dSAndroid Build Coastguard Worker       struct chunk *chunk = zlib->chunk;
2447*a67afe4dSAndroid Build Coastguard Worker 
2448*a67afe4dSAndroid Build Coastguard Worker       chunk->uncompressed_digits = uarb_copy(chunk->uncompressed_bytes,
2449*a67afe4dSAndroid Build Coastguard Worker          zlib->uncompressed_bytes, zlib->uncompressed_digits);
2450*a67afe4dSAndroid Build Coastguard Worker       chunk->compressed_digits = uarb_copy(chunk->compressed_bytes,
2451*a67afe4dSAndroid Build Coastguard Worker          zlib->compressed_bytes, zlib->compressed_digits);
2452*a67afe4dSAndroid Build Coastguard Worker       chunk->rewrite_buffer[0] = zlib->header[0];
2453*a67afe4dSAndroid Build Coastguard Worker       chunk->rewrite_buffer[1] = zlib->header[1];
2454*a67afe4dSAndroid Build Coastguard Worker 
2455*a67afe4dSAndroid Build Coastguard Worker       if (zlib->window_bits != zlib->file_bits || zlib->cksum)
2456*a67afe4dSAndroid Build Coastguard Worker       {
2457*a67afe4dSAndroid Build Coastguard Worker          /* A rewrite is required */
2458*a67afe4dSAndroid Build Coastguard Worker          chunk->rewrite_offset = zlib->rewrite_offset;
2459*a67afe4dSAndroid Build Coastguard Worker          chunk->rewrite_length = 2;
2460*a67afe4dSAndroid Build Coastguard Worker       }
2461*a67afe4dSAndroid Build Coastguard Worker 
2462*a67afe4dSAndroid Build Coastguard Worker       else
2463*a67afe4dSAndroid Build Coastguard Worker       {
2464*a67afe4dSAndroid Build Coastguard Worker          chunk->rewrite_offset = 0;
2465*a67afe4dSAndroid Build Coastguard Worker          chunk->rewrite_length = 0;
2466*a67afe4dSAndroid Build Coastguard Worker       }
2467*a67afe4dSAndroid Build Coastguard Worker 
2468*a67afe4dSAndroid Build Coastguard Worker       if (in_bytes < nbytes)
2469*a67afe4dSAndroid Build Coastguard Worker          chunk_message(chunk, "extra compressed data");
2470*a67afe4dSAndroid Build Coastguard Worker 
2471*a67afe4dSAndroid Build Coastguard Worker       zlib->extra_bytes = nbytes - in_bytes;
2472*a67afe4dSAndroid Build Coastguard Worker       zlib->ok_bits = zlib->window_bits;
2473*a67afe4dSAndroid Build Coastguard Worker    }
2474*a67afe4dSAndroid Build Coastguard Worker 
2475*a67afe4dSAndroid Build Coastguard Worker    return endrc;
2476*a67afe4dSAndroid Build Coastguard Worker }
2477*a67afe4dSAndroid Build Coastguard Worker 
2478*a67afe4dSAndroid Build Coastguard Worker static int
zlib_run(struct zlib * zlib)2479*a67afe4dSAndroid Build Coastguard Worker zlib_run(struct zlib *zlib)
2480*a67afe4dSAndroid Build Coastguard Worker    /* Like zlib_advance but also handles a stream of IDAT chunks. */
2481*a67afe4dSAndroid Build Coastguard Worker {
2482*a67afe4dSAndroid Build Coastguard Worker    /* The 'extra_bytes' field is set by zlib_advance if there is extra
2483*a67afe4dSAndroid Build Coastguard Worker     * compressed data in the chunk it handles (if it sees Z_STREAM_END before
2484*a67afe4dSAndroid Build Coastguard Worker     * all the input data has been used.)  This function uses the value to update
2485*a67afe4dSAndroid Build Coastguard Worker     * the correct chunk length, so the problem should only ever be detected once
2486*a67afe4dSAndroid Build Coastguard Worker     * for each chunk.  zlib_advance outputs the error message, though see the
2487*a67afe4dSAndroid Build Coastguard Worker     * IDAT specific check below.
2488*a67afe4dSAndroid Build Coastguard Worker     */
2489*a67afe4dSAndroid Build Coastguard Worker    zlib->extra_bytes = 0;
2490*a67afe4dSAndroid Build Coastguard Worker 
2491*a67afe4dSAndroid Build Coastguard Worker    if (zlib->idat != NULL)
2492*a67afe4dSAndroid Build Coastguard Worker    {
2493*a67afe4dSAndroid Build Coastguard Worker       struct IDAT_list *list = zlib->idat->idat_list_head;
2494*a67afe4dSAndroid Build Coastguard Worker       struct IDAT_list *last = zlib->idat->idat_list_tail;
2495*a67afe4dSAndroid Build Coastguard Worker       int        skip = 0;
2496*a67afe4dSAndroid Build Coastguard Worker 
2497*a67afe4dSAndroid Build Coastguard Worker       /* 'rewrite_offset' is the offset of the LZ data within the chunk, for
2498*a67afe4dSAndroid Build Coastguard Worker        * IDAT it should be 0:
2499*a67afe4dSAndroid Build Coastguard Worker        */
2500*a67afe4dSAndroid Build Coastguard Worker       assert(zlib->rewrite_offset == 0);
2501*a67afe4dSAndroid Build Coastguard Worker 
2502*a67afe4dSAndroid Build Coastguard Worker       /* Process each IDAT_list in turn; the caller has left the stream
2503*a67afe4dSAndroid Build Coastguard Worker        * positioned at the start of the first IDAT chunk data.
2504*a67afe4dSAndroid Build Coastguard Worker        */
2505*a67afe4dSAndroid Build Coastguard Worker       for (;;)
2506*a67afe4dSAndroid Build Coastguard Worker       {
2507*a67afe4dSAndroid Build Coastguard Worker          unsigned int count = list->count;
2508*a67afe4dSAndroid Build Coastguard Worker          unsigned int i;
2509*a67afe4dSAndroid Build Coastguard Worker 
2510*a67afe4dSAndroid Build Coastguard Worker          for (i = 0; i<count; ++i)
2511*a67afe4dSAndroid Build Coastguard Worker          {
2512*a67afe4dSAndroid Build Coastguard Worker             int rc;
2513*a67afe4dSAndroid Build Coastguard Worker 
2514*a67afe4dSAndroid Build Coastguard Worker             if (skip > 0) /* Skip CRC and next IDAT header */
2515*a67afe4dSAndroid Build Coastguard Worker                skip_12(zlib->file);
2516*a67afe4dSAndroid Build Coastguard Worker 
2517*a67afe4dSAndroid Build Coastguard Worker             skip = 12; /* for the next time */
2518*a67afe4dSAndroid Build Coastguard Worker 
2519*a67afe4dSAndroid Build Coastguard Worker             rc = zlib_advance(zlib, list->lengths[i]);
2520*a67afe4dSAndroid Build Coastguard Worker 
2521*a67afe4dSAndroid Build Coastguard Worker             switch (rc)
2522*a67afe4dSAndroid Build Coastguard Worker             {
2523*a67afe4dSAndroid Build Coastguard Worker                case ZLIB_OK: /* keep going */
2524*a67afe4dSAndroid Build Coastguard Worker                   break;
2525*a67afe4dSAndroid Build Coastguard Worker 
2526*a67afe4dSAndroid Build Coastguard Worker                case ZLIB_STREAM_END: /* stop */
2527*a67afe4dSAndroid Build Coastguard Worker                   /* There may be extra chunks; if there are and one of them is
2528*a67afe4dSAndroid Build Coastguard Worker                    * not zero length output the 'extra data' message.  Only do
2529*a67afe4dSAndroid Build Coastguard Worker                    * this check if errors are being output.
2530*a67afe4dSAndroid Build Coastguard Worker                    */
2531*a67afe4dSAndroid Build Coastguard Worker                   if (zlib->global->errors && zlib->extra_bytes == 0)
2532*a67afe4dSAndroid Build Coastguard Worker                   {
2533*a67afe4dSAndroid Build Coastguard Worker                      struct IDAT_list *check = list;
2534*a67afe4dSAndroid Build Coastguard Worker                      int j = i+1, jcount = count;
2535*a67afe4dSAndroid Build Coastguard Worker 
2536*a67afe4dSAndroid Build Coastguard Worker                      for (;;)
2537*a67afe4dSAndroid Build Coastguard Worker                      {
2538*a67afe4dSAndroid Build Coastguard Worker                         for (; j<jcount; ++j)
2539*a67afe4dSAndroid Build Coastguard Worker                            if (check->lengths[j] > 0)
2540*a67afe4dSAndroid Build Coastguard Worker                            {
2541*a67afe4dSAndroid Build Coastguard Worker                               chunk_message(zlib->chunk,
2542*a67afe4dSAndroid Build Coastguard Worker                                  "extra compressed data");
2543*a67afe4dSAndroid Build Coastguard Worker                               goto end_check;
2544*a67afe4dSAndroid Build Coastguard Worker                            }
2545*a67afe4dSAndroid Build Coastguard Worker 
2546*a67afe4dSAndroid Build Coastguard Worker                         if (check == last)
2547*a67afe4dSAndroid Build Coastguard Worker                            break;
2548*a67afe4dSAndroid Build Coastguard Worker 
2549*a67afe4dSAndroid Build Coastguard Worker                         check = check->next;
2550*a67afe4dSAndroid Build Coastguard Worker                         jcount = check->count;
2551*a67afe4dSAndroid Build Coastguard Worker                         j = 0;
2552*a67afe4dSAndroid Build Coastguard Worker                      }
2553*a67afe4dSAndroid Build Coastguard Worker                   }
2554*a67afe4dSAndroid Build Coastguard Worker 
2555*a67afe4dSAndroid Build Coastguard Worker                end_check:
2556*a67afe4dSAndroid Build Coastguard Worker                   /* Terminate the list at the current position, reducing the
2557*a67afe4dSAndroid Build Coastguard Worker                    * length of the last IDAT too if required.
2558*a67afe4dSAndroid Build Coastguard Worker                    */
2559*a67afe4dSAndroid Build Coastguard Worker                   list->lengths[i] -= zlib->extra_bytes;
2560*a67afe4dSAndroid Build Coastguard Worker                   list->count = i+1;
2561*a67afe4dSAndroid Build Coastguard Worker                   zlib->idat->idat_list_tail = list;
2562*a67afe4dSAndroid Build Coastguard Worker                   /* FALLTHROUGH */
2563*a67afe4dSAndroid Build Coastguard Worker 
2564*a67afe4dSAndroid Build Coastguard Worker                default:
2565*a67afe4dSAndroid Build Coastguard Worker                   return rc;
2566*a67afe4dSAndroid Build Coastguard Worker             }
2567*a67afe4dSAndroid Build Coastguard Worker          }
2568*a67afe4dSAndroid Build Coastguard Worker 
2569*a67afe4dSAndroid Build Coastguard Worker          /* At the end of the compressed data and Z_STREAM_END was not seen. */
2570*a67afe4dSAndroid Build Coastguard Worker          if (list == last)
2571*a67afe4dSAndroid Build Coastguard Worker             return ZLIB_OK;
2572*a67afe4dSAndroid Build Coastguard Worker 
2573*a67afe4dSAndroid Build Coastguard Worker          list = list->next;
2574*a67afe4dSAndroid Build Coastguard Worker       }
2575*a67afe4dSAndroid Build Coastguard Worker    }
2576*a67afe4dSAndroid Build Coastguard Worker 
2577*a67afe4dSAndroid Build Coastguard Worker    else
2578*a67afe4dSAndroid Build Coastguard Worker    {
2579*a67afe4dSAndroid Build Coastguard Worker       struct chunk *chunk = zlib->chunk;
2580*a67afe4dSAndroid Build Coastguard Worker       int rc;
2581*a67afe4dSAndroid Build Coastguard Worker 
2582*a67afe4dSAndroid Build Coastguard Worker       assert(zlib->rewrite_offset < chunk->chunk_length);
2583*a67afe4dSAndroid Build Coastguard Worker 
2584*a67afe4dSAndroid Build Coastguard Worker       rc = zlib_advance(zlib, chunk->chunk_length - zlib->rewrite_offset);
2585*a67afe4dSAndroid Build Coastguard Worker 
2586*a67afe4dSAndroid Build Coastguard Worker       /* The extra bytes in the chunk are handled now by adjusting the chunk
2587*a67afe4dSAndroid Build Coastguard Worker        * length to exclude them; the zlib data is always stored at the end of
2588*a67afe4dSAndroid Build Coastguard Worker        * the PNG chunk (although clearly this is not necessary.)  zlib_advance
2589*a67afe4dSAndroid Build Coastguard Worker        * has already output a warning message.
2590*a67afe4dSAndroid Build Coastguard Worker        */
2591*a67afe4dSAndroid Build Coastguard Worker       chunk->chunk_length -= zlib->extra_bytes;
2592*a67afe4dSAndroid Build Coastguard Worker       return rc;
2593*a67afe4dSAndroid Build Coastguard Worker    }
2594*a67afe4dSAndroid Build Coastguard Worker }
2595*a67afe4dSAndroid Build Coastguard Worker 
2596*a67afe4dSAndroid Build Coastguard Worker static int /* global function; not a member function */
zlib_check(struct file * file,png_uint_32 offset)2597*a67afe4dSAndroid Build Coastguard Worker zlib_check(struct file *file, png_uint_32 offset)
2598*a67afe4dSAndroid Build Coastguard Worker    /* Check the stream of zlib compressed data in either idat (if given) or (if
2599*a67afe4dSAndroid Build Coastguard Worker     * not) chunk.  In fact it is zlib_run that handles the difference in reading
2600*a67afe4dSAndroid Build Coastguard Worker     * a single chunk and a list of IDAT chunks.
2601*a67afe4dSAndroid Build Coastguard Worker     *
2602*a67afe4dSAndroid Build Coastguard Worker     * In either case the input file must be positioned at the first byte of zlib
2603*a67afe4dSAndroid Build Coastguard Worker     * compressed data (the first header byte).
2604*a67afe4dSAndroid Build Coastguard Worker     *
2605*a67afe4dSAndroid Build Coastguard Worker     * The return value is true on success, including the case where the zlib
2606*a67afe4dSAndroid Build Coastguard Worker     * header may need to be rewritten, and false on an unrecoverable error.
2607*a67afe4dSAndroid Build Coastguard Worker     *
2608*a67afe4dSAndroid Build Coastguard Worker     * In the case of IDAT chunks 'offset' should be 0.
2609*a67afe4dSAndroid Build Coastguard Worker     */
2610*a67afe4dSAndroid Build Coastguard Worker {
2611*a67afe4dSAndroid Build Coastguard Worker    fpos_t start_pos;
2612*a67afe4dSAndroid Build Coastguard Worker    struct zlib zlib;
2613*a67afe4dSAndroid Build Coastguard Worker 
2614*a67afe4dSAndroid Build Coastguard Worker    /* Record the start of the LZ data to allow a re-read. */
2615*a67afe4dSAndroid Build Coastguard Worker    file_getpos(file, &start_pos);
2616*a67afe4dSAndroid Build Coastguard Worker 
2617*a67afe4dSAndroid Build Coastguard Worker    /* First test the existing (file) window bits: */
2618*a67afe4dSAndroid Build Coastguard Worker    if (zlib_init(&zlib, file->idat, file->chunk, 0/*window bits*/, offset))
2619*a67afe4dSAndroid Build Coastguard Worker    {
2620*a67afe4dSAndroid Build Coastguard Worker       int min_bits, max_bits, rc;
2621*a67afe4dSAndroid Build Coastguard Worker 
2622*a67afe4dSAndroid Build Coastguard Worker       /* The first run using the existing window bits. */
2623*a67afe4dSAndroid Build Coastguard Worker       rc = zlib_run(&zlib);
2624*a67afe4dSAndroid Build Coastguard Worker 
2625*a67afe4dSAndroid Build Coastguard Worker       switch (rc)
2626*a67afe4dSAndroid Build Coastguard Worker       {
2627*a67afe4dSAndroid Build Coastguard Worker          case ZLIB_TOO_FAR_BACK:
2628*a67afe4dSAndroid Build Coastguard Worker             /* too far back error */
2629*a67afe4dSAndroid Build Coastguard Worker             file->status_code |= TOO_FAR_BACK;
2630*a67afe4dSAndroid Build Coastguard Worker             min_bits = zlib.window_bits + 1;
2631*a67afe4dSAndroid Build Coastguard Worker             max_bits = 15;
2632*a67afe4dSAndroid Build Coastguard Worker             break;
2633*a67afe4dSAndroid Build Coastguard Worker 
2634*a67afe4dSAndroid Build Coastguard Worker          case ZLIB_STREAM_END:
2635*a67afe4dSAndroid Build Coastguard Worker             if (!zlib.global->optimize_zlib &&
2636*a67afe4dSAndroid Build Coastguard Worker                zlib.window_bits == zlib.file_bits && !zlib.cksum)
2637*a67afe4dSAndroid Build Coastguard Worker             {
2638*a67afe4dSAndroid Build Coastguard Worker                /* The trivial case where the stream is ok and optimization was
2639*a67afe4dSAndroid Build Coastguard Worker                 * not requested.
2640*a67afe4dSAndroid Build Coastguard Worker                 */
2641*a67afe4dSAndroid Build Coastguard Worker                zlib_end(&zlib);
2642*a67afe4dSAndroid Build Coastguard Worker                return 1;
2643*a67afe4dSAndroid Build Coastguard Worker             }
2644*a67afe4dSAndroid Build Coastguard Worker 
2645*a67afe4dSAndroid Build Coastguard Worker             max_bits = max_window_bits(zlib.uncompressed_bytes,
2646*a67afe4dSAndroid Build Coastguard Worker                zlib.uncompressed_digits);
2647*a67afe4dSAndroid Build Coastguard Worker             if (zlib.ok_bits < max_bits)
2648*a67afe4dSAndroid Build Coastguard Worker                max_bits = zlib.ok_bits;
2649*a67afe4dSAndroid Build Coastguard Worker             min_bits = 8;
2650*a67afe4dSAndroid Build Coastguard Worker 
2651*a67afe4dSAndroid Build Coastguard Worker             /* cksum is set if there is an error in the zlib header checksum
2652*a67afe4dSAndroid Build Coastguard Worker              * calculation in the original file (and this may be the only reason
2653*a67afe4dSAndroid Build Coastguard Worker              * a rewrite is required).  We can't rely on the file window bits in
2654*a67afe4dSAndroid Build Coastguard Worker              * this case, so do the optimization anyway.
2655*a67afe4dSAndroid Build Coastguard Worker              */
2656*a67afe4dSAndroid Build Coastguard Worker             if (zlib.cksum)
2657*a67afe4dSAndroid Build Coastguard Worker                chunk_message(zlib.chunk, "zlib checksum");
2658*a67afe4dSAndroid Build Coastguard Worker             break;
2659*a67afe4dSAndroid Build Coastguard Worker 
2660*a67afe4dSAndroid Build Coastguard Worker 
2661*a67afe4dSAndroid Build Coastguard Worker          case ZLIB_OK:
2662*a67afe4dSAndroid Build Coastguard Worker             /* Truncated stream; unrecoverable, gets converted to ZLIB_FATAL */
2663*a67afe4dSAndroid Build Coastguard Worker             zlib.z.msg = PNGZ_MSG_CAST("[truncated]");
2664*a67afe4dSAndroid Build Coastguard Worker             zlib_message(&zlib, 0/*expected*/);
2665*a67afe4dSAndroid Build Coastguard Worker             /* FALLTHROUGH */
2666*a67afe4dSAndroid Build Coastguard Worker 
2667*a67afe4dSAndroid Build Coastguard Worker          default:
2668*a67afe4dSAndroid Build Coastguard Worker             /* Unrecoverable error; skip the chunk; a zlib_message has already
2669*a67afe4dSAndroid Build Coastguard Worker              * been output.
2670*a67afe4dSAndroid Build Coastguard Worker              */
2671*a67afe4dSAndroid Build Coastguard Worker             zlib_end(&zlib);
2672*a67afe4dSAndroid Build Coastguard Worker             return 0;
2673*a67afe4dSAndroid Build Coastguard Worker       }
2674*a67afe4dSAndroid Build Coastguard Worker 
2675*a67afe4dSAndroid Build Coastguard Worker       /* Optimize window bits or fix a too-far-back error.  min_bits and
2676*a67afe4dSAndroid Build Coastguard Worker        * max_bits have been set appropriately, ok_bits records the bit value
2677*a67afe4dSAndroid Build Coastguard Worker        * known to work.
2678*a67afe4dSAndroid Build Coastguard Worker        */
2679*a67afe4dSAndroid Build Coastguard Worker       while (min_bits < max_bits || max_bits < zlib.ok_bits/*if 16*/)
2680*a67afe4dSAndroid Build Coastguard Worker       {
2681*a67afe4dSAndroid Build Coastguard Worker          int test_bits = (min_bits + max_bits) >> 1;
2682*a67afe4dSAndroid Build Coastguard Worker 
2683*a67afe4dSAndroid Build Coastguard Worker          if (zlib_reset(&zlib, test_bits))
2684*a67afe4dSAndroid Build Coastguard Worker          {
2685*a67afe4dSAndroid Build Coastguard Worker             file_setpos(file, &start_pos);
2686*a67afe4dSAndroid Build Coastguard Worker             rc = zlib_run(&zlib);
2687*a67afe4dSAndroid Build Coastguard Worker 
2688*a67afe4dSAndroid Build Coastguard Worker             switch (rc)
2689*a67afe4dSAndroid Build Coastguard Worker             {
2690*a67afe4dSAndroid Build Coastguard Worker                case ZLIB_TOO_FAR_BACK:
2691*a67afe4dSAndroid Build Coastguard Worker                   min_bits = test_bits+1;
2692*a67afe4dSAndroid Build Coastguard Worker                   if (min_bits > max_bits)
2693*a67afe4dSAndroid Build Coastguard Worker                   {
2694*a67afe4dSAndroid Build Coastguard Worker                      /* This happens when the stream really is damaged and it
2695*a67afe4dSAndroid Build Coastguard Worker                       * contains a distance code that addresses bytes before
2696*a67afe4dSAndroid Build Coastguard Worker                       * the start of the uncompressed data.
2697*a67afe4dSAndroid Build Coastguard Worker                       */
2698*a67afe4dSAndroid Build Coastguard Worker                      assert(test_bits == 15);
2699*a67afe4dSAndroid Build Coastguard Worker 
2700*a67afe4dSAndroid Build Coastguard Worker                      /* Output the error that wasn't output before: */
2701*a67afe4dSAndroid Build Coastguard Worker                      if (zlib.z.msg == NULL)
2702*a67afe4dSAndroid Build Coastguard Worker                         zlib.z.msg = PNGZ_MSG_CAST(
2703*a67afe4dSAndroid Build Coastguard Worker                            "invalid distance too far back");
2704*a67afe4dSAndroid Build Coastguard Worker                      zlib_message(&zlib, 0/*stream error*/);
2705*a67afe4dSAndroid Build Coastguard Worker                      zlib_end(&zlib);
2706*a67afe4dSAndroid Build Coastguard Worker                      return 0;
2707*a67afe4dSAndroid Build Coastguard Worker                   }
2708*a67afe4dSAndroid Build Coastguard Worker                   break;
2709*a67afe4dSAndroid Build Coastguard Worker 
2710*a67afe4dSAndroid Build Coastguard Worker                case ZLIB_STREAM_END: /* success */
2711*a67afe4dSAndroid Build Coastguard Worker                   max_bits = test_bits;
2712*a67afe4dSAndroid Build Coastguard Worker                   break;
2713*a67afe4dSAndroid Build Coastguard Worker 
2714*a67afe4dSAndroid Build Coastguard Worker                default:
2715*a67afe4dSAndroid Build Coastguard Worker                   /* A fatal error; this happens if a too-far-back error was
2716*a67afe4dSAndroid Build Coastguard Worker                    * hiding a more serious error, zlib_advance has already
2717*a67afe4dSAndroid Build Coastguard Worker                    * output a zlib_message.
2718*a67afe4dSAndroid Build Coastguard Worker                    */
2719*a67afe4dSAndroid Build Coastguard Worker                   zlib_end(&zlib);
2720*a67afe4dSAndroid Build Coastguard Worker                   return 0;
2721*a67afe4dSAndroid Build Coastguard Worker             }
2722*a67afe4dSAndroid Build Coastguard Worker          }
2723*a67afe4dSAndroid Build Coastguard Worker 
2724*a67afe4dSAndroid Build Coastguard Worker          else /* inflateReset2 failed */
2725*a67afe4dSAndroid Build Coastguard Worker          {
2726*a67afe4dSAndroid Build Coastguard Worker             zlib_end(&zlib);
2727*a67afe4dSAndroid Build Coastguard Worker             return 0;
2728*a67afe4dSAndroid Build Coastguard Worker          }
2729*a67afe4dSAndroid Build Coastguard Worker       }
2730*a67afe4dSAndroid Build Coastguard Worker 
2731*a67afe4dSAndroid Build Coastguard Worker       /* The loop guarantees this */
2732*a67afe4dSAndroid Build Coastguard Worker       assert(zlib.ok_bits == max_bits);
2733*a67afe4dSAndroid Build Coastguard Worker       zlib_end(&zlib);
2734*a67afe4dSAndroid Build Coastguard Worker       return 1;
2735*a67afe4dSAndroid Build Coastguard Worker    }
2736*a67afe4dSAndroid Build Coastguard Worker 
2737*a67afe4dSAndroid Build Coastguard Worker    else /* zlib initialization failed - skip the chunk */
2738*a67afe4dSAndroid Build Coastguard Worker    {
2739*a67afe4dSAndroid Build Coastguard Worker       zlib_end(&zlib);
2740*a67afe4dSAndroid Build Coastguard Worker       return 0;
2741*a67afe4dSAndroid Build Coastguard Worker    }
2742*a67afe4dSAndroid Build Coastguard Worker }
2743*a67afe4dSAndroid Build Coastguard Worker 
2744*a67afe4dSAndroid Build Coastguard Worker /***************************** LIBPNG CALLBACKS *******************************/
2745*a67afe4dSAndroid Build Coastguard Worker /* The strategy here is to run a regular libpng PNG file read but examine the
2746*a67afe4dSAndroid Build Coastguard Worker  * input data (from the file) before passing it to libpng so as to be aware of
2747*a67afe4dSAndroid Build Coastguard Worker  * the state we expect libpng to be in.  Warning and error callbacks are also
2748*a67afe4dSAndroid Build Coastguard Worker  * intercepted so that they can be quieted and interpreted.  Interpretation
2749*a67afe4dSAndroid Build Coastguard Worker  * depends on a somewhat risky string match for known error messages; let us
2750*a67afe4dSAndroid Build Coastguard Worker  * hope that this can be fixed in the next version of libpng.
2751*a67afe4dSAndroid Build Coastguard Worker  *
2752*a67afe4dSAndroid Build Coastguard Worker  * The control structure is pointed to by the libpng error pointer.  It contains
2753*a67afe4dSAndroid Build Coastguard Worker  * that set of structures which must persist across multiple read callbacks,
2754*a67afe4dSAndroid Build Coastguard Worker  * which is pretty much everything except the 'zlib' control structure.
2755*a67afe4dSAndroid Build Coastguard Worker  *
2756*a67afe4dSAndroid Build Coastguard Worker  * The file structure is instantiated in the caller of the per-file routine, but
2757*a67afe4dSAndroid Build Coastguard Worker  * the per-file routine contains the chunk and IDAT control structures.
2758*a67afe4dSAndroid Build Coastguard Worker  */
2759*a67afe4dSAndroid Build Coastguard Worker /* The three routines read_chunk, process_chunk and sync_stream can only be
2760*a67afe4dSAndroid Build Coastguard Worker  * called via a call to read_chunk and only exit at a return from process_chunk.
2761*a67afe4dSAndroid Build Coastguard Worker  * These routines could have been written as one confusing large routine,
2762*a67afe4dSAndroid Build Coastguard Worker  * instead this code relies on the compiler to do tail call elimination.  The
2763*a67afe4dSAndroid Build Coastguard Worker  * possible calls are as follows:
2764*a67afe4dSAndroid Build Coastguard Worker  *
2765*a67afe4dSAndroid Build Coastguard Worker  * read_chunk
2766*a67afe4dSAndroid Build Coastguard Worker  *    -> sync_stream
2767*a67afe4dSAndroid Build Coastguard Worker  *       -> process_chunk
2768*a67afe4dSAndroid Build Coastguard Worker  *    -> process_chunk
2769*a67afe4dSAndroid Build Coastguard Worker  *       -> read_chunk
2770*a67afe4dSAndroid Build Coastguard Worker  *       returns
2771*a67afe4dSAndroid Build Coastguard Worker  */
2772*a67afe4dSAndroid Build Coastguard Worker static void read_chunk(struct file *file);
2773*a67afe4dSAndroid Build Coastguard Worker static void
process_chunk(struct file * file,png_uint_32 file_crc,png_uint_32 next_length,png_uint_32 next_type)2774*a67afe4dSAndroid Build Coastguard Worker process_chunk(struct file *file, png_uint_32 file_crc, png_uint_32 next_length,
2775*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 next_type)
2776*a67afe4dSAndroid Build Coastguard Worker    /* Called when the chunk data has been read, next_length and next_type
2777*a67afe4dSAndroid Build Coastguard Worker     * will be set for the next chunk (or 0 if this is IEND).
2778*a67afe4dSAndroid Build Coastguard Worker     *
2779*a67afe4dSAndroid Build Coastguard Worker     * When this routine returns, chunk_length and chunk_type will be set for the
2780*a67afe4dSAndroid Build Coastguard Worker     * next chunk to write because if a chunk is skipped this return calls back
2781*a67afe4dSAndroid Build Coastguard Worker     * to read_chunk.
2782*a67afe4dSAndroid Build Coastguard Worker     */
2783*a67afe4dSAndroid Build Coastguard Worker {
2784*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 type = file->type;
2785*a67afe4dSAndroid Build Coastguard Worker 
2786*a67afe4dSAndroid Build Coastguard Worker    if (file->global->verbose > 1)
2787*a67afe4dSAndroid Build Coastguard Worker    {
2788*a67afe4dSAndroid Build Coastguard Worker       fputs("  ", stderr);
2789*a67afe4dSAndroid Build Coastguard Worker       type_name(file->type, stderr);
2790*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, " %lu 0x%.8x 0x%.8x\n", (unsigned long)file->length,
2791*a67afe4dSAndroid Build Coastguard Worker          file->crc ^ 0xffffffff, file_crc);
2792*a67afe4dSAndroid Build Coastguard Worker    }
2793*a67afe4dSAndroid Build Coastguard Worker 
2794*a67afe4dSAndroid Build Coastguard Worker    /* The basic structure seems correct but the CRC may not match, in this
2795*a67afe4dSAndroid Build Coastguard Worker     * case assume that it is simply a bad CRC, either wrongly calculated or
2796*a67afe4dSAndroid Build Coastguard Worker     * because of damaged stream data.
2797*a67afe4dSAndroid Build Coastguard Worker     */
2798*a67afe4dSAndroid Build Coastguard Worker    if ((file->crc ^ 0xffffffff) != file_crc)
2799*a67afe4dSAndroid Build Coastguard Worker    {
2800*a67afe4dSAndroid Build Coastguard Worker       /* The behavior is set by the 'skip' setting; if it is anything other
2801*a67afe4dSAndroid Build Coastguard Worker        * than SKIP_BAD_CRC ignore the bad CRC and return the chunk, with a
2802*a67afe4dSAndroid Build Coastguard Worker        * corrected CRC and possibly processed, to libpng.  Otherwise skip the
2803*a67afe4dSAndroid Build Coastguard Worker        * chunk, which will result in a fatal error if the chunk is critical.
2804*a67afe4dSAndroid Build Coastguard Worker        */
2805*a67afe4dSAndroid Build Coastguard Worker       file->status_code |= CRC_ERROR;
2806*a67afe4dSAndroid Build Coastguard Worker 
2807*a67afe4dSAndroid Build Coastguard Worker       /* Ignore the bad CRC  */
2808*a67afe4dSAndroid Build Coastguard Worker       if (file->global->skip != SKIP_BAD_CRC)
2809*a67afe4dSAndroid Build Coastguard Worker          type_message(file, type, "bad CRC");
2810*a67afe4dSAndroid Build Coastguard Worker 
2811*a67afe4dSAndroid Build Coastguard Worker       /* This will cause an IEND with a bad CRC to stop */
2812*a67afe4dSAndroid Build Coastguard Worker       else if (CRITICAL(type))
2813*a67afe4dSAndroid Build Coastguard Worker          stop(file, READ_ERROR_CODE, "bad CRC in critical chunk");
2814*a67afe4dSAndroid Build Coastguard Worker 
2815*a67afe4dSAndroid Build Coastguard Worker       else
2816*a67afe4dSAndroid Build Coastguard Worker       {
2817*a67afe4dSAndroid Build Coastguard Worker          type_message(file, type, "skipped: bad CRC");
2818*a67afe4dSAndroid Build Coastguard Worker 
2819*a67afe4dSAndroid Build Coastguard Worker          /* NOTE: this cannot be reached for IEND because it is critical. */
2820*a67afe4dSAndroid Build Coastguard Worker          goto skip_chunk;
2821*a67afe4dSAndroid Build Coastguard Worker       }
2822*a67afe4dSAndroid Build Coastguard Worker    }
2823*a67afe4dSAndroid Build Coastguard Worker 
2824*a67afe4dSAndroid Build Coastguard Worker    /* Check for other 'skip' cases and handle these; these only apply to
2825*a67afe4dSAndroid Build Coastguard Worker     * ancillary chunks (and not tRNS, which should probably have been a critical
2826*a67afe4dSAndroid Build Coastguard Worker     * chunk.)
2827*a67afe4dSAndroid Build Coastguard Worker     */
2828*a67afe4dSAndroid Build Coastguard Worker    if (skip_chunk_type(file->global, type))
2829*a67afe4dSAndroid Build Coastguard Worker       goto skip_chunk;
2830*a67afe4dSAndroid Build Coastguard Worker 
2831*a67afe4dSAndroid Build Coastguard Worker    /* The chunk may still be skipped if problems are detected in the LZ data,
2832*a67afe4dSAndroid Build Coastguard Worker     * however the LZ data check requires a chunk.  Handle this by instantiating
2833*a67afe4dSAndroid Build Coastguard Worker     * a chunk unless an IDAT is already instantiated (IDAT control structures
2834*a67afe4dSAndroid Build Coastguard Worker     * instantiate their own chunk.)
2835*a67afe4dSAndroid Build Coastguard Worker     */
2836*a67afe4dSAndroid Build Coastguard Worker    if (type != png_IDAT)
2837*a67afe4dSAndroid Build Coastguard Worker       file->alloc(file, 0/*chunk*/);
2838*a67afe4dSAndroid Build Coastguard Worker 
2839*a67afe4dSAndroid Build Coastguard Worker    else if (file->idat == NULL)
2840*a67afe4dSAndroid Build Coastguard Worker       file->alloc(file, 1/*IDAT*/);
2841*a67afe4dSAndroid Build Coastguard Worker 
2842*a67afe4dSAndroid Build Coastguard Worker    else
2843*a67afe4dSAndroid Build Coastguard Worker    {
2844*a67afe4dSAndroid Build Coastguard Worker       /* The chunk length must be updated for process_IDAT */
2845*a67afe4dSAndroid Build Coastguard Worker       assert(file->chunk != NULL);
2846*a67afe4dSAndroid Build Coastguard Worker       assert(file->chunk->chunk_type == png_IDAT);
2847*a67afe4dSAndroid Build Coastguard Worker       file->chunk->chunk_length = file->length;
2848*a67afe4dSAndroid Build Coastguard Worker    }
2849*a67afe4dSAndroid Build Coastguard Worker 
2850*a67afe4dSAndroid Build Coastguard Worker    /* Record the 'next' information too, now that the original values for
2851*a67afe4dSAndroid Build Coastguard Worker     * this chunk have been copied.  Notice that the IDAT chunks only make a
2852*a67afe4dSAndroid Build Coastguard Worker     * copy of the position of the first chunk, this is fine - process_IDAT does
2853*a67afe4dSAndroid Build Coastguard Worker     * not need the position of this chunk.
2854*a67afe4dSAndroid Build Coastguard Worker     */
2855*a67afe4dSAndroid Build Coastguard Worker    file->length = next_length;
2856*a67afe4dSAndroid Build Coastguard Worker    file->type = next_type;
2857*a67afe4dSAndroid Build Coastguard Worker    getpos(file);
2858*a67afe4dSAndroid Build Coastguard Worker 
2859*a67afe4dSAndroid Build Coastguard Worker    /* Do per-type processing, note that if this code does not return from the
2860*a67afe4dSAndroid Build Coastguard Worker     * function the chunk will be skipped.  The rewrite is cancelled here so that
2861*a67afe4dSAndroid Build Coastguard Worker     * it can be set in the per-chunk processing.
2862*a67afe4dSAndroid Build Coastguard Worker     */
2863*a67afe4dSAndroid Build Coastguard Worker    file->chunk->rewrite_length = 0;
2864*a67afe4dSAndroid Build Coastguard Worker    file->chunk->rewrite_offset = 0;
2865*a67afe4dSAndroid Build Coastguard Worker    switch (type)
2866*a67afe4dSAndroid Build Coastguard Worker    {
2867*a67afe4dSAndroid Build Coastguard Worker       default:
2868*a67afe4dSAndroid Build Coastguard Worker          return;
2869*a67afe4dSAndroid Build Coastguard Worker 
2870*a67afe4dSAndroid Build Coastguard Worker       case png_IHDR:
2871*a67afe4dSAndroid Build Coastguard Worker          /* Read this now and update the control structure with the information
2872*a67afe4dSAndroid Build Coastguard Worker           * it contains.  The header is validated completely to ensure this is a
2873*a67afe4dSAndroid Build Coastguard Worker           * PNG.
2874*a67afe4dSAndroid Build Coastguard Worker           */
2875*a67afe4dSAndroid Build Coastguard Worker          {
2876*a67afe4dSAndroid Build Coastguard Worker             struct chunk *chunk = file->chunk;
2877*a67afe4dSAndroid Build Coastguard Worker 
2878*a67afe4dSAndroid Build Coastguard Worker             if (chunk->chunk_length != 13)
2879*a67afe4dSAndroid Build Coastguard Worker                stop_invalid(file, "IHDR length");
2880*a67afe4dSAndroid Build Coastguard Worker 
2881*a67afe4dSAndroid Build Coastguard Worker             /* Read all the IHDR information and validate it. */
2882*a67afe4dSAndroid Build Coastguard Worker             setpos(chunk);
2883*a67afe4dSAndroid Build Coastguard Worker             file->width = reread_4(file);
2884*a67afe4dSAndroid Build Coastguard Worker             file->height = reread_4(file);
2885*a67afe4dSAndroid Build Coastguard Worker             file->bit_depth = reread_byte(file);
2886*a67afe4dSAndroid Build Coastguard Worker             file->color_type = reread_byte(file);
2887*a67afe4dSAndroid Build Coastguard Worker             file->compression_method = reread_byte(file);
2888*a67afe4dSAndroid Build Coastguard Worker             file->filter_method = reread_byte(file);
2889*a67afe4dSAndroid Build Coastguard Worker             file->interlace_method = reread_byte(file);
2890*a67afe4dSAndroid Build Coastguard Worker 
2891*a67afe4dSAndroid Build Coastguard Worker             /* This validates all the fields, and calls stop_invalid if
2892*a67afe4dSAndroid Build Coastguard Worker              * there is a problem.
2893*a67afe4dSAndroid Build Coastguard Worker              */
2894*a67afe4dSAndroid Build Coastguard Worker             calc_image_size(file);
2895*a67afe4dSAndroid Build Coastguard Worker          }
2896*a67afe4dSAndroid Build Coastguard Worker          return;
2897*a67afe4dSAndroid Build Coastguard Worker 
2898*a67afe4dSAndroid Build Coastguard Worker          /* Ancillary chunks that require further processing: */
2899*a67afe4dSAndroid Build Coastguard Worker       case png_zTXt: case png_iCCP:
2900*a67afe4dSAndroid Build Coastguard Worker          if (process_zTXt_iCCP(file))
2901*a67afe4dSAndroid Build Coastguard Worker             return;
2902*a67afe4dSAndroid Build Coastguard Worker          chunk_end(&file->chunk);
2903*a67afe4dSAndroid Build Coastguard Worker          file_setpos(file, &file->data_pos);
2904*a67afe4dSAndroid Build Coastguard Worker          break;
2905*a67afe4dSAndroid Build Coastguard Worker 
2906*a67afe4dSAndroid Build Coastguard Worker       case png_iTXt:
2907*a67afe4dSAndroid Build Coastguard Worker          if (process_iTXt(file))
2908*a67afe4dSAndroid Build Coastguard Worker             return;
2909*a67afe4dSAndroid Build Coastguard Worker          chunk_end(&file->chunk);
2910*a67afe4dSAndroid Build Coastguard Worker          file_setpos(file, &file->data_pos);
2911*a67afe4dSAndroid Build Coastguard Worker          break;
2912*a67afe4dSAndroid Build Coastguard Worker 
2913*a67afe4dSAndroid Build Coastguard Worker       case png_IDAT:
2914*a67afe4dSAndroid Build Coastguard Worker          if (process_IDAT(file))
2915*a67afe4dSAndroid Build Coastguard Worker             return;
2916*a67afe4dSAndroid Build Coastguard Worker          /* First pass: */
2917*a67afe4dSAndroid Build Coastguard Worker          assert(next_type == png_IDAT);
2918*a67afe4dSAndroid Build Coastguard Worker          break;
2919*a67afe4dSAndroid Build Coastguard Worker    }
2920*a67afe4dSAndroid Build Coastguard Worker 
2921*a67afe4dSAndroid Build Coastguard Worker    /* Control reaches this point if the chunk must be skipped.  For chunks other
2922*a67afe4dSAndroid Build Coastguard Worker     * than IDAT this means that the zlib compressed data is fatally damaged and
2923*a67afe4dSAndroid Build Coastguard Worker     * the chunk will not be passed to libpng.  For IDAT it means that the end of
2924*a67afe4dSAndroid Build Coastguard Worker     * the IDAT stream has not yet been reached and we must handle the next
2925*a67afe4dSAndroid Build Coastguard Worker     * (IDAT) chunk.  If the LZ data in an IDAT stream cannot be read 'stop' must
2926*a67afe4dSAndroid Build Coastguard Worker     * be used to halt parsing of the PNG.
2927*a67afe4dSAndroid Build Coastguard Worker     */
2928*a67afe4dSAndroid Build Coastguard Worker    read_chunk(file);
2929*a67afe4dSAndroid Build Coastguard Worker    return;
2930*a67afe4dSAndroid Build Coastguard Worker 
2931*a67afe4dSAndroid Build Coastguard Worker    /* This is the generic code to skip the current chunk; simply jump to the
2932*a67afe4dSAndroid Build Coastguard Worker     * next one.
2933*a67afe4dSAndroid Build Coastguard Worker     */
2934*a67afe4dSAndroid Build Coastguard Worker skip_chunk:
2935*a67afe4dSAndroid Build Coastguard Worker    file->length = next_length;
2936*a67afe4dSAndroid Build Coastguard Worker    file->type = next_type;
2937*a67afe4dSAndroid Build Coastguard Worker    getpos(file);
2938*a67afe4dSAndroid Build Coastguard Worker    read_chunk(file);
2939*a67afe4dSAndroid Build Coastguard Worker }
2940*a67afe4dSAndroid Build Coastguard Worker 
2941*a67afe4dSAndroid Build Coastguard Worker static png_uint_32
get32(png_bytep buffer,int offset)2942*a67afe4dSAndroid Build Coastguard Worker get32(png_bytep buffer, int offset)
2943*a67afe4dSAndroid Build Coastguard Worker    /* Read a 32-bit value from an 8-byte circular buffer (used only below).
2944*a67afe4dSAndroid Build Coastguard Worker     */
2945*a67afe4dSAndroid Build Coastguard Worker {
2946*a67afe4dSAndroid Build Coastguard Worker    return
2947*a67afe4dSAndroid Build Coastguard Worker       (buffer[ offset    & 7] << 24) +
2948*a67afe4dSAndroid Build Coastguard Worker       (buffer[(offset+1) & 7] << 16) +
2949*a67afe4dSAndroid Build Coastguard Worker       (buffer[(offset+2) & 7] <<  8) +
2950*a67afe4dSAndroid Build Coastguard Worker       (buffer[(offset+3) & 7]      );
2951*a67afe4dSAndroid Build Coastguard Worker }
2952*a67afe4dSAndroid Build Coastguard Worker 
2953*a67afe4dSAndroid Build Coastguard Worker static void
sync_stream(struct file * file)2954*a67afe4dSAndroid Build Coastguard Worker sync_stream(struct file *file)
2955*a67afe4dSAndroid Build Coastguard Worker    /* The stream seems to be messed up, attempt to resync from the current chunk
2956*a67afe4dSAndroid Build Coastguard Worker     * header.  Executes stop on a fatal error, otherwise calls process_chunk.
2957*a67afe4dSAndroid Build Coastguard Worker     */
2958*a67afe4dSAndroid Build Coastguard Worker {
2959*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 file_crc;
2960*a67afe4dSAndroid Build Coastguard Worker 
2961*a67afe4dSAndroid Build Coastguard Worker    file->status_code |= STREAM_ERROR;
2962*a67afe4dSAndroid Build Coastguard Worker 
2963*a67afe4dSAndroid Build Coastguard Worker    if (file->global->verbose)
2964*a67afe4dSAndroid Build Coastguard Worker    {
2965*a67afe4dSAndroid Build Coastguard Worker       fputs(" SYNC ", stderr);
2966*a67afe4dSAndroid Build Coastguard Worker       type_name(file->type, stderr);
2967*a67afe4dSAndroid Build Coastguard Worker       putc('\n', stderr);
2968*a67afe4dSAndroid Build Coastguard Worker    }
2969*a67afe4dSAndroid Build Coastguard Worker 
2970*a67afe4dSAndroid Build Coastguard Worker    /* Return to the start of the chunk data */
2971*a67afe4dSAndroid Build Coastguard Worker    file_setpos(file, &file->data_pos);
2972*a67afe4dSAndroid Build Coastguard Worker    file->read_count = 8;
2973*a67afe4dSAndroid Build Coastguard Worker 
2974*a67afe4dSAndroid Build Coastguard Worker    if (read_4(file, &file_crc) == 4) /* else completely truncated */
2975*a67afe4dSAndroid Build Coastguard Worker    {
2976*a67afe4dSAndroid Build Coastguard Worker       /* Ignore the recorded chunk length, proceed through the data looking for
2977*a67afe4dSAndroid Build Coastguard Worker        * a leading sequence of bytes that match the CRC in the following four
2978*a67afe4dSAndroid Build Coastguard Worker        * bytes.  Each time a match is found check the next 8 bytes for a valid
2979*a67afe4dSAndroid Build Coastguard Worker        * length, chunk-type pair.
2980*a67afe4dSAndroid Build Coastguard Worker        */
2981*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 length;
2982*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 type = file->type;
2983*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 crc = crc_init_4(type);
2984*a67afe4dSAndroid Build Coastguard Worker       png_byte buffer[8];
2985*a67afe4dSAndroid Build Coastguard Worker       unsigned int nread = 0, nused = 0;
2986*a67afe4dSAndroid Build Coastguard Worker 
2987*a67afe4dSAndroid Build Coastguard Worker       for (length=0; length <= 0x7fffffff; ++length)
2988*a67afe4dSAndroid Build Coastguard Worker       {
2989*a67afe4dSAndroid Build Coastguard Worker          int ch;
2990*a67afe4dSAndroid Build Coastguard Worker 
2991*a67afe4dSAndroid Build Coastguard Worker          if ((crc ^ 0xffffffff) == file_crc)
2992*a67afe4dSAndroid Build Coastguard Worker          {
2993*a67afe4dSAndroid Build Coastguard Worker             /* A match on the CRC; for IEND this is sufficient, but for anything
2994*a67afe4dSAndroid Build Coastguard Worker              * else expect a following chunk header.
2995*a67afe4dSAndroid Build Coastguard Worker              */
2996*a67afe4dSAndroid Build Coastguard Worker             if (type == png_IEND)
2997*a67afe4dSAndroid Build Coastguard Worker             {
2998*a67afe4dSAndroid Build Coastguard Worker                file->length = length;
2999*a67afe4dSAndroid Build Coastguard Worker                process_chunk(file, file_crc, 0, 0);
3000*a67afe4dSAndroid Build Coastguard Worker                return;
3001*a67afe4dSAndroid Build Coastguard Worker             }
3002*a67afe4dSAndroid Build Coastguard Worker 
3003*a67afe4dSAndroid Build Coastguard Worker             else
3004*a67afe4dSAndroid Build Coastguard Worker             {
3005*a67afe4dSAndroid Build Coastguard Worker                /* Need 8 bytes */
3006*a67afe4dSAndroid Build Coastguard Worker                while (nread < 8+nused)
3007*a67afe4dSAndroid Build Coastguard Worker                {
3008*a67afe4dSAndroid Build Coastguard Worker                   ch = read_byte(file);
3009*a67afe4dSAndroid Build Coastguard Worker                   if (ch == EOF)
3010*a67afe4dSAndroid Build Coastguard Worker                      goto truncated;
3011*a67afe4dSAndroid Build Coastguard Worker                   buffer[(nread++) & 7] = (png_byte)ch;
3012*a67afe4dSAndroid Build Coastguard Worker                }
3013*a67afe4dSAndroid Build Coastguard Worker 
3014*a67afe4dSAndroid Build Coastguard Worker                /* Prevent overflow */
3015*a67afe4dSAndroid Build Coastguard Worker                nread -= nused & ~7;
3016*a67afe4dSAndroid Build Coastguard Worker                nused -= nused & ~7; /* or, nused &= 7 ;-) */
3017*a67afe4dSAndroid Build Coastguard Worker 
3018*a67afe4dSAndroid Build Coastguard Worker                /* Examine the 8 bytes for a valid chunk header. */
3019*a67afe4dSAndroid Build Coastguard Worker                {
3020*a67afe4dSAndroid Build Coastguard Worker                   png_uint_32 next_length = get32(buffer, nused);
3021*a67afe4dSAndroid Build Coastguard Worker 
3022*a67afe4dSAndroid Build Coastguard Worker                   if (next_length < 0x7fffffff)
3023*a67afe4dSAndroid Build Coastguard Worker                   {
3024*a67afe4dSAndroid Build Coastguard Worker                      png_uint_32 next_type = get32(buffer, nused+4);
3025*a67afe4dSAndroid Build Coastguard Worker 
3026*a67afe4dSAndroid Build Coastguard Worker                      if (chunk_type_valid(next_type))
3027*a67afe4dSAndroid Build Coastguard Worker                      {
3028*a67afe4dSAndroid Build Coastguard Worker                         file->read_count -= 8;
3029*a67afe4dSAndroid Build Coastguard Worker                         process_chunk(file, file_crc, next_length, next_type);
3030*a67afe4dSAndroid Build Coastguard Worker                         return;
3031*a67afe4dSAndroid Build Coastguard Worker                      }
3032*a67afe4dSAndroid Build Coastguard Worker                   }
3033*a67afe4dSAndroid Build Coastguard Worker 
3034*a67afe4dSAndroid Build Coastguard Worker                   /* Not valid, keep going. */
3035*a67afe4dSAndroid Build Coastguard Worker                }
3036*a67afe4dSAndroid Build Coastguard Worker             }
3037*a67afe4dSAndroid Build Coastguard Worker          }
3038*a67afe4dSAndroid Build Coastguard Worker 
3039*a67afe4dSAndroid Build Coastguard Worker          /* This catches up with the circular buffer which gets filled above
3040*a67afe4dSAndroid Build Coastguard Worker           * while checking a chunk header.  This code is slightly tricky - if
3041*a67afe4dSAndroid Build Coastguard Worker           * the chunk_type is IEND the buffer will never be used, if it is not
3042*a67afe4dSAndroid Build Coastguard Worker           * the code will always read ahead exactly 8 bytes and pass this on to
3043*a67afe4dSAndroid Build Coastguard Worker           * process_chunk.  So the invariant that IEND leaves the file position
3044*a67afe4dSAndroid Build Coastguard Worker           * after the IEND CRC and other chunk leave it after the *next* chunk
3045*a67afe4dSAndroid Build Coastguard Worker           * header is not broken.
3046*a67afe4dSAndroid Build Coastguard Worker           */
3047*a67afe4dSAndroid Build Coastguard Worker          if (nread <= nused)
3048*a67afe4dSAndroid Build Coastguard Worker          {
3049*a67afe4dSAndroid Build Coastguard Worker             ch = read_byte(file);
3050*a67afe4dSAndroid Build Coastguard Worker 
3051*a67afe4dSAndroid Build Coastguard Worker             if (ch == EOF)
3052*a67afe4dSAndroid Build Coastguard Worker                goto truncated;
3053*a67afe4dSAndroid Build Coastguard Worker          }
3054*a67afe4dSAndroid Build Coastguard Worker 
3055*a67afe4dSAndroid Build Coastguard Worker          else
3056*a67afe4dSAndroid Build Coastguard Worker             ch = buffer[(++nused) & 7];
3057*a67afe4dSAndroid Build Coastguard Worker 
3058*a67afe4dSAndroid Build Coastguard Worker          crc = crc_one_byte(crc, file_crc >> 24);
3059*a67afe4dSAndroid Build Coastguard Worker          file_crc = (file_crc << 8) + ch;
3060*a67afe4dSAndroid Build Coastguard Worker       }
3061*a67afe4dSAndroid Build Coastguard Worker 
3062*a67afe4dSAndroid Build Coastguard Worker       /* Control gets to here if when 0x7fffffff bytes (plus 8) have been read,
3063*a67afe4dSAndroid Build Coastguard Worker        * ok, treat this as a damaged stream too:
3064*a67afe4dSAndroid Build Coastguard Worker        */
3065*a67afe4dSAndroid Build Coastguard Worker    }
3066*a67afe4dSAndroid Build Coastguard Worker 
3067*a67afe4dSAndroid Build Coastguard Worker truncated:
3068*a67afe4dSAndroid Build Coastguard Worker    stop(file, READ_ERROR_CODE, "damaged PNG stream");
3069*a67afe4dSAndroid Build Coastguard Worker }
3070*a67afe4dSAndroid Build Coastguard Worker 
3071*a67afe4dSAndroid Build Coastguard Worker static void
read_chunk(struct file * file)3072*a67afe4dSAndroid Build Coastguard Worker read_chunk(struct file *file)
3073*a67afe4dSAndroid Build Coastguard Worker    /* On entry file::data_pos must be set to the position of the first byte
3074*a67afe4dSAndroid Build Coastguard Worker     * of the chunk data *and* the input file must be at this position.  This
3075*a67afe4dSAndroid Build Coastguard Worker     * routine (via process_chunk) instantiates a chunk or IDAT control structure
3076*a67afe4dSAndroid Build Coastguard Worker     * based on file::length and file::type and also resets these fields and
3077*a67afe4dSAndroid Build Coastguard Worker     * file::data_pos for the chunk after this one.  For an IDAT chunk the whole
3078*a67afe4dSAndroid Build Coastguard Worker     * stream of IDATs will be read, until something other than an IDAT is
3079*a67afe4dSAndroid Build Coastguard Worker     * encountered, and the file fields will be set for the chunk after the end
3080*a67afe4dSAndroid Build Coastguard Worker     * of the stream of IDATs.
3081*a67afe4dSAndroid Build Coastguard Worker     *
3082*a67afe4dSAndroid Build Coastguard Worker     * For IEND the file::type field will be set to 0, and nothing beyond the end
3083*a67afe4dSAndroid Build Coastguard Worker     * of the IEND chunk will have been read.
3084*a67afe4dSAndroid Build Coastguard Worker     */
3085*a67afe4dSAndroid Build Coastguard Worker {
3086*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 length = file->length;
3087*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 type = file->type;
3088*a67afe4dSAndroid Build Coastguard Worker 
3089*a67afe4dSAndroid Build Coastguard Worker    /* After IEND file::type is set to 0, if libpng attempts to read
3090*a67afe4dSAndroid Build Coastguard Worker     * more data at this point this is a bug in libpng.
3091*a67afe4dSAndroid Build Coastguard Worker     */
3092*a67afe4dSAndroid Build Coastguard Worker    if (type == 0)
3093*a67afe4dSAndroid Build Coastguard Worker       stop(file, UNEXPECTED_ERROR_CODE, "read beyond IEND");
3094*a67afe4dSAndroid Build Coastguard Worker 
3095*a67afe4dSAndroid Build Coastguard Worker    if (file->global->verbose > 2)
3096*a67afe4dSAndroid Build Coastguard Worker    {
3097*a67afe4dSAndroid Build Coastguard Worker       fputs("   ", stderr);
3098*a67afe4dSAndroid Build Coastguard Worker       type_name(type, stderr);
3099*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, " %lu\n", (unsigned long)length);
3100*a67afe4dSAndroid Build Coastguard Worker    }
3101*a67afe4dSAndroid Build Coastguard Worker 
3102*a67afe4dSAndroid Build Coastguard Worker    /* Start the read_crc calculation with the chunk type, then read to the end
3103*a67afe4dSAndroid Build Coastguard Worker     * of the chunk data (without processing it in any way) to check that it is
3104*a67afe4dSAndroid Build Coastguard Worker     * all there and calculate the CRC.
3105*a67afe4dSAndroid Build Coastguard Worker     */
3106*a67afe4dSAndroid Build Coastguard Worker    file->crc = crc_init_4(type);
3107*a67afe4dSAndroid Build Coastguard Worker    if (crc_read_many(file, length)) /* else it was truncated */
3108*a67afe4dSAndroid Build Coastguard Worker    {
3109*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 file_crc; /* CRC read from file */
3110*a67afe4dSAndroid Build Coastguard Worker       unsigned int nread = read_4(file, &file_crc);
3111*a67afe4dSAndroid Build Coastguard Worker 
3112*a67afe4dSAndroid Build Coastguard Worker       if (nread == 4)
3113*a67afe4dSAndroid Build Coastguard Worker       {
3114*a67afe4dSAndroid Build Coastguard Worker          if (type != png_IEND) /* do not read beyond IEND */
3115*a67afe4dSAndroid Build Coastguard Worker          {
3116*a67afe4dSAndroid Build Coastguard Worker             png_uint_32 next_length;
3117*a67afe4dSAndroid Build Coastguard Worker 
3118*a67afe4dSAndroid Build Coastguard Worker             nread += read_4(file, &next_length);
3119*a67afe4dSAndroid Build Coastguard Worker             if (nread == 8 && next_length <= 0x7fffffff)
3120*a67afe4dSAndroid Build Coastguard Worker             {
3121*a67afe4dSAndroid Build Coastguard Worker                png_uint_32 next_type;
3122*a67afe4dSAndroid Build Coastguard Worker 
3123*a67afe4dSAndroid Build Coastguard Worker                nread += read_4(file, &next_type);
3124*a67afe4dSAndroid Build Coastguard Worker 
3125*a67afe4dSAndroid Build Coastguard Worker                if (nread == 12 && chunk_type_valid(next_type))
3126*a67afe4dSAndroid Build Coastguard Worker                {
3127*a67afe4dSAndroid Build Coastguard Worker                   /* Adjust the read count back to the correct value for this
3128*a67afe4dSAndroid Build Coastguard Worker                    * chunk.
3129*a67afe4dSAndroid Build Coastguard Worker                    */
3130*a67afe4dSAndroid Build Coastguard Worker                   file->read_count -= 8;
3131*a67afe4dSAndroid Build Coastguard Worker                   process_chunk(file, file_crc, next_length, next_type);
3132*a67afe4dSAndroid Build Coastguard Worker                   return;
3133*a67afe4dSAndroid Build Coastguard Worker                }
3134*a67afe4dSAndroid Build Coastguard Worker             }
3135*a67afe4dSAndroid Build Coastguard Worker          }
3136*a67afe4dSAndroid Build Coastguard Worker 
3137*a67afe4dSAndroid Build Coastguard Worker          else /* IEND */
3138*a67afe4dSAndroid Build Coastguard Worker          {
3139*a67afe4dSAndroid Build Coastguard Worker             process_chunk(file, file_crc, 0, 0);
3140*a67afe4dSAndroid Build Coastguard Worker             return;
3141*a67afe4dSAndroid Build Coastguard Worker          }
3142*a67afe4dSAndroid Build Coastguard Worker       }
3143*a67afe4dSAndroid Build Coastguard Worker    }
3144*a67afe4dSAndroid Build Coastguard Worker 
3145*a67afe4dSAndroid Build Coastguard Worker    /* Control gets to here if the stream seems invalid or damaged in some
3146*a67afe4dSAndroid Build Coastguard Worker     * way.  Either there was a problem reading all the expected data (this
3147*a67afe4dSAndroid Build Coastguard Worker     * chunk's data, its CRC and the length and type of the next chunk) or the
3148*a67afe4dSAndroid Build Coastguard Worker     * next chunk length/type are invalid.  Notice that the cases that end up
3149*a67afe4dSAndroid Build Coastguard Worker     * here all correspond to cases that would otherwise terminate the read of
3150*a67afe4dSAndroid Build Coastguard Worker     * the PNG file.
3151*a67afe4dSAndroid Build Coastguard Worker     */
3152*a67afe4dSAndroid Build Coastguard Worker    sync_stream(file);
3153*a67afe4dSAndroid Build Coastguard Worker }
3154*a67afe4dSAndroid Build Coastguard Worker 
3155*a67afe4dSAndroid Build Coastguard Worker /* This returns a file* from a png_struct in an implementation specific way. */
3156*a67afe4dSAndroid Build Coastguard Worker static struct file *get_control(png_const_structrp png_ptr);
3157*a67afe4dSAndroid Build Coastguard Worker 
3158*a67afe4dSAndroid Build Coastguard Worker static void PNGCBAPI
error_handler(png_structp png_ptr,png_const_charp message)3159*a67afe4dSAndroid Build Coastguard Worker error_handler(png_structp png_ptr, png_const_charp message)
3160*a67afe4dSAndroid Build Coastguard Worker {
3161*a67afe4dSAndroid Build Coastguard Worker    stop(get_control(png_ptr),  LIBPNG_ERROR_CODE, message);
3162*a67afe4dSAndroid Build Coastguard Worker }
3163*a67afe4dSAndroid Build Coastguard Worker 
3164*a67afe4dSAndroid Build Coastguard Worker static void PNGCBAPI
warning_handler(png_structp png_ptr,png_const_charp message)3165*a67afe4dSAndroid Build Coastguard Worker warning_handler(png_structp png_ptr, png_const_charp message)
3166*a67afe4dSAndroid Build Coastguard Worker {
3167*a67afe4dSAndroid Build Coastguard Worker    struct file *file = get_control(png_ptr);
3168*a67afe4dSAndroid Build Coastguard Worker 
3169*a67afe4dSAndroid Build Coastguard Worker    if (file->global->warnings)
3170*a67afe4dSAndroid Build Coastguard Worker       emit_error(file, LIBPNG_WARNING_CODE, message);
3171*a67afe4dSAndroid Build Coastguard Worker }
3172*a67afe4dSAndroid Build Coastguard Worker 
3173*a67afe4dSAndroid Build Coastguard Worker /* Read callback - this is where the work gets done to check the stream before
3174*a67afe4dSAndroid Build Coastguard Worker  * passing it to libpng
3175*a67afe4dSAndroid Build Coastguard Worker  */
3176*a67afe4dSAndroid Build Coastguard Worker static void PNGCBAPI
read_callback(png_structp png_ptr,png_bytep buffer,size_t count)3177*a67afe4dSAndroid Build Coastguard Worker read_callback(png_structp png_ptr, png_bytep buffer, size_t count)
3178*a67afe4dSAndroid Build Coastguard Worker    /* Return 'count' bytes to libpng in 'buffer' */
3179*a67afe4dSAndroid Build Coastguard Worker {
3180*a67afe4dSAndroid Build Coastguard Worker    struct file *file = get_control(png_ptr);
3181*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 type, length; /* For the chunk be *WRITTEN* */
3182*a67afe4dSAndroid Build Coastguard Worker    struct chunk *chunk;
3183*a67afe4dSAndroid Build Coastguard Worker 
3184*a67afe4dSAndroid Build Coastguard Worker    /* libpng should always ask for at least one byte */
3185*a67afe4dSAndroid Build Coastguard Worker    if (count == 0)
3186*a67afe4dSAndroid Build Coastguard Worker       stop(file, UNEXPECTED_ERROR_CODE, "read callback for 0 bytes");
3187*a67afe4dSAndroid Build Coastguard Worker 
3188*a67afe4dSAndroid Build Coastguard Worker    /* The callback always reads ahead by 8 bytes - the signature or chunk header
3189*a67afe4dSAndroid Build Coastguard Worker     * - these bytes are stored in chunk_length and chunk_type.  This block is
3190*a67afe4dSAndroid Build Coastguard Worker     * executed once for the signature and once for the first chunk right at the
3191*a67afe4dSAndroid Build Coastguard Worker     * start.
3192*a67afe4dSAndroid Build Coastguard Worker     */
3193*a67afe4dSAndroid Build Coastguard Worker    if (file->read_count < 8)
3194*a67afe4dSAndroid Build Coastguard Worker    {
3195*a67afe4dSAndroid Build Coastguard Worker       assert(file->read_count == 0);
3196*a67afe4dSAndroid Build Coastguard Worker       assert((file->status_code & TRUNCATED) == 0);
3197*a67afe4dSAndroid Build Coastguard Worker 
3198*a67afe4dSAndroid Build Coastguard Worker       (void)read_4(file, &file->length);
3199*a67afe4dSAndroid Build Coastguard Worker 
3200*a67afe4dSAndroid Build Coastguard Worker       if (file->read_count == 4)
3201*a67afe4dSAndroid Build Coastguard Worker          (void)read_4(file, &file->type);
3202*a67afe4dSAndroid Build Coastguard Worker 
3203*a67afe4dSAndroid Build Coastguard Worker       if (file->read_count < 8)
3204*a67afe4dSAndroid Build Coastguard Worker       {
3205*a67afe4dSAndroid Build Coastguard Worker          assert((file->status_code & TRUNCATED) != 0);
3206*a67afe4dSAndroid Build Coastguard Worker          stop(file, READ_ERROR_CODE, "not a PNG (too short)");
3207*a67afe4dSAndroid Build Coastguard Worker       }
3208*a67afe4dSAndroid Build Coastguard Worker 
3209*a67afe4dSAndroid Build Coastguard Worker       if (file->state == STATE_SIGNATURE)
3210*a67afe4dSAndroid Build Coastguard Worker       {
3211*a67afe4dSAndroid Build Coastguard Worker          if (file->length != sig1 || file->type != sig2)
3212*a67afe4dSAndroid Build Coastguard Worker             stop(file, LIBPNG_ERROR_CODE, "not a PNG (signature)");
3213*a67afe4dSAndroid Build Coastguard Worker 
3214*a67afe4dSAndroid Build Coastguard Worker          /* Else write it (this is the initialization of write_count, prior to
3215*a67afe4dSAndroid Build Coastguard Worker           * this it contains CLEAR garbage.)
3216*a67afe4dSAndroid Build Coastguard Worker           */
3217*a67afe4dSAndroid Build Coastguard Worker          file->write_count = 0;
3218*a67afe4dSAndroid Build Coastguard Worker       }
3219*a67afe4dSAndroid Build Coastguard Worker 
3220*a67afe4dSAndroid Build Coastguard Worker       else
3221*a67afe4dSAndroid Build Coastguard Worker       {
3222*a67afe4dSAndroid Build Coastguard Worker          assert(file->state == STATE_CHUNKS);
3223*a67afe4dSAndroid Build Coastguard Worker 
3224*a67afe4dSAndroid Build Coastguard Worker          /* The first chunk must be a well formed IHDR (this could be relaxed to
3225*a67afe4dSAndroid Build Coastguard Worker           * use the checks in process_chunk, but that seems unnecessary.)
3226*a67afe4dSAndroid Build Coastguard Worker           */
3227*a67afe4dSAndroid Build Coastguard Worker          if (file->length != 13 || file->type != png_IHDR)
3228*a67afe4dSAndroid Build Coastguard Worker             stop(file, LIBPNG_ERROR_CODE, "not a PNG (IHDR)");
3229*a67afe4dSAndroid Build Coastguard Worker 
3230*a67afe4dSAndroid Build Coastguard Worker          /* The position of the data must be stored too */
3231*a67afe4dSAndroid Build Coastguard Worker          getpos(file);
3232*a67afe4dSAndroid Build Coastguard Worker       }
3233*a67afe4dSAndroid Build Coastguard Worker    }
3234*a67afe4dSAndroid Build Coastguard Worker 
3235*a67afe4dSAndroid Build Coastguard Worker    /* Retrieve previous state (because the read callbacks are made pretty much
3236*a67afe4dSAndroid Build Coastguard Worker     * byte-by-byte in the sequential reader prior to 1.7).
3237*a67afe4dSAndroid Build Coastguard Worker     */
3238*a67afe4dSAndroid Build Coastguard Worker    chunk = file->chunk;
3239*a67afe4dSAndroid Build Coastguard Worker 
3240*a67afe4dSAndroid Build Coastguard Worker    if (chunk != NULL)
3241*a67afe4dSAndroid Build Coastguard Worker    {
3242*a67afe4dSAndroid Build Coastguard Worker       length = chunk->chunk_length;
3243*a67afe4dSAndroid Build Coastguard Worker       type = chunk->chunk_type;
3244*a67afe4dSAndroid Build Coastguard Worker    }
3245*a67afe4dSAndroid Build Coastguard Worker 
3246*a67afe4dSAndroid Build Coastguard Worker    else
3247*a67afe4dSAndroid Build Coastguard Worker    {
3248*a67afe4dSAndroid Build Coastguard Worker       /* This is the signature case; for IDAT and other chunks these values will
3249*a67afe4dSAndroid Build Coastguard Worker        * be overwritten when read_chunk is called below.
3250*a67afe4dSAndroid Build Coastguard Worker        */
3251*a67afe4dSAndroid Build Coastguard Worker       length = file->length;
3252*a67afe4dSAndroid Build Coastguard Worker       type = file->type;
3253*a67afe4dSAndroid Build Coastguard Worker    }
3254*a67afe4dSAndroid Build Coastguard Worker 
3255*a67afe4dSAndroid Build Coastguard Worker    do
3256*a67afe4dSAndroid Build Coastguard Worker    {
3257*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 b;
3258*a67afe4dSAndroid Build Coastguard Worker 
3259*a67afe4dSAndroid Build Coastguard Worker       /* Complete the read of a chunk; as a side effect this also instantiates
3260*a67afe4dSAndroid Build Coastguard Worker        * a chunk control structure and sets the file length/type/data_pos fields
3261*a67afe4dSAndroid Build Coastguard Worker        * for the *NEXT* chunk header.
3262*a67afe4dSAndroid Build Coastguard Worker        *
3263*a67afe4dSAndroid Build Coastguard Worker        * NOTE: at an IDAT any following IDAT chunks will also be read and the
3264*a67afe4dSAndroid Build Coastguard Worker        * next_ fields will refer to the chunk after the last IDAT.
3265*a67afe4dSAndroid Build Coastguard Worker        *
3266*a67afe4dSAndroid Build Coastguard Worker        * NOTE: read_chunk only returns when it has read a chunk that must now be
3267*a67afe4dSAndroid Build Coastguard Worker        * written.
3268*a67afe4dSAndroid Build Coastguard Worker        */
3269*a67afe4dSAndroid Build Coastguard Worker       if (file->state != STATE_SIGNATURE && chunk == NULL)
3270*a67afe4dSAndroid Build Coastguard Worker       {
3271*a67afe4dSAndroid Build Coastguard Worker          assert(file->read_count == 8);
3272*a67afe4dSAndroid Build Coastguard Worker          assert(file->idat == NULL);
3273*a67afe4dSAndroid Build Coastguard Worker          read_chunk(file);
3274*a67afe4dSAndroid Build Coastguard Worker          chunk = file->chunk;
3275*a67afe4dSAndroid Build Coastguard Worker          assert(chunk != NULL);
3276*a67afe4dSAndroid Build Coastguard Worker 
3277*a67afe4dSAndroid Build Coastguard Worker          /* Do the initialization that was not done before. */
3278*a67afe4dSAndroid Build Coastguard Worker          length = chunk->chunk_length;
3279*a67afe4dSAndroid Build Coastguard Worker          type = chunk->chunk_type;
3280*a67afe4dSAndroid Build Coastguard Worker 
3281*a67afe4dSAndroid Build Coastguard Worker          /* And start writing the new chunk. */
3282*a67afe4dSAndroid Build Coastguard Worker          file->write_count = 0;
3283*a67afe4dSAndroid Build Coastguard Worker       }
3284*a67afe4dSAndroid Build Coastguard Worker 
3285*a67afe4dSAndroid Build Coastguard Worker       /* The chunk_ fields describe a chunk that must be written, or hold the
3286*a67afe4dSAndroid Build Coastguard Worker        * signature.  Write the header first.  In the signature case this
3287*a67afe4dSAndroid Build Coastguard Worker        * rewrites the signature.
3288*a67afe4dSAndroid Build Coastguard Worker        */
3289*a67afe4dSAndroid Build Coastguard Worker       switch (file->write_count)
3290*a67afe4dSAndroid Build Coastguard Worker       {
3291*a67afe4dSAndroid Build Coastguard Worker          case 0: b = length >> 24; break;
3292*a67afe4dSAndroid Build Coastguard Worker          case 1: b = length >> 16; break;
3293*a67afe4dSAndroid Build Coastguard Worker          case 2: b = length >>  8; break;
3294*a67afe4dSAndroid Build Coastguard Worker          case 3: b = length      ; break;
3295*a67afe4dSAndroid Build Coastguard Worker 
3296*a67afe4dSAndroid Build Coastguard Worker          case 4: b = type >> 24; break;
3297*a67afe4dSAndroid Build Coastguard Worker          case 5: b = type >> 16; break;
3298*a67afe4dSAndroid Build Coastguard Worker          case 6: b = type >>  8; break;
3299*a67afe4dSAndroid Build Coastguard Worker          case 7: b = type      ; break;
3300*a67afe4dSAndroid Build Coastguard Worker 
3301*a67afe4dSAndroid Build Coastguard Worker          case 8:
3302*a67afe4dSAndroid Build Coastguard Worker             /* The header has been written.  If this is really the signature
3303*a67afe4dSAndroid Build Coastguard Worker              * that's all that is required and we can go to normal chunk
3304*a67afe4dSAndroid Build Coastguard Worker              * processing.
3305*a67afe4dSAndroid Build Coastguard Worker              */
3306*a67afe4dSAndroid Build Coastguard Worker             if (file->state == STATE_SIGNATURE)
3307*a67afe4dSAndroid Build Coastguard Worker             {
3308*a67afe4dSAndroid Build Coastguard Worker                /* The signature has been written, the tail call to read_callback
3309*a67afe4dSAndroid Build Coastguard Worker                 * below (it's just a goto to the start with a decent compiler)
3310*a67afe4dSAndroid Build Coastguard Worker                 * will read the IHDR header ahead and validate it.
3311*a67afe4dSAndroid Build Coastguard Worker                 */
3312*a67afe4dSAndroid Build Coastguard Worker                assert(length == sig1 && type == sig2);
3313*a67afe4dSAndroid Build Coastguard Worker                file->read_count = 0; /* Forces a header read */
3314*a67afe4dSAndroid Build Coastguard Worker                file->state = STATE_CHUNKS; /* IHDR: checked above */
3315*a67afe4dSAndroid Build Coastguard Worker                read_callback(png_ptr, buffer, count);
3316*a67afe4dSAndroid Build Coastguard Worker                return;
3317*a67afe4dSAndroid Build Coastguard Worker             }
3318*a67afe4dSAndroid Build Coastguard Worker 
3319*a67afe4dSAndroid Build Coastguard Worker             else
3320*a67afe4dSAndroid Build Coastguard Worker             {
3321*a67afe4dSAndroid Build Coastguard Worker                assert(chunk != NULL);
3322*a67afe4dSAndroid Build Coastguard Worker 
3323*a67afe4dSAndroid Build Coastguard Worker                /* Set up for write, notice that repositioning the input stream
3324*a67afe4dSAndroid Build Coastguard Worker                 * is only necessary if something is to be read from it.  Also
3325*a67afe4dSAndroid Build Coastguard Worker                 * notice that for the IDAT stream this must only happen once -
3326*a67afe4dSAndroid Build Coastguard Worker                 * on the first IDAT - to get back to the start of the list and
3327*a67afe4dSAndroid Build Coastguard Worker                 * this is done inside process_IDAT:
3328*a67afe4dSAndroid Build Coastguard Worker                 */
3329*a67afe4dSAndroid Build Coastguard Worker                chunk->write_crc = crc_init_4(type);
3330*a67afe4dSAndroid Build Coastguard Worker                if (file->state != STATE_IDAT && length > 0)
3331*a67afe4dSAndroid Build Coastguard Worker                   setpos(chunk);
3332*a67afe4dSAndroid Build Coastguard Worker             }
3333*a67afe4dSAndroid Build Coastguard Worker             /* FALLTHROUGH */
3334*a67afe4dSAndroid Build Coastguard Worker 
3335*a67afe4dSAndroid Build Coastguard Worker          default:
3336*a67afe4dSAndroid Build Coastguard Worker             assert(chunk != NULL);
3337*a67afe4dSAndroid Build Coastguard Worker 
3338*a67afe4dSAndroid Build Coastguard Worker             /* NOTE: the arithmetic below overflows and gives a large positive
3339*a67afe4dSAndroid Build Coastguard Worker              * png_uint_32 value until the whole chunk data has been written.
3340*a67afe4dSAndroid Build Coastguard Worker              */
3341*a67afe4dSAndroid Build Coastguard Worker             switch (file->write_count - length)
3342*a67afe4dSAndroid Build Coastguard Worker             {
3343*a67afe4dSAndroid Build Coastguard Worker                /* Write the chunk data, normally this just comes from
3344*a67afe4dSAndroid Build Coastguard Worker                 * the file.  The only exception is for that part of a
3345*a67afe4dSAndroid Build Coastguard Worker                 * chunk which is zlib data and which must be rewritten,
3346*a67afe4dSAndroid Build Coastguard Worker                 * and IDAT chunks which can be completely
3347*a67afe4dSAndroid Build Coastguard Worker                 * reconstructed.
3348*a67afe4dSAndroid Build Coastguard Worker                 */
3349*a67afe4dSAndroid Build Coastguard Worker                default:
3350*a67afe4dSAndroid Build Coastguard Worker                   if (file->state == STATE_IDAT)
3351*a67afe4dSAndroid Build Coastguard Worker                   {
3352*a67afe4dSAndroid Build Coastguard Worker                      struct IDAT *idat = file->idat;
3353*a67afe4dSAndroid Build Coastguard Worker 
3354*a67afe4dSAndroid Build Coastguard Worker                      assert(idat != NULL);
3355*a67afe4dSAndroid Build Coastguard Worker 
3356*a67afe4dSAndroid Build Coastguard Worker                      /* Read an IDAT byte from the input stream of IDAT chunks.
3357*a67afe4dSAndroid Build Coastguard Worker                       * Because the IDAT stream can be re-chunked this stream is
3358*a67afe4dSAndroid Build Coastguard Worker                       * held in the struct IDAT members.  The chunk members, in
3359*a67afe4dSAndroid Build Coastguard Worker                       * particular chunk_length (and therefore the length local)
3360*a67afe4dSAndroid Build Coastguard Worker                       * refer to the output chunk.
3361*a67afe4dSAndroid Build Coastguard Worker                       */
3362*a67afe4dSAndroid Build Coastguard Worker                      while (idat->idat_index >= idat->idat_length)
3363*a67afe4dSAndroid Build Coastguard Worker                      {
3364*a67afe4dSAndroid Build Coastguard Worker                         /* Advance one chunk */
3365*a67afe4dSAndroid Build Coastguard Worker                         struct IDAT_list *cur = idat->idat_cur;
3366*a67afe4dSAndroid Build Coastguard Worker 
3367*a67afe4dSAndroid Build Coastguard Worker                         assert(idat->idat_index == idat->idat_length);
3368*a67afe4dSAndroid Build Coastguard Worker                         assert(cur != NULL && cur->count > 0);
3369*a67afe4dSAndroid Build Coastguard Worker 
3370*a67afe4dSAndroid Build Coastguard Worker                         /* NOTE: IDAT_list::count here, not IDAT_list::length */
3371*a67afe4dSAndroid Build Coastguard Worker                         if (++(idat->idat_count) >= cur->count)
3372*a67afe4dSAndroid Build Coastguard Worker                         {
3373*a67afe4dSAndroid Build Coastguard Worker                            assert(idat->idat_count == cur->count);
3374*a67afe4dSAndroid Build Coastguard Worker 
3375*a67afe4dSAndroid Build Coastguard Worker                            /* Move on to the next IDAT_list: */
3376*a67afe4dSAndroid Build Coastguard Worker                            cur = cur->next;
3377*a67afe4dSAndroid Build Coastguard Worker 
3378*a67afe4dSAndroid Build Coastguard Worker                            /* This is an internal error - read beyond the end of
3379*a67afe4dSAndroid Build Coastguard Worker                             * the pre-calculated stream.
3380*a67afe4dSAndroid Build Coastguard Worker                             */
3381*a67afe4dSAndroid Build Coastguard Worker                            if (cur == NULL || cur->count == 0)
3382*a67afe4dSAndroid Build Coastguard Worker                               stop(file, UNEXPECTED_ERROR_CODE,
3383*a67afe4dSAndroid Build Coastguard Worker                                  "read beyond end of IDAT");
3384*a67afe4dSAndroid Build Coastguard Worker 
3385*a67afe4dSAndroid Build Coastguard Worker                            idat->idat_count = 0;
3386*a67afe4dSAndroid Build Coastguard Worker                            idat->idat_cur = cur;
3387*a67afe4dSAndroid Build Coastguard Worker                         }
3388*a67afe4dSAndroid Build Coastguard Worker 
3389*a67afe4dSAndroid Build Coastguard Worker                         idat->idat_index = 0;
3390*a67afe4dSAndroid Build Coastguard Worker                         /* Zero length IDAT chunks are permitted, so the length
3391*a67afe4dSAndroid Build Coastguard Worker                          * here may be 0.
3392*a67afe4dSAndroid Build Coastguard Worker                          */
3393*a67afe4dSAndroid Build Coastguard Worker                         idat->idat_length = cur->lengths[idat->idat_count];
3394*a67afe4dSAndroid Build Coastguard Worker 
3395*a67afe4dSAndroid Build Coastguard Worker                         /* And skip 12 bytes to the next chunk data */
3396*a67afe4dSAndroid Build Coastguard Worker                         skip_12(file);
3397*a67afe4dSAndroid Build Coastguard Worker                      }
3398*a67afe4dSAndroid Build Coastguard Worker 
3399*a67afe4dSAndroid Build Coastguard Worker                      /* The index is always that of the next byte, the rest of
3400*a67afe4dSAndroid Build Coastguard Worker                       * the information is always the current IDAT chunk and the
3401*a67afe4dSAndroid Build Coastguard Worker                       * current list.
3402*a67afe4dSAndroid Build Coastguard Worker                       */
3403*a67afe4dSAndroid Build Coastguard Worker                      ++(idat->idat_index);
3404*a67afe4dSAndroid Build Coastguard Worker                   }
3405*a67afe4dSAndroid Build Coastguard Worker 
3406*a67afe4dSAndroid Build Coastguard Worker                   /* Read the byte from the stream. */
3407*a67afe4dSAndroid Build Coastguard Worker                   b = reread_byte(file);
3408*a67afe4dSAndroid Build Coastguard Worker 
3409*a67afe4dSAndroid Build Coastguard Worker                   /* If the byte must be rewritten handle that here */
3410*a67afe4dSAndroid Build Coastguard Worker                   if (chunk->rewrite_length > 0)
3411*a67afe4dSAndroid Build Coastguard Worker                   {
3412*a67afe4dSAndroid Build Coastguard Worker                      if (chunk->rewrite_offset > 0)
3413*a67afe4dSAndroid Build Coastguard Worker                         --(chunk->rewrite_offset);
3414*a67afe4dSAndroid Build Coastguard Worker 
3415*a67afe4dSAndroid Build Coastguard Worker                      else
3416*a67afe4dSAndroid Build Coastguard Worker                      {
3417*a67afe4dSAndroid Build Coastguard Worker                         b = chunk->rewrite_buffer[0];
3418*a67afe4dSAndroid Build Coastguard Worker                         memmove(chunk->rewrite_buffer, chunk->rewrite_buffer+1,
3419*a67afe4dSAndroid Build Coastguard Worker                            (sizeof chunk->rewrite_buffer)-
3420*a67afe4dSAndroid Build Coastguard Worker                               (sizeof chunk->rewrite_buffer[0]));
3421*a67afe4dSAndroid Build Coastguard Worker 
3422*a67afe4dSAndroid Build Coastguard Worker                         --(chunk->rewrite_length);
3423*a67afe4dSAndroid Build Coastguard Worker                      }
3424*a67afe4dSAndroid Build Coastguard Worker                   }
3425*a67afe4dSAndroid Build Coastguard Worker 
3426*a67afe4dSAndroid Build Coastguard Worker                   chunk->write_crc = crc_one_byte(chunk->write_crc, b);
3427*a67afe4dSAndroid Build Coastguard Worker                   break;
3428*a67afe4dSAndroid Build Coastguard Worker 
3429*a67afe4dSAndroid Build Coastguard Worker                /* The CRC is written at:
3430*a67afe4dSAndroid Build Coastguard Worker                 *
3431*a67afe4dSAndroid Build Coastguard Worker                 *    chunk_write == chunk_length+8..chunk_length+11
3432*a67afe4dSAndroid Build Coastguard Worker                 *
3433*a67afe4dSAndroid Build Coastguard Worker                 * so 8 to 11.  The CRC is not (yet) conditioned.
3434*a67afe4dSAndroid Build Coastguard Worker                 */
3435*a67afe4dSAndroid Build Coastguard Worker                case  8: b = chunk->write_crc >> 24; goto write_crc;
3436*a67afe4dSAndroid Build Coastguard Worker                case  9: b = chunk->write_crc >> 16; goto write_crc;
3437*a67afe4dSAndroid Build Coastguard Worker                case 10: b = chunk->write_crc >>  8; goto write_crc;
3438*a67afe4dSAndroid Build Coastguard Worker                case 11:
3439*a67afe4dSAndroid Build Coastguard Worker                   /* This must happen before the chunk_end below: */
3440*a67afe4dSAndroid Build Coastguard Worker                   b = chunk->write_crc;
3441*a67afe4dSAndroid Build Coastguard Worker 
3442*a67afe4dSAndroid Build Coastguard Worker                   if (file->global->verbose > 2)
3443*a67afe4dSAndroid Build Coastguard Worker                   {
3444*a67afe4dSAndroid Build Coastguard Worker                      fputs("   ", stderr);
3445*a67afe4dSAndroid Build Coastguard Worker                      type_name(type, stderr);
3446*a67afe4dSAndroid Build Coastguard Worker                      fprintf(stderr, " %lu 0x%.8x\n", (unsigned long)length,
3447*a67afe4dSAndroid Build Coastguard Worker                         chunk->write_crc ^ 0xffffffff);
3448*a67afe4dSAndroid Build Coastguard Worker                   }
3449*a67afe4dSAndroid Build Coastguard Worker 
3450*a67afe4dSAndroid Build Coastguard Worker                   /* The IDAT stream is written without a call to read_chunk
3451*a67afe4dSAndroid Build Coastguard Worker                    * until the end is reached.  rechunk_length() calculates the
3452*a67afe4dSAndroid Build Coastguard Worker                    * length of the output chunks.  Control gets to this point at
3453*a67afe4dSAndroid Build Coastguard Worker                    * the end of an *output* chunk - the length calculated by
3454*a67afe4dSAndroid Build Coastguard Worker                    * rechunk_length.  If this corresponds to the end of the
3455*a67afe4dSAndroid Build Coastguard Worker                    * input stream stop writing IDAT chunks, otherwise continue.
3456*a67afe4dSAndroid Build Coastguard Worker                    */
3457*a67afe4dSAndroid Build Coastguard Worker                   if (file->state == STATE_IDAT &&
3458*a67afe4dSAndroid Build Coastguard Worker                      (file->idat->idat_index < file->idat->idat_length ||
3459*a67afe4dSAndroid Build Coastguard Worker                       1+file->idat->idat_count < file->idat->idat_cur->count ||
3460*a67afe4dSAndroid Build Coastguard Worker                       file->idat->idat_cur != file->idat->idat_list_tail))
3461*a67afe4dSAndroid Build Coastguard Worker                   {
3462*a67afe4dSAndroid Build Coastguard Worker                      /* Write another IDAT chunk.  Call rechunk_length to
3463*a67afe4dSAndroid Build Coastguard Worker                       * calculate the length required.
3464*a67afe4dSAndroid Build Coastguard Worker                       */
3465*a67afe4dSAndroid Build Coastguard Worker                      length = chunk->chunk_length =
3466*a67afe4dSAndroid Build Coastguard Worker                          rechunk_length(file->idat, 0/*end*/);
3467*a67afe4dSAndroid Build Coastguard Worker                      assert(type == png_IDAT);
3468*a67afe4dSAndroid Build Coastguard Worker                      file->write_count = 0; /* for the new chunk */
3469*a67afe4dSAndroid Build Coastguard Worker                      --(file->write_count); /* fake out the increment below */
3470*a67afe4dSAndroid Build Coastguard Worker                   }
3471*a67afe4dSAndroid Build Coastguard Worker 
3472*a67afe4dSAndroid Build Coastguard Worker                   else
3473*a67afe4dSAndroid Build Coastguard Worker                   {
3474*a67afe4dSAndroid Build Coastguard Worker                      /* Entered at the end of a non-IDAT chunk and at the end of
3475*a67afe4dSAndroid Build Coastguard Worker                       * the IDAT stream.  The rewrite should have been cleared.
3476*a67afe4dSAndroid Build Coastguard Worker                       */
3477*a67afe4dSAndroid Build Coastguard Worker                      if (chunk->rewrite_length > 0 || chunk->rewrite_offset > 0)
3478*a67afe4dSAndroid Build Coastguard Worker                         stop(file, UNEXPECTED_ERROR_CODE, "pending rewrite");
3479*a67afe4dSAndroid Build Coastguard Worker 
3480*a67afe4dSAndroid Build Coastguard Worker                      /* This is the last byte so reset chunk_read for the next
3481*a67afe4dSAndroid Build Coastguard Worker                       * chunk and move the input file to the position after the
3482*a67afe4dSAndroid Build Coastguard Worker                       * *next* chunk header if required.
3483*a67afe4dSAndroid Build Coastguard Worker                       */
3484*a67afe4dSAndroid Build Coastguard Worker                      file->read_count = 8;
3485*a67afe4dSAndroid Build Coastguard Worker                      file_setpos(file, &file->data_pos);
3486*a67afe4dSAndroid Build Coastguard Worker 
3487*a67afe4dSAndroid Build Coastguard Worker                      if (file->idat == NULL)
3488*a67afe4dSAndroid Build Coastguard Worker                         chunk_end(&file->chunk);
3489*a67afe4dSAndroid Build Coastguard Worker 
3490*a67afe4dSAndroid Build Coastguard Worker                      else
3491*a67afe4dSAndroid Build Coastguard Worker                         IDAT_end(&file->idat);
3492*a67afe4dSAndroid Build Coastguard Worker                   }
3493*a67afe4dSAndroid Build Coastguard Worker 
3494*a67afe4dSAndroid Build Coastguard Worker                write_crc:
3495*a67afe4dSAndroid Build Coastguard Worker                   b ^= 0xff; /* conditioning */
3496*a67afe4dSAndroid Build Coastguard Worker                   break;
3497*a67afe4dSAndroid Build Coastguard Worker             }
3498*a67afe4dSAndroid Build Coastguard Worker             break;
3499*a67afe4dSAndroid Build Coastguard Worker       }
3500*a67afe4dSAndroid Build Coastguard Worker 
3501*a67afe4dSAndroid Build Coastguard Worker       /* Write one byte */
3502*a67afe4dSAndroid Build Coastguard Worker       b &= 0xff;
3503*a67afe4dSAndroid Build Coastguard Worker       *buffer++ = (png_byte)b;
3504*a67afe4dSAndroid Build Coastguard Worker       --count;
3505*a67afe4dSAndroid Build Coastguard Worker       write_byte(file, (png_byte)b); /* increments chunk_write */
3506*a67afe4dSAndroid Build Coastguard Worker    }
3507*a67afe4dSAndroid Build Coastguard Worker    while (count > 0);
3508*a67afe4dSAndroid Build Coastguard Worker }
3509*a67afe4dSAndroid Build Coastguard Worker 
3510*a67afe4dSAndroid Build Coastguard Worker /* Bundle the file and an uninitialized chunk and IDAT control structure
3511*a67afe4dSAndroid Build Coastguard Worker  * together to allow implementation of the chunk/IDAT allocate routine.
3512*a67afe4dSAndroid Build Coastguard Worker  */
3513*a67afe4dSAndroid Build Coastguard Worker struct control
3514*a67afe4dSAndroid Build Coastguard Worker {
3515*a67afe4dSAndroid Build Coastguard Worker    struct file  file;
3516*a67afe4dSAndroid Build Coastguard Worker    struct chunk chunk;
3517*a67afe4dSAndroid Build Coastguard Worker    struct IDAT  idat;
3518*a67afe4dSAndroid Build Coastguard Worker };
3519*a67afe4dSAndroid Build Coastguard Worker 
3520*a67afe4dSAndroid Build Coastguard Worker static int
control_end(struct control * control)3521*a67afe4dSAndroid Build Coastguard Worker control_end(struct control *control)
3522*a67afe4dSAndroid Build Coastguard Worker {
3523*a67afe4dSAndroid Build Coastguard Worker    return file_end(&control->file);
3524*a67afe4dSAndroid Build Coastguard Worker }
3525*a67afe4dSAndroid Build Coastguard Worker 
3526*a67afe4dSAndroid Build Coastguard Worker static struct file *
get_control(png_const_structrp png_ptr)3527*a67afe4dSAndroid Build Coastguard Worker get_control(png_const_structrp png_ptr)
3528*a67afe4dSAndroid Build Coastguard Worker {
3529*a67afe4dSAndroid Build Coastguard Worker    /* This just returns the (file*).  The chunk and idat control structures
3530*a67afe4dSAndroid Build Coastguard Worker     * don't always exist.
3531*a67afe4dSAndroid Build Coastguard Worker     */
3532*a67afe4dSAndroid Build Coastguard Worker    struct control *control = voidcast(struct control*,
3533*a67afe4dSAndroid Build Coastguard Worker       png_get_error_ptr(png_ptr));
3534*a67afe4dSAndroid Build Coastguard Worker    return &control->file;
3535*a67afe4dSAndroid Build Coastguard Worker }
3536*a67afe4dSAndroid Build Coastguard Worker 
3537*a67afe4dSAndroid Build Coastguard Worker static void
allocate(struct file * file,int allocate_idat)3538*a67afe4dSAndroid Build Coastguard Worker allocate(struct file *file, int allocate_idat)
3539*a67afe4dSAndroid Build Coastguard Worker {
3540*a67afe4dSAndroid Build Coastguard Worker    struct control *control = voidcast(struct control*, file->alloc_ptr);
3541*a67afe4dSAndroid Build Coastguard Worker 
3542*a67afe4dSAndroid Build Coastguard Worker    if (allocate_idat)
3543*a67afe4dSAndroid Build Coastguard Worker    {
3544*a67afe4dSAndroid Build Coastguard Worker       assert(file->idat == NULL);
3545*a67afe4dSAndroid Build Coastguard Worker       IDAT_init(&control->idat, file);
3546*a67afe4dSAndroid Build Coastguard Worker    }
3547*a67afe4dSAndroid Build Coastguard Worker 
3548*a67afe4dSAndroid Build Coastguard Worker    else /* chunk */
3549*a67afe4dSAndroid Build Coastguard Worker    {
3550*a67afe4dSAndroid Build Coastguard Worker       assert(file->chunk == NULL);
3551*a67afe4dSAndroid Build Coastguard Worker       chunk_init(&control->chunk, file);
3552*a67afe4dSAndroid Build Coastguard Worker    }
3553*a67afe4dSAndroid Build Coastguard Worker }
3554*a67afe4dSAndroid Build Coastguard Worker 
3555*a67afe4dSAndroid Build Coastguard Worker static int
control_init(struct control * control,struct global * global,const char * file_name,const char * out_name)3556*a67afe4dSAndroid Build Coastguard Worker control_init(struct control *control, struct global *global,
3557*a67afe4dSAndroid Build Coastguard Worker    const char *file_name, const char *out_name)
3558*a67afe4dSAndroid Build Coastguard Worker    /* This wraps file_init(&control::file) and simply returns the result from
3559*a67afe4dSAndroid Build Coastguard Worker     * file_init.
3560*a67afe4dSAndroid Build Coastguard Worker     */
3561*a67afe4dSAndroid Build Coastguard Worker {
3562*a67afe4dSAndroid Build Coastguard Worker    return file_init(&control->file, global, file_name, out_name, control,
3563*a67afe4dSAndroid Build Coastguard Worker       allocate);
3564*a67afe4dSAndroid Build Coastguard Worker }
3565*a67afe4dSAndroid Build Coastguard Worker 
3566*a67afe4dSAndroid Build Coastguard Worker static int
read_png(struct control * control)3567*a67afe4dSAndroid Build Coastguard Worker read_png(struct control *control)
3568*a67afe4dSAndroid Build Coastguard Worker    /* Read a PNG, return 0 on success else an error (status) code; a bit mask as
3569*a67afe4dSAndroid Build Coastguard Worker     * defined for file::status_code as above.
3570*a67afe4dSAndroid Build Coastguard Worker     */
3571*a67afe4dSAndroid Build Coastguard Worker {
3572*a67afe4dSAndroid Build Coastguard Worker    png_structp png_ptr;
3573*a67afe4dSAndroid Build Coastguard Worker    png_infop info_ptr = NULL;
3574*a67afe4dSAndroid Build Coastguard Worker    volatile int rc;
3575*a67afe4dSAndroid Build Coastguard Worker 
3576*a67afe4dSAndroid Build Coastguard Worker    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, control,
3577*a67afe4dSAndroid Build Coastguard Worker       error_handler, warning_handler);
3578*a67afe4dSAndroid Build Coastguard Worker 
3579*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
3580*a67afe4dSAndroid Build Coastguard Worker    {
3581*a67afe4dSAndroid Build Coastguard Worker       /* This is not really expected. */
3582*a67afe4dSAndroid Build Coastguard Worker       log_error(&control->file, LIBPNG_ERROR_CODE, "OOM allocating png_struct");
3583*a67afe4dSAndroid Build Coastguard Worker       control->file.status_code |= INTERNAL_ERROR;
3584*a67afe4dSAndroid Build Coastguard Worker       return LIBPNG_ERROR_CODE;
3585*a67afe4dSAndroid Build Coastguard Worker    }
3586*a67afe4dSAndroid Build Coastguard Worker 
3587*a67afe4dSAndroid Build Coastguard Worker    rc = setjmp(control->file.jmpbuf);
3588*a67afe4dSAndroid Build Coastguard Worker    if (rc == 0)
3589*a67afe4dSAndroid Build Coastguard Worker    {
3590*a67afe4dSAndroid Build Coastguard Worker #     ifdef PNG_SET_USER_LIMITS_SUPPORTED
3591*a67afe4dSAndroid Build Coastguard Worker          /* Remove any limits on the size of PNG files that can be read,
3592*a67afe4dSAndroid Build Coastguard Worker           * without this we may reject files based on built-in safety
3593*a67afe4dSAndroid Build Coastguard Worker           * limits.
3594*a67afe4dSAndroid Build Coastguard Worker           */
3595*a67afe4dSAndroid Build Coastguard Worker          png_set_user_limits(png_ptr, 0x7fffffff, 0x7fffffff);
3596*a67afe4dSAndroid Build Coastguard Worker          png_set_chunk_cache_max(png_ptr, 0);
3597*a67afe4dSAndroid Build Coastguard Worker          png_set_chunk_malloc_max(png_ptr, 0);
3598*a67afe4dSAndroid Build Coastguard Worker #     endif
3599*a67afe4dSAndroid Build Coastguard Worker 
3600*a67afe4dSAndroid Build Coastguard Worker       png_set_read_fn(png_ptr, control, read_callback);
3601*a67afe4dSAndroid Build Coastguard Worker 
3602*a67afe4dSAndroid Build Coastguard Worker       info_ptr = png_create_info_struct(png_ptr);
3603*a67afe4dSAndroid Build Coastguard Worker       if (info_ptr == NULL)
3604*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "OOM allocating info structure");
3605*a67afe4dSAndroid Build Coastguard Worker 
3606*a67afe4dSAndroid Build Coastguard Worker       if (control->file.global->verbose)
3607*a67afe4dSAndroid Build Coastguard Worker          fprintf(stderr, " INFO\n");
3608*a67afe4dSAndroid Build Coastguard Worker 
3609*a67afe4dSAndroid Build Coastguard Worker       png_read_info(png_ptr, info_ptr);
3610*a67afe4dSAndroid Build Coastguard Worker 
3611*a67afe4dSAndroid Build Coastguard Worker       {
3612*a67afe4dSAndroid Build Coastguard Worker         png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
3613*a67afe4dSAndroid Build Coastguard Worker         int passes = png_set_interlace_handling(png_ptr);
3614*a67afe4dSAndroid Build Coastguard Worker         int pass;
3615*a67afe4dSAndroid Build Coastguard Worker 
3616*a67afe4dSAndroid Build Coastguard Worker         png_start_read_image(png_ptr);
3617*a67afe4dSAndroid Build Coastguard Worker 
3618*a67afe4dSAndroid Build Coastguard Worker         for (pass = 0; pass < passes; ++pass)
3619*a67afe4dSAndroid Build Coastguard Worker         {
3620*a67afe4dSAndroid Build Coastguard Worker            png_uint_32 y = height;
3621*a67afe4dSAndroid Build Coastguard Worker 
3622*a67afe4dSAndroid Build Coastguard Worker            /* NOTE: this skips asking libpng to return either version of
3623*a67afe4dSAndroid Build Coastguard Worker             * the image row, but libpng still reads the rows.
3624*a67afe4dSAndroid Build Coastguard Worker             */
3625*a67afe4dSAndroid Build Coastguard Worker            while (y-- > 0)
3626*a67afe4dSAndroid Build Coastguard Worker               png_read_row(png_ptr, NULL, NULL);
3627*a67afe4dSAndroid Build Coastguard Worker         }
3628*a67afe4dSAndroid Build Coastguard Worker       }
3629*a67afe4dSAndroid Build Coastguard Worker 
3630*a67afe4dSAndroid Build Coastguard Worker       if (control->file.global->verbose)
3631*a67afe4dSAndroid Build Coastguard Worker          fprintf(stderr, " END\n");
3632*a67afe4dSAndroid Build Coastguard Worker 
3633*a67afe4dSAndroid Build Coastguard Worker       /* Make sure to read to the end of the file: */
3634*a67afe4dSAndroid Build Coastguard Worker       png_read_end(png_ptr, info_ptr);
3635*a67afe4dSAndroid Build Coastguard Worker    }
3636*a67afe4dSAndroid Build Coastguard Worker 
3637*a67afe4dSAndroid Build Coastguard Worker    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
3638*a67afe4dSAndroid Build Coastguard Worker    return rc;
3639*a67afe4dSAndroid Build Coastguard Worker }
3640*a67afe4dSAndroid Build Coastguard Worker 
3641*a67afe4dSAndroid Build Coastguard Worker static int
one_file(struct global * global,const char * file_name,const char * out_name)3642*a67afe4dSAndroid Build Coastguard Worker one_file(struct global *global, const char *file_name, const char *out_name)
3643*a67afe4dSAndroid Build Coastguard Worker {
3644*a67afe4dSAndroid Build Coastguard Worker    int rc;
3645*a67afe4dSAndroid Build Coastguard Worker    struct control control;
3646*a67afe4dSAndroid Build Coastguard Worker 
3647*a67afe4dSAndroid Build Coastguard Worker    if (global->verbose)
3648*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, "FILE %s -> %s\n", file_name,
3649*a67afe4dSAndroid Build Coastguard Worker          out_name ? out_name : "<none>");
3650*a67afe4dSAndroid Build Coastguard Worker 
3651*a67afe4dSAndroid Build Coastguard Worker    /* Although control_init can return a failure code the structure is always
3652*a67afe4dSAndroid Build Coastguard Worker     * initialized, so control_end can be used to accumulate any status codes.
3653*a67afe4dSAndroid Build Coastguard Worker     */
3654*a67afe4dSAndroid Build Coastguard Worker    rc = control_init(&control, global, file_name, out_name);
3655*a67afe4dSAndroid Build Coastguard Worker 
3656*a67afe4dSAndroid Build Coastguard Worker    if (rc == 0)
3657*a67afe4dSAndroid Build Coastguard Worker       rc = read_png(&control);
3658*a67afe4dSAndroid Build Coastguard Worker 
3659*a67afe4dSAndroid Build Coastguard Worker    rc |= control_end(&control);
3660*a67afe4dSAndroid Build Coastguard Worker 
3661*a67afe4dSAndroid Build Coastguard Worker    return rc;
3662*a67afe4dSAndroid Build Coastguard Worker }
3663*a67afe4dSAndroid Build Coastguard Worker 
3664*a67afe4dSAndroid Build Coastguard Worker static void
usage(const char * prog)3665*a67afe4dSAndroid Build Coastguard Worker usage(const char *prog)
3666*a67afe4dSAndroid Build Coastguard Worker {
3667*a67afe4dSAndroid Build Coastguard Worker    /* ANSI C-90 limits strings to 509 characters, so use a string array: */
3668*a67afe4dSAndroid Build Coastguard Worker    size_t i;
3669*a67afe4dSAndroid Build Coastguard Worker    static const char *usage_string[] = {
3670*a67afe4dSAndroid Build Coastguard Worker "  Tests, optimizes and optionally fixes the zlib header in PNG files.",
3671*a67afe4dSAndroid Build Coastguard Worker "  Optionally, when fixing, strips ancillary chunks from the file.",
3672*a67afe4dSAndroid Build Coastguard Worker 0,
3673*a67afe4dSAndroid Build Coastguard Worker "OPTIONS",
3674*a67afe4dSAndroid Build Coastguard Worker "  OPERATION",
3675*a67afe4dSAndroid Build Coastguard Worker "      By default files are just checked for readability with a summary of the",
3676*a67afe4dSAndroid Build Coastguard Worker "      of zlib issues founds for each compressed chunk and the IDAT stream in",
3677*a67afe4dSAndroid Build Coastguard Worker "      the file.",
3678*a67afe4dSAndroid Build Coastguard Worker "    --optimize (-o):",
3679*a67afe4dSAndroid Build Coastguard Worker "      Find the smallest deflate window size for the compressed data.",
3680*a67afe4dSAndroid Build Coastguard Worker "    --strip=[none|crc|unsafe|unused|transform|color|all]:",
3681*a67afe4dSAndroid Build Coastguard Worker "        none (default):   Retain all chunks.",
3682*a67afe4dSAndroid Build Coastguard Worker "        crc:    Remove chunks with a bad CRC.",
3683*a67afe4dSAndroid Build Coastguard Worker "        unsafe: Remove chunks that may be unsafe to retain if the image data",
3684*a67afe4dSAndroid Build Coastguard Worker "                is modified.  This is set automatically if --max is given but",
3685*a67afe4dSAndroid Build Coastguard Worker "                may be cancelled by a later --strip=none.",
3686*a67afe4dSAndroid Build Coastguard Worker "        unused: Remove chunks not used by libpng when decoding an image.",
3687*a67afe4dSAndroid Build Coastguard Worker "                This retains any chunks that might be used by libpng image",
3688*a67afe4dSAndroid Build Coastguard Worker "                transformations.",
3689*a67afe4dSAndroid Build Coastguard Worker "        transform: unused+bKGD.",
3690*a67afe4dSAndroid Build Coastguard Worker "        color:  transform+iCCP and cHRM.",
3691*a67afe4dSAndroid Build Coastguard Worker "        all:    color+gAMA and sRGB.",
3692*a67afe4dSAndroid Build Coastguard Worker "      Only ancillary chunks are ever removed.  In addition the tRNS and sBIT",
3693*a67afe4dSAndroid Build Coastguard Worker "      chunks are never removed as they affect exact interpretation of the",
3694*a67afe4dSAndroid Build Coastguard Worker "      image pixel values.  The following known chunks are treated specially",
3695*a67afe4dSAndroid Build Coastguard Worker "      by the above options:",
3696*a67afe4dSAndroid Build Coastguard Worker "        gAMA, sRGB [all]: These specify the gamma encoding used for the pixel",
3697*a67afe4dSAndroid Build Coastguard Worker "            values.",
3698*a67afe4dSAndroid Build Coastguard Worker "        cHRM, iCCP [color]: These specify how colors are encoded.  iCCP also",
3699*a67afe4dSAndroid Build Coastguard Worker "            specifies the exact encoding of a pixel value; however, in",
3700*a67afe4dSAndroid Build Coastguard Worker "            practice most programs will ignore it.",
3701*a67afe4dSAndroid Build Coastguard Worker "        bKGD [transform]: This is used by libpng transforms."
3702*a67afe4dSAndroid Build Coastguard Worker "    --max=<number>:",
3703*a67afe4dSAndroid Build Coastguard Worker "      Use IDAT chunks sized <number>.  If no number is given the IDAT",
3704*a67afe4dSAndroid Build Coastguard Worker "      chunks will be the maximum size permitted; 2^31-1 bytes.  If the option",
3705*a67afe4dSAndroid Build Coastguard Worker "      is omitted the original chunk sizes will not be changed.  When the",
3706*a67afe4dSAndroid Build Coastguard Worker "      option is given --strip=unsafe is set automatically. This may be",
3707*a67afe4dSAndroid Build Coastguard Worker "      cancelled if you know that all unknown unsafe-to-copy chunks really are",
3708*a67afe4dSAndroid Build Coastguard Worker "      safe to copy across an IDAT size change.  This is true of all chunks",
3709*a67afe4dSAndroid Build Coastguard Worker "      that have ever been formally proposed as PNG extensions.",
3710*a67afe4dSAndroid Build Coastguard Worker "  MESSAGES",
3711*a67afe4dSAndroid Build Coastguard Worker "      By default the program only outputs summaries for each file.",
3712*a67afe4dSAndroid Build Coastguard Worker "    --quiet (-q):",
3713*a67afe4dSAndroid Build Coastguard Worker "      Do not output the summaries except for files that cannot be read. With",
3714*a67afe4dSAndroid Build Coastguard Worker "      two --quiets these are not output either.",
3715*a67afe4dSAndroid Build Coastguard Worker "    --errors (-e):",
3716*a67afe4dSAndroid Build Coastguard Worker "      Output errors from libpng and the program (except too-far-back).",
3717*a67afe4dSAndroid Build Coastguard Worker "    --warnings (-w):",
3718*a67afe4dSAndroid Build Coastguard Worker "      Output warnings from libpng.",
3719*a67afe4dSAndroid Build Coastguard Worker "  OUTPUT",
3720*a67afe4dSAndroid Build Coastguard Worker "      By default nothing is written.",
3721*a67afe4dSAndroid Build Coastguard Worker "    --out=<file>:",
3722*a67afe4dSAndroid Build Coastguard Worker "      Write the optimized/corrected version of the next PNG to <file>.  This",
3723*a67afe4dSAndroid Build Coastguard Worker "      overrides the following two options",
3724*a67afe4dSAndroid Build Coastguard Worker "    --suffix=<suffix>:",
3725*a67afe4dSAndroid Build Coastguard Worker "      Set --out=<name><suffix> for all following files unless overridden on",
3726*a67afe4dSAndroid Build Coastguard Worker "      a per-file basis by explicit --out.",
3727*a67afe4dSAndroid Build Coastguard Worker "    --prefix=<prefix>:",
3728*a67afe4dSAndroid Build Coastguard Worker "      Set --out=<prefix><name> for all the following files unless overridden",
3729*a67afe4dSAndroid Build Coastguard Worker "      on a per-file basis by explicit --out.",
3730*a67afe4dSAndroid Build Coastguard Worker "      These two options can be used together to produce a suffix and prefix.",
3731*a67afe4dSAndroid Build Coastguard Worker "  INTERNAL OPTIONS",
3732*a67afe4dSAndroid Build Coastguard Worker #if 0 /*NYI*/
3733*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_MAXIMUM_INFLATE_WINDOW
3734*a67afe4dSAndroid Build Coastguard Worker "    --test:",
3735*a67afe4dSAndroid Build Coastguard Worker "      Test the PNG_MAXIMUM_INFLATE_WINDOW option.  Setting this disables",
3736*a67afe4dSAndroid Build Coastguard Worker "      output as this would produce a broken file.",
3737*a67afe4dSAndroid Build Coastguard Worker #endif
3738*a67afe4dSAndroid Build Coastguard Worker #endif
3739*a67afe4dSAndroid Build Coastguard Worker 0,
3740*a67afe4dSAndroid Build Coastguard Worker "EXIT CODES",
3741*a67afe4dSAndroid Build Coastguard Worker "  *** SUBJECT TO CHANGE ***",
3742*a67afe4dSAndroid Build Coastguard Worker "  The program exit code is value in the range 0..127 holding a bit mask of",
3743*a67afe4dSAndroid Build Coastguard Worker "  the following codes.  Notice that the results for each file are combined",
3744*a67afe4dSAndroid Build Coastguard Worker "  together - check one file at a time to get a meaningful error code!",
3745*a67afe4dSAndroid Build Coastguard Worker "    0x01: The zlib too-far-back error existed in at least one chunk.",
3746*a67afe4dSAndroid Build Coastguard Worker "    0x02: At least one chunk had a CRC error.",
3747*a67afe4dSAndroid Build Coastguard Worker "    0x04: A chunk length was incorrect.",
3748*a67afe4dSAndroid Build Coastguard Worker "    0x08: The file was truncated.",
3749*a67afe4dSAndroid Build Coastguard Worker "  Errors less than 16 are potentially recoverable, for a single file if the",
3750*a67afe4dSAndroid Build Coastguard Worker "  exit code is less than 16 the file could be read (with corrections if a",
3751*a67afe4dSAndroid Build Coastguard Worker "  non-zero code is returned).",
3752*a67afe4dSAndroid Build Coastguard Worker "    0x10: The file could not be read, even with corrections.",
3753*a67afe4dSAndroid Build Coastguard Worker "    0x20: The output file could not be written.",
3754*a67afe4dSAndroid Build Coastguard Worker "    0x40: An unexpected, potentially internal, error occurred.",
3755*a67afe4dSAndroid Build Coastguard Worker "  If the command line arguments are incorrect the program exits with exit",
3756*a67afe4dSAndroid Build Coastguard Worker "  255.  Some older operating systems only support 7-bit exit codes, on those",
3757*a67afe4dSAndroid Build Coastguard Worker "  systems it is suggested that this program is first tested by supplying",
3758*a67afe4dSAndroid Build Coastguard Worker "  invalid arguments.",
3759*a67afe4dSAndroid Build Coastguard Worker 0,
3760*a67afe4dSAndroid Build Coastguard Worker "DESCRIPTION",
3761*a67afe4dSAndroid Build Coastguard Worker "  " PROGRAM_NAME ":",
3762*a67afe4dSAndroid Build Coastguard Worker "  checks each PNG file on the command line for errors.  By default errors are",
3763*a67afe4dSAndroid Build Coastguard Worker "  not output and the program just returns an exit code and prints a summary.",
3764*a67afe4dSAndroid Build Coastguard Worker "  With the --quiet (-q) option the summaries are suppressed too and the",
3765*a67afe4dSAndroid Build Coastguard Worker "  program only outputs unexpected errors (internal errors and file open",
3766*a67afe4dSAndroid Build Coastguard Worker "  errors).",
3767*a67afe4dSAndroid Build Coastguard Worker "  Various known problems in PNG files are fixed while the file is being read",
3768*a67afe4dSAndroid Build Coastguard Worker "  The exit code says what problems were fixed.  In particular the zlib error:",
3769*a67afe4dSAndroid Build Coastguard Worker 0,
3770*a67afe4dSAndroid Build Coastguard Worker "        \"invalid distance too far back\"",
3771*a67afe4dSAndroid Build Coastguard Worker 0,
3772*a67afe4dSAndroid Build Coastguard Worker "  caused by an incorrect optimization of a zlib stream is fixed in any",
3773*a67afe4dSAndroid Build Coastguard Worker "  compressed chunk in which it is encountered.  An integrity problem of the",
3774*a67afe4dSAndroid Build Coastguard Worker "  PNG stream caused by a bug in libpng which wrote an incorrect chunk length",
3775*a67afe4dSAndroid Build Coastguard Worker "  is also fixed.  Chunk CRC errors are automatically fixed up.",
3776*a67afe4dSAndroid Build Coastguard Worker 0,
3777*a67afe4dSAndroid Build Coastguard Worker "  Setting one of the \"OUTPUT\" options causes the possibly modified file to",
3778*a67afe4dSAndroid Build Coastguard Worker "  be written to a new file.",
3779*a67afe4dSAndroid Build Coastguard Worker 0,
3780*a67afe4dSAndroid Build Coastguard Worker "  Notice that some PNG files with the zlib optimization problem can still be",
3781*a67afe4dSAndroid Build Coastguard Worker "  read by libpng under some circumstances.  This program will still detect",
3782*a67afe4dSAndroid Build Coastguard Worker "  and, if requested, correct the error.",
3783*a67afe4dSAndroid Build Coastguard Worker 0,
3784*a67afe4dSAndroid Build Coastguard Worker "  The program will reliably process all files on the command line unless",
3785*a67afe4dSAndroid Build Coastguard Worker "  either an invalid argument causes the usage message (this message) to be",
3786*a67afe4dSAndroid Build Coastguard Worker "  produced or the program crashes.",
3787*a67afe4dSAndroid Build Coastguard Worker 0,
3788*a67afe4dSAndroid Build Coastguard Worker "  The summary lines describe issues encountered with the zlib compressed",
3789*a67afe4dSAndroid Build Coastguard Worker "  stream of a chunk.  They have the following format, which is SUBJECT TO",
3790*a67afe4dSAndroid Build Coastguard Worker "  CHANGE in the future:",
3791*a67afe4dSAndroid Build Coastguard Worker 0,
3792*a67afe4dSAndroid Build Coastguard Worker "     chunk reason comp-level p1 p2 p3 p4 file",
3793*a67afe4dSAndroid Build Coastguard Worker 0,
3794*a67afe4dSAndroid Build Coastguard Worker "  p1 through p4 vary according to the 'reason'.  There are always 8 space",
3795*a67afe4dSAndroid Build Coastguard Worker "  separated fields.  Reasons specific formats are:",
3796*a67afe4dSAndroid Build Coastguard Worker 0,
3797*a67afe4dSAndroid Build Coastguard Worker "     chunk ERR status code read-errno write-errno message file",
3798*a67afe4dSAndroid Build Coastguard Worker "     chunk SKP comp-level file-bits zlib-rc compressed message file",
3799*a67afe4dSAndroid Build Coastguard Worker "     chunk ??? comp-level file-bits ok-bits compressed uncompress file",
3800*a67afe4dSAndroid Build Coastguard Worker 0,
3801*a67afe4dSAndroid Build Coastguard Worker "  The various fields are",
3802*a67afe4dSAndroid Build Coastguard Worker 0,
3803*a67afe4dSAndroid Build Coastguard Worker "$1 chunk:      The chunk type of a chunk in the file or 'HEAD' if a problem",
3804*a67afe4dSAndroid Build Coastguard Worker "               is reported by libpng at the start of the IDAT stream.",
3805*a67afe4dSAndroid Build Coastguard Worker "$2 reason:     One of:",
3806*a67afe4dSAndroid Build Coastguard Worker "          CHK: A zlib header checksum was detected and fixed.",
3807*a67afe4dSAndroid Build Coastguard Worker "          TFB: The zlib too far back error was detected and fixed.",
3808*a67afe4dSAndroid Build Coastguard Worker "          OK : No errors were detected in the zlib stream and optimization",
3809*a67afe4dSAndroid Build Coastguard Worker "               was not requested, or was not possible.",
3810*a67afe4dSAndroid Build Coastguard Worker "          OPT: The zlib stream window bits value could be improved (and was).",
3811*a67afe4dSAndroid Build Coastguard Worker "          SKP: The chunk was skipped because of a zlib issue (zlib-rc) with",
3812*a67afe4dSAndroid Build Coastguard Worker "               explanation 'message'",
3813*a67afe4dSAndroid Build Coastguard Worker "          ERR: The read of the file was aborted.  The parameters explain why.",
3814*a67afe4dSAndroid Build Coastguard Worker "$3 status:     For 'ERR' the accumulated status code from 'EXIT CODES' above.",
3815*a67afe4dSAndroid Build Coastguard Worker "               This is printed as a 2 digit hexadecimal value",
3816*a67afe4dSAndroid Build Coastguard Worker "   comp-level: The recorded compression level (FLEVEL) of a zlib stream",
3817*a67afe4dSAndroid Build Coastguard Worker "               expressed as a string {supfast,stdfast,default,maximum}",
3818*a67afe4dSAndroid Build Coastguard Worker "$4 code:       The file exit code; where stop was called, as a fairly terse",
3819*a67afe4dSAndroid Build Coastguard Worker "               string {warning,libpng,zlib,invalid,read,write,unexpected}.",
3820*a67afe4dSAndroid Build Coastguard Worker "   file-bits:  The zlib window bits recorded in the file.",
3821*a67afe4dSAndroid Build Coastguard Worker "$5 read-errno: A system errno value from a read translated by strerror(3).",
3822*a67afe4dSAndroid Build Coastguard Worker "   zlib-rc:    A zlib return code as a string (see zlib.h).",
3823*a67afe4dSAndroid Build Coastguard Worker "   ok-bits:    The smallest zlib window bits value that works.",
3824*a67afe4dSAndroid Build Coastguard Worker "$6 write-errno:A system errno value from a write translated by strerror(3).",
3825*a67afe4dSAndroid Build Coastguard Worker "   compressed: The count of compressed bytes in the zlib stream, when the",
3826*a67afe4dSAndroid Build Coastguard Worker "               reason is 'SKP'; this is a count of the bytes read from the",
3827*a67afe4dSAndroid Build Coastguard Worker "               stream when the fatal error was encountered.",
3828*a67afe4dSAndroid Build Coastguard Worker "$7 message:    An error message (spaces replaced by _, as in all parameters),",
3829*a67afe4dSAndroid Build Coastguard Worker "   uncompress: The count of bytes from uncompressing the zlib stream; this",
3830*a67afe4dSAndroid Build Coastguard Worker "               may not be the same as the number of bytes in the image.",
3831*a67afe4dSAndroid Build Coastguard Worker "$8 file:       The name of the file (this may contain spaces).",
3832*a67afe4dSAndroid Build Coastguard Worker };
3833*a67afe4dSAndroid Build Coastguard Worker 
3834*a67afe4dSAndroid Build Coastguard Worker    fprintf(stderr, "Usage: %s {[options] png-file}\n", prog);
3835*a67afe4dSAndroid Build Coastguard Worker 
3836*a67afe4dSAndroid Build Coastguard Worker    for (i=0; i < (sizeof usage_string)/(sizeof usage_string[0]); ++i)
3837*a67afe4dSAndroid Build Coastguard Worker    {
3838*a67afe4dSAndroid Build Coastguard Worker       if (usage_string[i] != 0)
3839*a67afe4dSAndroid Build Coastguard Worker          fputs(usage_string[i], stderr);
3840*a67afe4dSAndroid Build Coastguard Worker 
3841*a67afe4dSAndroid Build Coastguard Worker       fputc('\n', stderr);
3842*a67afe4dSAndroid Build Coastguard Worker    }
3843*a67afe4dSAndroid Build Coastguard Worker 
3844*a67afe4dSAndroid Build Coastguard Worker    exit(255);
3845*a67afe4dSAndroid Build Coastguard Worker }
3846*a67afe4dSAndroid Build Coastguard Worker 
3847*a67afe4dSAndroid Build Coastguard Worker int
main(int argc,const char ** argv)3848*a67afe4dSAndroid Build Coastguard Worker main(int argc, const char **argv)
3849*a67afe4dSAndroid Build Coastguard Worker {
3850*a67afe4dSAndroid Build Coastguard Worker    char temp_name[FILENAME_MAX+1];
3851*a67afe4dSAndroid Build Coastguard Worker    const char *  prog = *argv;
3852*a67afe4dSAndroid Build Coastguard Worker    const char *  outfile = NULL;
3853*a67afe4dSAndroid Build Coastguard Worker    const char *  suffix = NULL;
3854*a67afe4dSAndroid Build Coastguard Worker    const char *  prefix = NULL;
3855*a67afe4dSAndroid Build Coastguard Worker    int           done = 0; /* if at least one file is processed */
3856*a67afe4dSAndroid Build Coastguard Worker    struct global global;
3857*a67afe4dSAndroid Build Coastguard Worker 
3858*a67afe4dSAndroid Build Coastguard Worker    global_init(&global);
3859*a67afe4dSAndroid Build Coastguard Worker 
3860*a67afe4dSAndroid Build Coastguard Worker    while (--argc > 0)
3861*a67afe4dSAndroid Build Coastguard Worker    {
3862*a67afe4dSAndroid Build Coastguard Worker       ++argv;
3863*a67afe4dSAndroid Build Coastguard Worker 
3864*a67afe4dSAndroid Build Coastguard Worker       if (strcmp(*argv, "--debug") == 0)
3865*a67afe4dSAndroid Build Coastguard Worker       {
3866*a67afe4dSAndroid Build Coastguard Worker          /* To help debugging problems: */
3867*a67afe4dSAndroid Build Coastguard Worker          global.errors = global.warnings = 1;
3868*a67afe4dSAndroid Build Coastguard Worker          global.quiet = 0;
3869*a67afe4dSAndroid Build Coastguard Worker          global.verbose = 7;
3870*a67afe4dSAndroid Build Coastguard Worker       }
3871*a67afe4dSAndroid Build Coastguard Worker 
3872*a67afe4dSAndroid Build Coastguard Worker       else if (strncmp(*argv, "--max=", 6) == 0)
3873*a67afe4dSAndroid Build Coastguard Worker       {
3874*a67afe4dSAndroid Build Coastguard Worker          global.idat_max = (png_uint_32)atol(6+*argv);
3875*a67afe4dSAndroid Build Coastguard Worker 
3876*a67afe4dSAndroid Build Coastguard Worker          if (global.skip < SKIP_UNSAFE)
3877*a67afe4dSAndroid Build Coastguard Worker             global.skip = SKIP_UNSAFE;
3878*a67afe4dSAndroid Build Coastguard Worker       }
3879*a67afe4dSAndroid Build Coastguard Worker 
3880*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--max") == 0)
3881*a67afe4dSAndroid Build Coastguard Worker       {
3882*a67afe4dSAndroid Build Coastguard Worker          global.idat_max = 0x7fffffff;
3883*a67afe4dSAndroid Build Coastguard Worker 
3884*a67afe4dSAndroid Build Coastguard Worker          if (global.skip < SKIP_UNSAFE)
3885*a67afe4dSAndroid Build Coastguard Worker             global.skip = SKIP_UNSAFE;
3886*a67afe4dSAndroid Build Coastguard Worker       }
3887*a67afe4dSAndroid Build Coastguard Worker 
3888*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--optimize") == 0 || strcmp(*argv, "-o") == 0)
3889*a67afe4dSAndroid Build Coastguard Worker          global.optimize_zlib = 1;
3890*a67afe4dSAndroid Build Coastguard Worker 
3891*a67afe4dSAndroid Build Coastguard Worker       else if (strncmp(*argv, "--out=", 6) == 0)
3892*a67afe4dSAndroid Build Coastguard Worker          outfile = 6+*argv;
3893*a67afe4dSAndroid Build Coastguard Worker 
3894*a67afe4dSAndroid Build Coastguard Worker       else if (strncmp(*argv, "--suffix=", 9) == 0)
3895*a67afe4dSAndroid Build Coastguard Worker          suffix = 9+*argv;
3896*a67afe4dSAndroid Build Coastguard Worker 
3897*a67afe4dSAndroid Build Coastguard Worker       else if (strncmp(*argv, "--prefix=", 9) == 0)
3898*a67afe4dSAndroid Build Coastguard Worker          prefix = 9+*argv;
3899*a67afe4dSAndroid Build Coastguard Worker 
3900*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=none") == 0)
3901*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_NONE;
3902*a67afe4dSAndroid Build Coastguard Worker 
3903*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=crc") == 0)
3904*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_BAD_CRC;
3905*a67afe4dSAndroid Build Coastguard Worker 
3906*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=unsafe") == 0)
3907*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_UNSAFE;
3908*a67afe4dSAndroid Build Coastguard Worker 
3909*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=unused") == 0)
3910*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_UNUSED;
3911*a67afe4dSAndroid Build Coastguard Worker 
3912*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=transform") == 0)
3913*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_TRANSFORM;
3914*a67afe4dSAndroid Build Coastguard Worker 
3915*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=color") == 0)
3916*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_COLOR;
3917*a67afe4dSAndroid Build Coastguard Worker 
3918*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--strip=all") == 0)
3919*a67afe4dSAndroid Build Coastguard Worker          global.skip = SKIP_ALL;
3920*a67afe4dSAndroid Build Coastguard Worker 
3921*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--errors") == 0 || strcmp(*argv, "-e") == 0)
3922*a67afe4dSAndroid Build Coastguard Worker          global.errors = 1;
3923*a67afe4dSAndroid Build Coastguard Worker 
3924*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--warnings") == 0 || strcmp(*argv, "-w") == 0)
3925*a67afe4dSAndroid Build Coastguard Worker          global.warnings = 1;
3926*a67afe4dSAndroid Build Coastguard Worker 
3927*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--quiet") == 0 || strcmp(*argv, "-q") == 0)
3928*a67afe4dSAndroid Build Coastguard Worker       {
3929*a67afe4dSAndroid Build Coastguard Worker          if (global.quiet)
3930*a67afe4dSAndroid Build Coastguard Worker             global.quiet = 2;
3931*a67afe4dSAndroid Build Coastguard Worker 
3932*a67afe4dSAndroid Build Coastguard Worker          else
3933*a67afe4dSAndroid Build Coastguard Worker             global.quiet = 1;
3934*a67afe4dSAndroid Build Coastguard Worker       }
3935*a67afe4dSAndroid Build Coastguard Worker 
3936*a67afe4dSAndroid Build Coastguard Worker       else if (strcmp(*argv, "--verbose") == 0 || strcmp(*argv, "-v") == 0)
3937*a67afe4dSAndroid Build Coastguard Worker          ++global.verbose;
3938*a67afe4dSAndroid Build Coastguard Worker 
3939*a67afe4dSAndroid Build Coastguard Worker #if 0
3940*a67afe4dSAndroid Build Coastguard Worker       /* NYI */
3941*a67afe4dSAndroid Build Coastguard Worker #     ifdef PNG_MAXIMUM_INFLATE_WINDOW
3942*a67afe4dSAndroid Build Coastguard Worker          else if (strcmp(*argv, "--test") == 0)
3943*a67afe4dSAndroid Build Coastguard Worker             ++set_option;
3944*a67afe4dSAndroid Build Coastguard Worker #     endif
3945*a67afe4dSAndroid Build Coastguard Worker #endif
3946*a67afe4dSAndroid Build Coastguard Worker 
3947*a67afe4dSAndroid Build Coastguard Worker       else if ((*argv)[0] == '-')
3948*a67afe4dSAndroid Build Coastguard Worker          usage(prog);
3949*a67afe4dSAndroid Build Coastguard Worker 
3950*a67afe4dSAndroid Build Coastguard Worker       else
3951*a67afe4dSAndroid Build Coastguard Worker       {
3952*a67afe4dSAndroid Build Coastguard Worker          size_t outlen = strlen(*argv);
3953*a67afe4dSAndroid Build Coastguard Worker 
3954*a67afe4dSAndroid Build Coastguard Worker          if (outlen > FILENAME_MAX)
3955*a67afe4dSAndroid Build Coastguard Worker          {
3956*a67afe4dSAndroid Build Coastguard Worker             fprintf(stderr, "%s: output file name too long: %s%s%s\n",
3957*a67afe4dSAndroid Build Coastguard Worker                prog, prefix, *argv, suffix ? suffix : "");
3958*a67afe4dSAndroid Build Coastguard Worker             global.status_code |= WRITE_ERROR;
3959*a67afe4dSAndroid Build Coastguard Worker             continue;
3960*a67afe4dSAndroid Build Coastguard Worker          }
3961*a67afe4dSAndroid Build Coastguard Worker 
3962*a67afe4dSAndroid Build Coastguard Worker          if (outfile == NULL) /* else this takes precedence */
3963*a67afe4dSAndroid Build Coastguard Worker          {
3964*a67afe4dSAndroid Build Coastguard Worker             /* Consider the prefix/suffix options */
3965*a67afe4dSAndroid Build Coastguard Worker             if (prefix != NULL)
3966*a67afe4dSAndroid Build Coastguard Worker             {
3967*a67afe4dSAndroid Build Coastguard Worker                size_t prefixlen = strlen(prefix);
3968*a67afe4dSAndroid Build Coastguard Worker 
3969*a67afe4dSAndroid Build Coastguard Worker                if (prefixlen+outlen > FILENAME_MAX)
3970*a67afe4dSAndroid Build Coastguard Worker                {
3971*a67afe4dSAndroid Build Coastguard Worker                   fprintf(stderr, "%s: output file name too long: %s%s%s\n",
3972*a67afe4dSAndroid Build Coastguard Worker                      prog, prefix, *argv, suffix ? suffix : "");
3973*a67afe4dSAndroid Build Coastguard Worker                   global.status_code |= WRITE_ERROR;
3974*a67afe4dSAndroid Build Coastguard Worker                   continue;
3975*a67afe4dSAndroid Build Coastguard Worker                }
3976*a67afe4dSAndroid Build Coastguard Worker 
3977*a67afe4dSAndroid Build Coastguard Worker                memcpy(temp_name, prefix, prefixlen);
3978*a67afe4dSAndroid Build Coastguard Worker                memcpy(temp_name+prefixlen, *argv, outlen);
3979*a67afe4dSAndroid Build Coastguard Worker                outlen += prefixlen;
3980*a67afe4dSAndroid Build Coastguard Worker                outfile = temp_name;
3981*a67afe4dSAndroid Build Coastguard Worker             }
3982*a67afe4dSAndroid Build Coastguard Worker 
3983*a67afe4dSAndroid Build Coastguard Worker             else if (suffix != NULL)
3984*a67afe4dSAndroid Build Coastguard Worker                memcpy(temp_name, *argv, outlen);
3985*a67afe4dSAndroid Build Coastguard Worker 
3986*a67afe4dSAndroid Build Coastguard Worker             temp_name[outlen] = 0;
3987*a67afe4dSAndroid Build Coastguard Worker 
3988*a67afe4dSAndroid Build Coastguard Worker             if (suffix != NULL)
3989*a67afe4dSAndroid Build Coastguard Worker             {
3990*a67afe4dSAndroid Build Coastguard Worker                size_t suffixlen = strlen(suffix);
3991*a67afe4dSAndroid Build Coastguard Worker 
3992*a67afe4dSAndroid Build Coastguard Worker                if (outlen+suffixlen > FILENAME_MAX)
3993*a67afe4dSAndroid Build Coastguard Worker                {
3994*a67afe4dSAndroid Build Coastguard Worker                   fprintf(stderr, "%s: output file name too long: %s%s\n",
3995*a67afe4dSAndroid Build Coastguard Worker                      prog, *argv, suffix);
3996*a67afe4dSAndroid Build Coastguard Worker                   global.status_code |= WRITE_ERROR;
3997*a67afe4dSAndroid Build Coastguard Worker                   continue;
3998*a67afe4dSAndroid Build Coastguard Worker                }
3999*a67afe4dSAndroid Build Coastguard Worker 
4000*a67afe4dSAndroid Build Coastguard Worker                memcpy(temp_name+outlen, suffix, suffixlen);
4001*a67afe4dSAndroid Build Coastguard Worker                outlen += suffixlen;
4002*a67afe4dSAndroid Build Coastguard Worker                temp_name[outlen] = 0;
4003*a67afe4dSAndroid Build Coastguard Worker                outfile = temp_name;
4004*a67afe4dSAndroid Build Coastguard Worker             }
4005*a67afe4dSAndroid Build Coastguard Worker          }
4006*a67afe4dSAndroid Build Coastguard Worker 
4007*a67afe4dSAndroid Build Coastguard Worker          (void)one_file(&global, *argv, outfile);
4008*a67afe4dSAndroid Build Coastguard Worker          ++done;
4009*a67afe4dSAndroid Build Coastguard Worker          outfile = NULL;
4010*a67afe4dSAndroid Build Coastguard Worker       }
4011*a67afe4dSAndroid Build Coastguard Worker    }
4012*a67afe4dSAndroid Build Coastguard Worker 
4013*a67afe4dSAndroid Build Coastguard Worker    if (!done)
4014*a67afe4dSAndroid Build Coastguard Worker       usage(prog);
4015*a67afe4dSAndroid Build Coastguard Worker 
4016*a67afe4dSAndroid Build Coastguard Worker    return global_end(&global);
4017*a67afe4dSAndroid Build Coastguard Worker }
4018*a67afe4dSAndroid Build Coastguard Worker 
4019*a67afe4dSAndroid Build Coastguard Worker #else /* ZLIB_VERNUM < 0x1240 */
4020*a67afe4dSAndroid Build Coastguard Worker int
main(void)4021*a67afe4dSAndroid Build Coastguard Worker main(void)
4022*a67afe4dSAndroid Build Coastguard Worker {
4023*a67afe4dSAndroid Build Coastguard Worker    fprintf(stderr,
4024*a67afe4dSAndroid Build Coastguard Worker       "pngfix needs libpng with a zlib >=1.2.4 (not 0x%x)\n",
4025*a67afe4dSAndroid Build Coastguard Worker       ZLIB_VERNUM);
4026*a67afe4dSAndroid Build Coastguard Worker    return 77;
4027*a67afe4dSAndroid Build Coastguard Worker }
4028*a67afe4dSAndroid Build Coastguard Worker #endif /* ZLIB_VERNUM */
4029*a67afe4dSAndroid Build Coastguard Worker 
4030*a67afe4dSAndroid Build Coastguard Worker #else /* No read support */
4031*a67afe4dSAndroid Build Coastguard Worker 
4032*a67afe4dSAndroid Build Coastguard Worker int
main(void)4033*a67afe4dSAndroid Build Coastguard Worker main(void)
4034*a67afe4dSAndroid Build Coastguard Worker {
4035*a67afe4dSAndroid Build Coastguard Worker    fprintf(stderr, "pngfix does not work without read deinterlace support\n");
4036*a67afe4dSAndroid Build Coastguard Worker    return 77;
4037*a67afe4dSAndroid Build Coastguard Worker }
4038*a67afe4dSAndroid Build Coastguard Worker #endif /* PNG_READ_SUPPORTED && PNG_EASY_ACCESS_SUPPORTED */
4039*a67afe4dSAndroid Build Coastguard Worker #else /* No setjmp support */
4040*a67afe4dSAndroid Build Coastguard Worker int
main(void)4041*a67afe4dSAndroid Build Coastguard Worker main(void)
4042*a67afe4dSAndroid Build Coastguard Worker {
4043*a67afe4dSAndroid Build Coastguard Worker    fprintf(stderr, "pngfix does not work without setjmp support\n");
4044*a67afe4dSAndroid Build Coastguard Worker    return 77;
4045*a67afe4dSAndroid Build Coastguard Worker }
4046*a67afe4dSAndroid Build Coastguard Worker #endif /* PNG_SETJMP_SUPPORTED */
4047*a67afe4dSAndroid Build Coastguard Worker /* vi: set textwidth=80 shiftwidth=3 softtabstop=-1 expandtab: */
4048