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