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