fukasawa e60969
/* pngfix.c
fukasawa e60969
 *
fukasawa e60969
 * Copyright (c) 2014-2016 John Cunningham Bowler
fukasawa e60969
 *
fukasawa e60969
 * Last changed in libpng 1.6.21 [January 15, 2016]
fukasawa e60969
 *
fukasawa e60969
 * This code is released under the libpng license.
fukasawa e60969
 * For conditions of distribution and use, see the disclaimer
fukasawa e60969
 * and license in png.h
fukasawa e60969
 *
fukasawa e60969
 * Tool to check and fix the zlib inflate 'too far back' problem.
fukasawa e60969
 * See the usage message for more information.
fukasawa e60969
 */
fukasawa e60969
#include <stdlib.h></stdlib.h>
fukasawa e60969
#include <stdio.h></stdio.h>
fukasawa e60969
#include <string.h></string.h>
fukasawa e60969
#include <ctype.h></ctype.h>
fukasawa e60969
#include <limits.h></limits.h>
fukasawa e60969
#include <errno.h></errno.h>
fukasawa e60969
#include <assert.h></assert.h>
fukasawa e60969
fukasawa e60969
#define implies(x,y) assert(!(x) || (y))
fukasawa e60969
fukasawa e60969
#ifdef __GNUC__
fukasawa e60969
   /* This is used to fix the error:
fukasawa e60969
    *
fukasawa e60969
    * pngfix.c:
fukasawa e60969
    * In function 'zlib_advance':
fukasawa e60969
    * pngfix.c:181:13: error: assuming signed overflow does not
fukasawa e60969
    *   occur when simplifying conditional to constant [-Werror=strict-overflow]
fukasawa e60969
    */
fukasawa e60969
#  define FIX_GCC volatile
fukasawa e60969
#else
fukasawa e60969
#  define FIX_GCC
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#define PROGRAM_NAME "pngfix"
fukasawa e60969
fukasawa e60969
/* Define the following to use this program against your installed libpng,
fukasawa e60969
 * rather than the one being built here:
fukasawa e60969
 */
fukasawa e60969
#ifdef PNG_FREESTANDING_TESTS
fukasawa e60969
#  include <png.h></png.h>
fukasawa e60969
#else
fukasawa e60969
#  include "../../png.h"
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#if PNG_LIBPNG_VER < 10603 /* 1.6.3 */
fukasawa e60969
#  error "pngfix will not work with libpng prior to 1.6.3"
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_SETJMP_SUPPORTED
fukasawa e60969
#include <setjmp.h></setjmp.h>
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_SUPPORTED) && defined(PNG_EASY_ACCESS_SUPPORTED) &&\
fukasawa e60969
   (defined(PNG_READ_DEINTERLACE_SUPPORTED) ||\
fukasawa e60969
    defined(PNG_READ_INTERLACING_SUPPORTED))
fukasawa e60969
fukasawa e60969
/* zlib.h defines the structure z_stream, an instance of which is included
fukasawa e60969
 * in this structure and is required for decompressing the LZ compressed
fukasawa e60969
 * data in PNG files.
fukasawa e60969
 */
fukasawa e60969
#ifndef ZLIB_CONST
fukasawa e60969
   /* We must ensure that zlib uses 'const' in declarations. */
fukasawa e60969
#  define ZLIB_CONST
fukasawa e60969
#endif
fukasawa e60969
#include <zlib.h></zlib.h>
fukasawa e60969
#ifdef const
fukasawa e60969
   /* zlib.h sometimes #defines const to nothing, undo this. */
fukasawa e60969
#  undef const
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
fukasawa e60969
 * with older builds.
fukasawa e60969
 */
fukasawa e60969
#if ZLIB_VERNUM < 0x1260
fukasawa e60969
#  define PNGZ_MSG_CAST(s) constcast(char*,s)
fukasawa e60969
#  define PNGZ_INPUT_CAST(b) constcast(png_bytep,b)
fukasawa e60969
#else
fukasawa e60969
#  define PNGZ_MSG_CAST(s) (s)
fukasawa e60969
#  define PNGZ_INPUT_CAST(b) (b)
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifndef PNG_MAXIMUM_INFLATE_WINDOW
fukasawa e60969
#  error "pngfix not supported in this libpng version"
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#if ZLIB_VERNUM >= 0x1240
fukasawa e60969
fukasawa e60969
/* Copied from pngpriv.h */
fukasawa e60969
#ifdef __cplusplus
fukasawa e60969
#  define voidcast(type, value) static_cast<type>(value)</type>
fukasawa e60969
#  define constcast(type, value) const_cast<type>(value)</type>
fukasawa e60969
#  define aligncast(type, value) \
fukasawa e60969
   static_cast<type>(static_cast<void*>(value))</void*></type>
fukasawa e60969
#  define aligncastconst(type, value) \
fukasawa e60969
   static_cast<type>(static_cast<const void*="">(value))</const></type>
fukasawa e60969
#else
fukasawa e60969
#  define voidcast(type, value) (value)
fukasawa e60969
#  define constcast(type, value) ((type)(value))
fukasawa e60969
#  define aligncast(type, value) ((void*)(value))
fukasawa e60969
#  define aligncastconst(type, value) ((const void*)(value))
fukasawa e60969
#endif /* __cplusplus */
fukasawa e60969
fukasawa e60969
#if PNG_LIBPNG_VER < 10700
fukasawa e60969
/* Chunk tags (copied from pngpriv.h) */
fukasawa e60969
#define PNG_32b(b,s) ((png_uint_32)(b) << (s))
fukasawa e60969
#define PNG_U32(b1,b2,b3,b4) \
fukasawa e60969
   (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
fukasawa e60969
fukasawa e60969
/* Constants for known chunk types. */
fukasawa e60969
#define png_IDAT PNG_U32( 73,  68,  65,  84)
fukasawa e60969
#define png_IEND PNG_U32( 73,  69,  78,  68)
fukasawa e60969
#define png_IHDR PNG_U32( 73,  72,  68,  82)
fukasawa e60969
#define png_PLTE PNG_U32( 80,  76,  84,  69)
fukasawa e60969
#define png_bKGD PNG_U32( 98,  75,  71,  68)
fukasawa e60969
#define png_cHRM PNG_U32( 99,  72,  82,  77)
fukasawa e60969
#define png_fRAc PNG_U32(102,  82,  65,  99) /* registered, not defined */
fukasawa e60969
#define png_gAMA PNG_U32(103,  65,  77,  65)
fukasawa e60969
#define png_gIFg PNG_U32(103,  73,  70, 103)
fukasawa e60969
#define png_gIFt PNG_U32(103,  73,  70, 116) /* deprecated */
fukasawa e60969
#define png_gIFx PNG_U32(103,  73,  70, 120)
fukasawa e60969
#define png_hIST PNG_U32(104,  73,  83,  84)
fukasawa e60969
#define png_iCCP PNG_U32(105,  67,  67,  80)
fukasawa e60969
#define png_iTXt PNG_U32(105,  84,  88, 116)
fukasawa e60969
#define png_oFFs PNG_U32(111,  70,  70, 115)
fukasawa e60969
#define png_pCAL PNG_U32(112,  67,  65,  76)
fukasawa e60969
#define png_pHYs PNG_U32(112,  72,  89, 115)
fukasawa e60969
#define png_sBIT PNG_U32(115,  66,  73,  84)
fukasawa e60969
#define png_sCAL PNG_U32(115,  67,  65,  76)
fukasawa e60969
#define png_sPLT PNG_U32(115,  80,  76,  84)
fukasawa e60969
#define png_sRGB PNG_U32(115,  82,  71,  66)
fukasawa e60969
#define png_sTER PNG_U32(115,  84,  69,  82)
fukasawa e60969
#define png_tEXt PNG_U32(116,  69,  88, 116)
fukasawa e60969
#define png_tIME PNG_U32(116,  73,  77,  69)
fukasawa e60969
#define png_tRNS PNG_U32(116,  82,  78,  83)
fukasawa e60969
#define png_zTXt PNG_U32(122,  84,  88, 116)
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
/* The 8-byte signature as a pair of 32-bit quantities */
fukasawa e60969
#define sig1 PNG_U32(137,  80,  78,  71)
fukasawa e60969
#define sig2 PNG_U32( 13,  10,  26,  10)
fukasawa e60969
fukasawa e60969
/* Is the chunk critical? */
fukasawa e60969
#define CRITICAL(chunk) (((chunk) & PNG_U32(32,0,0,0)) == 0)
fukasawa e60969
fukasawa e60969
/* Is it safe to copy? */
fukasawa e60969
#define SAFE_TO_COPY(chunk) (((chunk) & PNG_U32(0,0,0,32)) != 0)
fukasawa e60969
fukasawa e60969
/* Fix ups for builds with limited read support */
fukasawa e60969
#ifndef PNG_ERROR_TEXT_SUPPORTED
fukasawa e60969
#  define png_error(a,b) png_err(a)
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
/********************************* UTILITIES **********************************/
fukasawa e60969
/* UNREACHED is a value to cause an assert to fail. Because of the way the
fukasawa e60969
 * assert macro is written the string "UNREACHED" is produced in the error
fukasawa e60969
 * message.
fukasawa e60969
 */
fukasawa e60969
#define UNREACHED 0
fukasawa e60969
fukasawa e60969
/* 80-bit number handling - a PNG image can be up to (2^31-1)x(2^31-1) 8-byte
fukasawa e60969
 * (16-bit RGBA) pixels in size; that's less than 2^65 bytes or 2^68 bits, so
fukasawa e60969
 * arithmetic of 80-bit numbers is sufficient.  This representation uses an
fukasawa e60969
 * arbitrary length array of png_uint_16 digits (0..65535).  The representation
fukasawa e60969
 * is little endian.
fukasawa e60969
 *
fukasawa e60969
 * The arithmetic functions take zero to two uarb values together with the
fukasawa e60969
 * number of digits in those values and write the result to the given uarb
fukasawa e60969
 * (always the first argument) returning the number of digits in the result.
fukasawa e60969
 * If the result is negative the return value is also negative (this would
fukasawa e60969
 * normally be an error).
fukasawa e60969
 */
fukasawa e60969
typedef png_uint_16  udigit; /* A 'unum' is an array of these */
fukasawa e60969
typedef png_uint_16p uarb;
fukasawa e60969
typedef png_const_uint_16p uarbc;
fukasawa e60969
fukasawa e60969
#define UDIGITS(unum) ((sizeof unum)/(sizeof (udigit))
fukasawa e60969
   /* IMPORTANT: only apply this to an array, applied to a pointer the result
fukasawa e60969
    * will typically be '2', which is not useful.
fukasawa e60969
    */
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_set(uarb result, png_alloc_size_t val)
fukasawa e60969
   /* Set (initialize) 'result' to 'val'.  The size required for 'result' must
fukasawa e60969
    * be determined by the caller from a knowledge of the maximum for 'val'.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   int ndigits = 0;
fukasawa e60969
fukasawa e60969
   while (val > 0)
fukasawa e60969
   {
fukasawa e60969
      result[ndigits++] = (png_uint_16)(val & 0xffff);
fukasawa e60969
      val >>= 16;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return ndigits;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_copy(uarb to, uarb from, int idigits)
fukasawa e60969
   /* Copy a uarb, may reduce the digit count */
fukasawa e60969
{
fukasawa e60969
   int d, odigits;
fukasawa e60969
fukasawa e60969
   for (d=odigits=0; d
fukasawa e60969
      if ((to[d] = from[d]) != 0)
fukasawa e60969
         odigits = d+1;
fukasawa e60969
fukasawa e60969
   return odigits;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_inc(uarb num, int in_digits, png_int_32 add)
fukasawa e60969
   /* This is a signed 32-bit add, except that to avoid overflow the value added
fukasawa e60969
    * or subtracted must be no more than 2^31-65536.  A negative result
fukasawa e60969
    * indicates a negative number (which is an error below).  The size of
fukasawa e60969
    * 'num' should be max(in_digits+1,2) for arbitrary 'add' but can be just
fukasawa e60969
    * in_digits+1 if add is known to be in the range -65535..65535.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   FIX_GCC int out_digits = 0;
fukasawa e60969
fukasawa e60969
   while (out_digits < in_digits)
fukasawa e60969
   {
fukasawa e60969
      add += num[out_digits];
fukasawa e60969
      num[out_digits++] = (png_uint_16)(add & 0xffff);
fukasawa e60969
      add >>= 16;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   while (add != 0 && add != (-1))
fukasawa e60969
   {
fukasawa e60969
      num[out_digits++] = (png_uint_16)(add & 0xffff);
fukasawa e60969
      add >>= 16;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (add == 0)
fukasawa e60969
   {
fukasawa e60969
      while (out_digits > 0 && num[out_digits-1] == 0)
fukasawa e60969
         --out_digits;
fukasawa e60969
      return out_digits; /* may be 0 */
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else /* negative result */
fukasawa e60969
   {
fukasawa e60969
      while (out_digits > 1 && num[out_digits-1] == 0xffff)
fukasawa e60969
         --out_digits;
fukasawa e60969
fukasawa e60969
      return -out_digits;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_add32(uarb num, int in_digits, png_uint_32 add)
fukasawa e60969
   /* As above but this works with any 32-bit value and only does 'add' */
fukasawa e60969
{
fukasawa e60969
   if (in_digits > 0)
fukasawa e60969
   {
fukasawa e60969
      in_digits = uarb_inc(num, in_digits, add & 0xffff);
fukasawa e60969
      return uarb_inc(num+1, in_digits-1, add >> 16)+1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return uarb_set(num, add);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_mult_digit(uarb acc, int a_digits, uarb num, FIX_GCC int n_digits,
fukasawa e60969
   png_uint_16 val)
fukasawa e60969
   /* Primitive one-digit multiply - 'val' must be 0..65535. Note that this
fukasawa e60969
    * primitive is a multiply and accumulate - the result of *num * val is added
fukasawa e60969
    * to *acc.
fukasawa e60969
    *
fukasawa e60969
    * This is a one-digit multiply, so the product may be up to one digit longer
fukasawa e60969
    * than 'num', however the add to 'acc' means that the caller must ensure
fukasawa e60969
    * that 'acc' is at least one digit longer than this *and* at least one digit
fukasawa e60969
    * longer than the current length of 'acc'.  (Or the caller must otherwise
fukasawa e60969
    * ensure 'adigits' is adequate from knowledge of the values.)
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   /* The digits in *acc, *num and val are in the range 0..65535, so the
fukasawa e60969
    * result below is at most (65535*65535)+2*65635 = 65535*(65535+2), which is
fukasawa e60969
    * exactly 0xffffffff.
fukasawa e60969
    */
fukasawa e60969
   if (val > 0 && n_digits > 0) /* Else the product is 0 */
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 carry = 0;
fukasawa e60969
      int out_digits = 0;
fukasawa e60969
fukasawa e60969
      while (out_digits < n_digits || carry > 0)
fukasawa e60969
      {
fukasawa e60969
         if (out_digits < a_digits)
fukasawa e60969
            carry += acc[out_digits];
fukasawa e60969
fukasawa e60969
         if (out_digits < n_digits)
fukasawa e60969
            carry += (png_uint_32)num[out_digits] * val;
fukasawa e60969
fukasawa e60969
         acc[out_digits++] = (png_uint_16)(carry & 0xffff);
fukasawa e60969
         carry >>= 16;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* So carry is 0 and all the input digits have been consumed. This means
fukasawa e60969
       * that it is possible to skip any remaining digits in acc.
fukasawa e60969
       */
fukasawa e60969
      if (out_digits > a_digits)
fukasawa e60969
         return out_digits;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return a_digits;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_mult32(uarb acc, int a_digits, uarb num, int n_digits, png_uint_32 val)
fukasawa e60969
   /* calculate acc += num * val, 'val' may be any 32-bit value, 'acc' and 'num'
fukasawa e60969
    * may be any value, returns the number of digits in 'acc'.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   if (n_digits > 0 && val > 0)
fukasawa e60969
   {
fukasawa e60969
      a_digits = uarb_mult_digit(acc, a_digits, num, n_digits,
fukasawa e60969
         (png_uint_16)(val & 0xffff));
fukasawa e60969
fukasawa e60969
      val >>= 16;
fukasawa e60969
      if (val > 0)
fukasawa e60969
         a_digits = uarb_mult_digit(acc+1, a_digits-1, num, n_digits,
fukasawa e60969
            (png_uint_16)val) + 1;
fukasawa e60969
fukasawa e60969
      /* Because n_digits and val are >0 the following must be true: */
fukasawa e60969
      assert(a_digits > 0);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return a_digits;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_shift(uarb inout, int ndigits, unsigned int right_shift)
fukasawa e60969
   /* Shift inout right by right_shift bits, right_shift must be in the range
fukasawa e60969
    * 1..15
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   FIX_GCC int i = ndigits;
fukasawa e60969
   png_uint_16 carry = 0;
fukasawa e60969
fukasawa e60969
   assert(right_shift >= 1 && right_shift <= 15);
fukasawa e60969
fukasawa e60969
   while (--i >= 0)
fukasawa e60969
   {
fukasawa e60969
      png_uint_16 temp = (png_uint_16)(carry | (inout[i] >> right_shift));
fukasawa e60969
fukasawa e60969
      /* Bottom bits to top bits of carry */
fukasawa e60969
      carry = (png_uint_16)((inout[i] << (16-right_shift)) & 0xffff);
fukasawa e60969
fukasawa e60969
      inout[i] = temp;
fukasawa e60969
fukasawa e60969
      /* The shift may reduce ndigits */
fukasawa e60969
      if (i == ndigits-1 && temp == 0)
fukasawa e60969
         ndigits = i;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return ndigits;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
uarb_cmp(uarb a, int adigits, uarb b, int bdigits)
fukasawa e60969
   /* Return -1/0/+1 according as ab */
fukasawa e60969
{
fukasawa e60969
   if (adigits < bdigits)
fukasawa e60969
      return -1;
fukasawa e60969
fukasawa e60969
   if (adigits > bdigits)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   while (adigits-- > 0)
fukasawa e60969
      if (a[adigits] < b[adigits])
fukasawa e60969
         return -1;
fukasawa e60969
fukasawa e60969
      else if (a[adigits] > b[adigits])
fukasawa e60969
         return 1;
fukasawa e60969
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#if 0 /*UNUSED*/
fukasawa e60969
static int
fukasawa e60969
uarb_eq32(uarb num, int digits, png_uint_32 val)
fukasawa e60969
   /* Return true if the uarb is equal to 'val' */
fukasawa e60969
{
fukasawa e60969
   switch (digits)
fukasawa e60969
   {
fukasawa e60969
      case 0:  return val == 0;
fukasawa e60969
      case 1:  return val == num[0];
fukasawa e60969
      case 2:  return (val & 0xffff) == num[0] && (val >> 16) == num[1];
fukasawa e60969
      default: return 0;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
uarb_printx(uarb num, int digits, FILE *out)
fukasawa e60969
   /* Print 'num' as a hexadecimal number (easier than decimal!) */
fukasawa e60969
{
fukasawa e60969
   while (digits > 0)
fukasawa e60969
      if (num[--digits] > 0)
fukasawa e60969
      {
fukasawa e60969
         fprintf(out, "0x%x", num[digits]);
fukasawa e60969
fukasawa e60969
         while (digits > 0)
fukasawa e60969
            fprintf(out, "%.4x", num[--digits]);
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else if (digits == 0) /* the number is 0 */
fukasawa e60969
         fputs("0x0", out);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
uarb_print(uarb num, int digits, FILE *out)
fukasawa e60969
   /* Prints 'num' as a decimal if it will fit in an unsigned long, else as a
fukasawa e60969
    * hexadecimal number.  Notice that the results vary for images over 4GByte
fukasawa e60969
    * in a system dependent way, and the hexadecimal form doesn't work very well
fukasawa e60969
    * in awk script input.
fukasawa e60969
    *
fukasawa e60969
    *
fukasawa e60969
    * TODO: write uarb_div10
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   if (digits * sizeof (udigit) > sizeof (unsigned long))
fukasawa e60969
      uarb_printx(num, digits, out);
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      unsigned long n = 0;
fukasawa e60969
fukasawa e60969
      while (digits > 0)
fukasawa e60969
         n = (n << 16) + num[--digits];
fukasawa e60969
fukasawa e60969
      fprintf(out, "%lu", n);
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Generate random bytes.  This uses a boring repeatable algorithm and it
fukasawa e60969
 * is implemented here so that it gives the same set of numbers on every
fukasawa e60969
 * architecture.  It's a linear congruential generator (Knuth or Sedgewick
fukasawa e60969
 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
fukasawa e60969
 * Hill, "The Art of Electronics" (Pseudo-Random Bit Sequences and Noise
fukasawa e60969
 * Generation.)
fukasawa e60969
 *
fukasawa e60969
 * (Copied from contrib/libtests/pngvalid.c)
fukasawa e60969
 */
fukasawa e60969
static void
fukasawa e60969
make_random_bytes(png_uint_32* seed, void* pv, size_t size)
fukasawa e60969
{
fukasawa e60969
   png_uint_32 u0 = seed[0], u1 = seed[1];
fukasawa e60969
   png_bytep bytes = voidcast(png_bytep, pv);
fukasawa e60969
fukasawa e60969
   /* There are thirty-three bits; the next bit in the sequence is bit-33 XOR
fukasawa e60969
    * bit-20.  The top 1 bit is in u1, the bottom 32 are in u0.
fukasawa e60969
    */
fukasawa e60969
   size_t i;
fukasawa e60969
   for (i=0; i
fukasawa e60969
   {
fukasawa e60969
      /* First generate 8 new bits then shift them in at the end. */
fukasawa e60969
      png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
fukasawa e60969
      u1 <<= 8;
fukasawa e60969
      u1 |= u0 >> 24;
fukasawa e60969
      u0 <<= 8;
fukasawa e60969
      u0 |= u;
fukasawa e60969
      *bytes++ = (png_byte)u;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   seed[0] = u0;
fukasawa e60969
   seed[1] = u1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Clear an object to a random value. */
fukasawa e60969
static void
fukasawa e60969
clear(void *pv, size_t size)
fukasawa e60969
{
fukasawa e60969
   static png_uint_32 clear_seed[2] = { 0x12345678, 0x9abcdef0 };
fukasawa e60969
   make_random_bytes(clear_seed, pv, size);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#define CLEAR(object) clear(&(object), sizeof (object))
fukasawa e60969
fukasawa e60969
/* Copied from unreleased 1.7 code.
fukasawa e60969
 *
fukasawa e60969
 * CRC checking uses a local pre-built implementation of the Ethernet CRC32.
fukasawa e60969
 * This is to avoid a function call to the zlib DLL and to optimize the
fukasawa e60969
 * byte-by-byte case.
fukasawa e60969
 */
fukasawa e60969
static png_uint_32 crc_table[256] =
fukasawa e60969
{
fukasawa e60969
   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
fukasawa e60969
   0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
fukasawa e60969
   0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
fukasawa e60969
   0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
fukasawa e60969
   0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
fukasawa e60969
   0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
fukasawa e60969
   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
fukasawa e60969
   0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
fukasawa e60969
   0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
fukasawa e60969
   0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
fukasawa e60969
   0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
fukasawa e60969
   0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
fukasawa e60969
   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
fukasawa e60969
   0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
fukasawa e60969
   0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
fukasawa e60969
   0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
fukasawa e60969
   0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
fukasawa e60969
   0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
fukasawa e60969
   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
fukasawa e60969
   0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
fukasawa e60969
   0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
fukasawa e60969
   0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
fukasawa e60969
   0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
fukasawa e60969
   0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
fukasawa e60969
   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
fukasawa e60969
   0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
fukasawa e60969
   0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
fukasawa e60969
   0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
fukasawa e60969
   0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
fukasawa e60969
   0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
fukasawa e60969
   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
fukasawa e60969
   0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
fukasawa e60969
   0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
fukasawa e60969
   0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
fukasawa e60969
   0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
fukasawa e60969
   0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
fukasawa e60969
   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
fukasawa e60969
   0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
fukasawa e60969
   0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
fukasawa e60969
   0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
fukasawa e60969
   0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
fukasawa e60969
   0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
fukasawa e60969
   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
fukasawa e60969
   0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
fukasawa e60969
   0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
fukasawa e60969
   0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
fukasawa e60969
   0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
fukasawa e60969
   0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
fukasawa e60969
   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
fukasawa e60969
   0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
fukasawa e60969
   0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
fukasawa e60969
   0x2d02ef8d
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
/* The CRC calculated here *IS* conditioned, the corresponding value used by
fukasawa e60969
 * zlib and the result value is obtained by XORing with CRC_INIT, which is also
fukasawa e60969
 * the first value that must be passed in (for the first byte) to crc_one_byte.
fukasawa e60969
 */
fukasawa e60969
#define CRC_INIT 0xffffffff
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
crc_one_byte(png_uint_32 crc, int b)
fukasawa e60969
{
fukasawa e60969
   return crc_table[(crc ^ b) & 0xff] ^ (crc >> 8);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
crc_init_4(png_uint_32 value)
fukasawa e60969
{
fukasawa e60969
   /* This is an alternative to the algorithm used in zlib, which requires four
fukasawa e60969
    * separate tables to parallelize the four byte operations, it only works for
fukasawa e60969
    * a CRC of the first four bytes of the stream, but this is what happens in
fukasawa e60969
    * the parser below where length+chunk-name is read and chunk-name used to
fukasawa e60969
    * initialize the CRC.  Notice that the calculation here avoids repeated
fukasawa e60969
    * conditioning (xor with 0xffffffff) by storing the conditioned value.
fukasawa e60969
    */
fukasawa e60969
   png_uint_32 crc = crc_table[(~value >> 24)] ^ 0xffffff;
fukasawa e60969
fukasawa e60969
   crc = crc_table[(crc ^ (value >> 16)) & 0xff] ^ (crc >> 8);
fukasawa e60969
   crc = crc_table[(crc ^ (value >> 8)) & 0xff] ^ (crc >> 8);
fukasawa e60969
   return crc_table[(crc ^ value) & 0xff] ^ (crc >> 8);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
chunk_type_valid(png_uint_32 c)
fukasawa e60969
   /* Bit whacking approach to chunk name validation that is intended to avoid
fukasawa e60969
    * branches.  The cost is that it uses a lot of 32-bit constants, which might
fukasawa e60969
    * be bad on some architectures.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_uint_32 t;
fukasawa e60969
fukasawa e60969
   /* Remove bit 5 from all but the reserved byte; this means every
fukasawa e60969
    * 8-bit unit must be in the range 65-90 to be valid.  So bit 5
fukasawa e60969
    * must be zero, bit 6 must be set and bit 7 zero.
fukasawa e60969
    */
fukasawa e60969
   c &= ~PNG_U32(32,32,0,32);
fukasawa e60969
   t = (c & ~0x1f1f1f1f) ^ 0x40404040;
fukasawa e60969
fukasawa e60969
   /* Subtract 65 for each 8-bit quantity, this must not overflow
fukasawa e60969
    * and each byte must then be in the range 0-25.
fukasawa e60969
    */
fukasawa e60969
   c -= PNG_U32(65,65,65,65);
fukasawa e60969
   t |=c ;
fukasawa e60969
fukasawa e60969
   /* Subtract 26, handling the overflow which should set the top
fukasawa e60969
    * three bits of each byte.
fukasawa e60969
    */
fukasawa e60969
   c -= PNG_U32(25,25,25,26);
fukasawa e60969
   t |= ~c;
fukasawa e60969
fukasawa e60969
   return (t & 0xe0e0e0e0) == 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/**************************** CONTROL INFORMATION *****************************/
fukasawa e60969
fukasawa e60969
/* Information about a sequence of IDAT chunks, the chunks have been re-synced
fukasawa e60969
 * using sync_stream below and the new lengths are recorded here.  Because the
fukasawa e60969
 * number of chunks is unlimited this is handled using a linked list of these
fukasawa e60969
 * structures.
fukasawa e60969
 */
fukasawa e60969
struct IDAT_list
fukasawa e60969
{
fukasawa e60969
   struct IDAT_list *next;     /* Linked list */
fukasawa e60969
   unsigned int      length;   /* Actual length of the array below */
fukasawa e60969
   unsigned int      count;    /* Number of entries that are valid */
fukasawa e60969
#     define IDAT_INIT_LENGTH 16
fukasawa e60969
   png_uint_32       lengths[IDAT_INIT_LENGTH];
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
IDAT_list_init(struct IDAT_list *list)
fukasawa e60969
{
fukasawa e60969
   CLEAR(*list);
fukasawa e60969
fukasawa e60969
   list->next = NULL;
fukasawa e60969
   list->length = IDAT_INIT_LENGTH;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static size_t
fukasawa e60969
IDAT_list_size(struct IDAT_list *list, unsigned int length)
fukasawa e60969
   /* Return the size in bytes of an IDAT_list of the given length. */
fukasawa e60969
{
fukasawa e60969
   if (list != NULL)
fukasawa e60969
      length = list->length;
fukasawa e60969
fukasawa e60969
   return sizeof *list - sizeof list->lengths +
fukasawa e60969
      length * sizeof list->lengths[0];
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
IDAT_list_end(struct IDAT_list *IDAT_list)
fukasawa e60969
{
fukasawa e60969
   struct IDAT_list *list = IDAT_list->next;
fukasawa e60969
fukasawa e60969
   CLEAR(*IDAT_list);
fukasawa e60969
fukasawa e60969
   while (list != NULL)
fukasawa e60969
   {
fukasawa e60969
      struct IDAT_list *next = list->next;
fukasawa e60969
fukasawa e60969
      clear(list, IDAT_list_size(list, 0));
fukasawa e60969
      free(list);
fukasawa e60969
      list = next;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static struct IDAT_list *
fukasawa e60969
IDAT_list_extend(struct IDAT_list *tail)
fukasawa e60969
{
fukasawa e60969
   /* Use the previous cached value if available. */
fukasawa e60969
   struct IDAT_list *next = tail->next;
fukasawa e60969
fukasawa e60969
   if (next == NULL)
fukasawa e60969
   {
fukasawa e60969
      /* Insert a new, malloc'ed, block of IDAT information buffers, this
fukasawa e60969
       * one twice as large as the previous one:
fukasawa e60969
       */
fukasawa e60969
      unsigned int length = 2 * tail->length;
fukasawa e60969
fukasawa e60969
      if (length < tail->length) /* arithmetic overflow */
fukasawa e60969
         length = tail->length;
fukasawa e60969
fukasawa e60969
      next = voidcast(IDAT_list*, malloc(IDAT_list_size(NULL, length)));
fukasawa e60969
      CLEAR(*next);
fukasawa e60969
fukasawa e60969
      /* The caller must handle this: */
fukasawa e60969
      if (next == NULL)
fukasawa e60969
         return NULL;
fukasawa e60969
fukasawa e60969
      next->next = NULL;
fukasawa e60969
      next->length = length;
fukasawa e60969
      tail->next = next;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return next;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* GLOBAL CONTROL STRUCTURE */
fukasawa e60969
struct global
fukasawa e60969
{
fukasawa e60969
   /* PUBLIC GLOBAL VARIABLES: OWNER INITIALIZE */
fukasawa e60969
   unsigned int   errors        :1; /* print file errors to stderr */
fukasawa e60969
   unsigned int   warnings      :1; /* print libpng warnings to stderr */
fukasawa e60969
   unsigned int   optimize_zlib :1; /* Run optimization search */
fukasawa e60969
   unsigned int   quiet         :2; /* don't output summaries */
fukasawa e60969
   unsigned int   verbose       :3; /* various internal tracking */
fukasawa e60969
   unsigned int   skip          :3; /* Non-critical chunks to skip */
fukasawa e60969
#     define SKIP_NONE      0
fukasawa e60969
#     define SKIP_BAD_CRC   1    /* Chunks with a bad CRC */
fukasawa e60969
#     define SKIP_UNSAFE    2    /* Chunks not safe to copy */
fukasawa e60969
#     define SKIP_UNUSED    3    /* Chunks not used by libpng */
fukasawa e60969
#     define SKIP_TRANSFORM 4    /* Chunks only used in transforms */
fukasawa e60969
#     define SKIP_COLOR     5    /* Everything but tRNS, sBIT, gAMA and sRGB */
fukasawa e60969
#     define SKIP_ALL       6    /* Everything but tRNS and sBIT */
fukasawa e60969
fukasawa e60969
   png_uint_32    idat_max;         /* 0 to perform no re-chunking */
fukasawa e60969
fukasawa e60969
   int            status_code;      /* Accumulated status code */
fukasawa e60969
#     define TOO_FAR_BACK   0x01 /* found a too-far-back error */
fukasawa e60969
#     define CRC_ERROR      0x02 /* fixed an invalid CRC */
fukasawa e60969
#     define STREAM_ERROR   0x04 /* damaged PNG stream (may be fixable) */
fukasawa e60969
#     define TRUNCATED      0x08 /* truncated but still readable */
fukasawa e60969
#     define FILE_ERROR     0x10 /* could not read the file */
fukasawa e60969
#     define WRITE_ERROR    0x20 /* write error (this terminates the read) */
fukasawa e60969
#     define INTERNAL_ERROR 0x40 /* internal limits/errors encountered */
fukasawa e60969
fukasawa e60969
   /* PUBLIC GLOBAL VARIABLES: USED INTERNALLY BY IDAT READ CODE */
fukasawa e60969
   struct IDAT_list idat_cache;  /* Cache of file IDAT information buffers */
fukasawa e60969
      /* The structure is shared across all uses of this global control
fukasawa e60969
       * structure to avoid reallocation between IDAT streams.
fukasawa e60969
       */
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
global_end(struct global *global)
fukasawa e60969
{
fukasawa e60969
fukasawa e60969
   int rc;
fukasawa e60969
fukasawa e60969
   IDAT_list_end(&global->idat_cache);
fukasawa e60969
   rc = global->status_code;
fukasawa e60969
   CLEAR(*global);
fukasawa e60969
   return rc;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
global_init(struct global *global)
fukasawa e60969
   /* Call this once (and only once) to initialize the control */
fukasawa e60969
{
fukasawa e60969
   CLEAR(*global);
fukasawa e60969
fukasawa e60969
   /* Globals */
fukasawa e60969
   global->errors        = 0;
fukasawa e60969
   global->warnings      = 0;
fukasawa e60969
   global->quiet         = 0;
fukasawa e60969
   global->verbose       = 0;
fukasawa e60969
   global->idat_max      = 0;         /* no re-chunking of IDAT */
fukasawa e60969
   global->optimize_zlib = 0;
fukasawa e60969
   global->skip          = SKIP_NONE;
fukasawa e60969
   global->status_code   = 0;
fukasawa e60969
fukasawa e60969
   IDAT_list_init(&global->idat_cache);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
skip_chunk_type(const struct global *global, png_uint_32 type)
fukasawa e60969
   /* Return true if this chunk is to be skipped according to the --strip
fukasawa e60969
    * option.  This code needs to recognize all known ancillary chunks in order
fukasawa e60969
    * to handle the --strip=unsafe option.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   /* Never strip critical chunks: */
fukasawa e60969
   if (CRITICAL(type))
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   switch (type)
fukasawa e60969
   {
fukasawa e60969
      /* Chunks that are treated as, effectively, critical because they affect
fukasawa e60969
       * correct interpretation of the pixel values:
fukasawa e60969
       */
fukasawa e60969
      case png_tRNS: case png_sBIT:
fukasawa e60969
         return 0;
fukasawa e60969
fukasawa e60969
      /* Chunks that specify gamma encoding which should therefore only be
fukasawa e60969
       * removed the the user insists:
fukasawa e60969
       */
fukasawa e60969
      case png_gAMA: case png_sRGB:
fukasawa e60969
         if (global->skip >= SKIP_ALL)
fukasawa e60969
            return 1;
fukasawa e60969
         return 0;
fukasawa e60969
fukasawa e60969
      /* Chunks that affect color interpretation - not used by libpng and rarely
fukasawa e60969
       * used by applications, but technically still required for correct
fukasawa e60969
       * interpretation of the image data:
fukasawa e60969
       */
fukasawa e60969
      case png_cHRM: case png_iCCP:
fukasawa e60969
         if (global->skip >= SKIP_COLOR)
fukasawa e60969
            return 1;
fukasawa e60969
         return 0;
fukasawa e60969
fukasawa e60969
      /* Other chunks that are used by libpng in image transformations (as
fukasawa e60969
       * opposed to known chunks that have get/set APIs but are not otherwise
fukasawa e60969
       * used.)
fukasawa e60969
       */
fukasawa e60969
      case png_bKGD:
fukasawa e60969
         if (global->skip >= SKIP_TRANSFORM)
fukasawa e60969
            return 1;
fukasawa e60969
         return 0;
fukasawa e60969
fukasawa e60969
      /* All other chunks that libpng knows about and affect neither image
fukasawa e60969
       * interpretation nor libpng transforms - chunks that are effectively
fukasawa e60969
       * unused by libpng even though libpng might recognize and store them.
fukasawa e60969
       */
fukasawa e60969
      case png_fRAc: case png_gIFg: case png_gIFt: case png_gIFx: case png_hIST:
fukasawa e60969
      case png_iTXt: case png_oFFs: case png_pCAL: case png_pHYs: case png_sCAL:
fukasawa e60969
      case png_sPLT: case png_sTER: case png_tEXt: case png_tIME: case png_zTXt:
fukasawa e60969
         if (global->skip >= SKIP_UNUSED)
fukasawa e60969
            return 1;
fukasawa e60969
         return 0;
fukasawa e60969
fukasawa e60969
      /* Chunks that libpng does not know about (notice that this depends on the
fukasawa e60969
       * list above including all known chunks!)  The decision here depends on
fukasawa e60969
       * whether the safe-to-copy bit is set in the chunk type.
fukasawa e60969
       */
fukasawa e60969
      default:
fukasawa e60969
         if (SAFE_TO_COPY(type))
fukasawa e60969
         {
fukasawa e60969
            if (global->skip >= SKIP_UNUSED) /* as above */
fukasawa e60969
               return 1;
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         else if (global->skip >= SKIP_UNSAFE)
fukasawa e60969
            return 1;
fukasawa e60969
fukasawa e60969
         return 0;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* PER-FILE CONTROL STRUCTURE */
fukasawa e60969
struct chunk;
fukasawa e60969
struct IDAT;
fukasawa e60969
struct file
fukasawa e60969
{
fukasawa e60969
   /* ANCESTORS */
fukasawa e60969
   struct global *global;
fukasawa e60969
fukasawa e60969
   /* PUBLIC PER-FILE VARIABLES: CALLER INITIALIZE */
fukasawa e60969
   const char *   file_name;
fukasawa e60969
   const char *   out_name;      /* Name of output file (if required) */
fukasawa e60969
fukasawa e60969
   /* PUBLIC PER-FILE VARIABLES: SET BY PNG READ CODE */
fukasawa e60969
   /* File specific result codes */
fukasawa e60969
   int            status_code;   /* Set to a bit mask of the following: */
fukasawa e60969
   int            read_errno;    /* Records a read error errno */
fukasawa e60969
   int            write_errno;   /* Records a write error errno */
fukasawa e60969
fukasawa e60969
   /* IHDR information */
fukasawa e60969
   png_uint_32    width;
fukasawa e60969
   png_uint_32    height;
fukasawa e60969
   png_byte       bit_depth;
fukasawa e60969
   png_byte       color_type;
fukasawa e60969
   png_byte       compression_method;
fukasawa e60969
   png_byte       filter_method;
fukasawa e60969
   png_byte       interlace_method;
fukasawa e60969
fukasawa e60969
   udigit         image_bytes[5];
fukasawa e60969
   int            image_digits;
fukasawa e60969
fukasawa e60969
   /* PROTECTED PER-FILE VARIABLES: USED BY THE READ CODE */
fukasawa e60969
   FILE *         file;          /* Original PNG file */
fukasawa e60969
   FILE *         out;           /* If a new one is being written */
fukasawa e60969
   jmp_buf        jmpbuf;        /* Set while reading a PNG */
fukasawa e60969
fukasawa e60969
   /* PROTECTED CHUNK SPECIFIC VARIABLES: USED BY CHUNK CODE */
fukasawa e60969
   /* The following variables are used during reading to record the length, type
fukasawa e60969
    * and data position of the *next* chunk or, right at the start, the
fukasawa e60969
    * signature (in length,type).
fukasawa e60969
    *
fukasawa e60969
    * When a chunk control structure is instantiated these values are copied
fukasawa e60969
    * into the structure and can then be overritten with the data for the next
fukasawa e60969
    * chunk.
fukasawa e60969
    */
fukasawa e60969
   fpos_t         data_pos;      /* Position of first byte of chunk data */
fukasawa e60969
   png_uint_32    length;        /* First word (length or signature start) */
fukasawa e60969
   png_uint_32    type;          /* Second word (type or signature end) */
fukasawa e60969
   png_uint_32    crc;           /* Running chunk CRC (used by read_chunk) */
fukasawa e60969
fukasawa e60969
   /* These counts are maintained by the read and write routines below and are
fukasawa e60969
    * reset by the chunk handling code.  They record the total number of bytes
fukasawa e60969
    * read or written for the chunk, including the header (length,type) bytes.
fukasawa e60969
    */
fukasawa e60969
   png_uint_32    read_count;    /* Count of bytes read (in the chunk) */
fukasawa e60969
   png_uint_32    write_count;   /* Count of bytes written (in the chunk) */
fukasawa e60969
   int            state;         /* As defined here: */
fukasawa e60969
#     define STATE_SIGNATURE  0  /* The signature is being written */
fukasawa e60969
#     define STATE_CHUNKS     1  /* Non-IDAT chunks are being written */
fukasawa e60969
#     define STATE_IDAT       2  /* An IDAT stream is being written */
fukasawa e60969
fukasawa e60969
   /* Two pointers used to enable clean-up in the event of fatal errors and to
fukasawa e60969
    * hold state about the parser process (only one of each at present.)
fukasawa e60969
    */
fukasawa e60969
   struct chunk * chunk;
fukasawa e60969
   struct IDAT *  idat;
fukasawa e60969
fukasawa e60969
   /* Interface to allocate a new chunk or IDAT control structure.  The result
fukasawa e60969
    * is returned by setting one or other of the above variables.  Note that the
fukasawa e60969
    * relevant initializer is called by the allocator function.  The alloc_ptr
fukasawa e60969
    * is used only by the implementation of the allocate function.
fukasawa e60969
    */
fukasawa e60969
   void *         alloc_ptr;
fukasawa e60969
   void         (*alloc)(struct file*,int idat);
fukasawa e60969
                                  /* idat: allocate IDAT not chunk */
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
/* Valid longjmp (stop) codes are: */
fukasawa e60969
#define LIBPNG_WARNING_CODE   1 /* generic png_error */
fukasawa e60969
#define LIBPNG_ERROR_CODE     2 /* generic png_error */
fukasawa e60969
#define ZLIB_ERROR_CODE       3 /* generic zlib error */
fukasawa e60969
#define INVALID_ERROR_CODE    4 /* detected an invalid PNG */
fukasawa e60969
#define READ_ERROR_CODE       5 /* read failed */
fukasawa e60969
#define WRITE_ERROR_CODE      6 /* error in write */
fukasawa e60969
#define UNEXPECTED_ERROR_CODE 7 /* unexpected (internal?) error */
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
emit_string(const char *str, FILE *out)
fukasawa e60969
   /* Print a string with spaces replaced by '_' and non-printing characters by
fukasawa e60969
    * an octal escape.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   for (; *str; ++str)
fukasawa e60969
      if (isgraph(UCHAR_MAX & *str))
fukasawa e60969
         putc(*str, out);
fukasawa e60969
fukasawa e60969
      else if (isspace(UCHAR_MAX & *str))
fukasawa e60969
         putc('_', out);
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
         fprintf(out, "\\%.3o", *str);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static const char *
fukasawa e60969
strcode(int code)
fukasawa e60969
{
fukasawa e60969
   switch (code)
fukasawa e60969
   {
fukasawa e60969
      case LIBPNG_WARNING_CODE:   return "warning";
fukasawa e60969
      case LIBPNG_ERROR_CODE:     return "libpng";
fukasawa e60969
      case ZLIB_ERROR_CODE:       return "zlib";
fukasawa e60969
      case INVALID_ERROR_CODE:    return "invalid";
fukasawa e60969
      case READ_ERROR_CODE:       return "read";
fukasawa e60969
      case WRITE_ERROR_CODE:      return "write";
fukasawa e60969
      case UNEXPECTED_ERROR_CODE: return "unexpected";
fukasawa e60969
      default:                    return "INVALID";
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
emit_error(struct file *file, int code, const char *what)
fukasawa e60969
   /* Generic error message routine, takes a 'stop' code but can be used
fukasawa e60969
    * elsewhere.  Always outputs a message.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   const char *reason;
fukasawa e60969
   int err = 0;
fukasawa e60969
fukasawa e60969
   switch (code)
fukasawa e60969
   {
fukasawa e60969
      case LIBPNG_WARNING_CODE:   reason = "libpng warning:"; break;
fukasawa e60969
      case LIBPNG_ERROR_CODE:     reason = "libpng error:"; break;
fukasawa e60969
      case ZLIB_ERROR_CODE:       reason = "zlib error:"; break;
fukasawa e60969
      case INVALID_ERROR_CODE:    reason = "invalid"; break;
fukasawa e60969
      case READ_ERROR_CODE:       reason = "read failure:";
fukasawa e60969
                                  err = file->read_errno;
fukasawa e60969
                                  break;
fukasawa e60969
      case WRITE_ERROR_CODE:      reason = "write error";
fukasawa e60969
                                  err = file->write_errno;
fukasawa e60969
                                  break;
fukasawa e60969
      case UNEXPECTED_ERROR_CODE: reason = "unexpected error:";
fukasawa e60969
                                  err = file->read_errno;
fukasawa e60969
                                  if (err == 0)
fukasawa e60969
                                     err = file->write_errno;
fukasawa e60969
                                  break;
fukasawa e60969
      default:                    reason = "INVALID (internal error):"; break;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (err != 0)
fukasawa e60969
      fprintf(stderr, "%s: %s %s [%s]\n", file->file_name, reason, what,
fukasawa e60969
         strerror(err));
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      fprintf(stderr, "%s: %s %s\n", file->file_name, reason, what);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void chunk_end(struct chunk **);
fukasawa e60969
static void IDAT_end(struct IDAT **);
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
file_end(struct file *file)
fukasawa e60969
{
fukasawa e60969
   int rc;
fukasawa e60969
fukasawa e60969
   /* If either of the chunk pointers are set end them here, the IDAT structure
fukasawa e60969
    * must be deallocated first as it may deallocate the chunk structure.
fukasawa e60969
    */
fukasawa e60969
   if (file->idat != NULL)
fukasawa e60969
      IDAT_end(&file->idat);
fukasawa e60969
fukasawa e60969
   if (file->chunk != NULL)
fukasawa e60969
      chunk_end(&file->chunk);
fukasawa e60969
fukasawa e60969
   rc = file->status_code;
fukasawa e60969
fukasawa e60969
   if (file->file != NULL)
fukasawa e60969
      (void)fclose(file->file);
fukasawa e60969
fukasawa e60969
   if (file->out != NULL)
fukasawa e60969
   {
fukasawa e60969
      /* NOTE: this is bitwise |, all the following functions must execute and
fukasawa e60969
       * must succeed.
fukasawa e60969
       */
fukasawa e60969
      if (ferror(file->out) | fflush(file->out) | fclose(file->out))
fukasawa e60969
      {
fukasawa e60969
         perror(file->out_name);
fukasawa e60969
         emit_error(file, READ_ERROR_CODE, "output write error");
fukasawa e60969
         rc |= WRITE_ERROR;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Accumulate the result codes */
fukasawa e60969
   file->global->status_code |= rc;
fukasawa e60969
fukasawa e60969
   CLEAR(*file);
fukasawa e60969
fukasawa e60969
   return rc; /* status code: non-zero on read or write error */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
file_init(struct file *file, struct global *global, const char *file_name,
fukasawa e60969
   const char *out_name, void *alloc_ptr, void (*alloc)(struct file*,int))
fukasawa e60969
   /* Initialize a file control structure.  This will open the given files as
fukasawa e60969
    * well.  The status code returned is 0 on success, non zero (using the flags
fukasawa e60969
    * above) on a file open error.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   CLEAR(*file);
fukasawa e60969
   file->global = global;
fukasawa e60969
fukasawa e60969
   file->file_name = file_name;
fukasawa e60969
   file->out_name = out_name;
fukasawa e60969
   file->status_code = 0;
fukasawa e60969
   file->read_errno = 0;
fukasawa e60969
   file->write_errno = 0;
fukasawa e60969
fukasawa e60969
   file->file = NULL;
fukasawa e60969
   file->out = NULL;
fukasawa e60969
   /* jmpbuf is garbage: must be set by read_png */
fukasawa e60969
fukasawa e60969
   file->read_count = 0;
fukasawa e60969
   file->state = STATE_SIGNATURE;
fukasawa e60969
fukasawa e60969
   file->chunk = NULL;
fukasawa e60969
   file->idat = NULL;
fukasawa e60969
fukasawa e60969
   file->alloc_ptr = alloc_ptr;
fukasawa e60969
   file->alloc = alloc;
fukasawa e60969
fukasawa e60969
   /* Open the files: */
fukasawa e60969
   assert(file_name != NULL);
fukasawa e60969
   file->file = fopen(file_name, "rb");
fukasawa e60969
fukasawa e60969
   if (file->file == NULL)
fukasawa e60969
   {
fukasawa e60969
      file->read_errno = errno;
fukasawa e60969
      file->status_code |= FILE_ERROR;
fukasawa e60969
      /* Always output: please give a readable file! */
fukasawa e60969
      perror(file_name);
fukasawa e60969
      return FILE_ERROR;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (out_name != NULL)
fukasawa e60969
   {
fukasawa e60969
      file->out = fopen(out_name, "wb");
fukasawa e60969
fukasawa e60969
      if (file->out == NULL)
fukasawa e60969
      {
fukasawa e60969
         file->write_errno = errno;
fukasawa e60969
         file->status_code |= WRITE_ERROR;
fukasawa e60969
         perror(out_name);
fukasawa e60969
         return WRITE_ERROR;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
log_error(struct file *file, int code, const char *what)
fukasawa e60969
   /* Like emit_error but checks the global 'errors' flag */
fukasawa e60969
{
fukasawa e60969
   if (file->global->errors)
fukasawa e60969
      emit_error(file, code, what);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static char
fukasawa e60969
type_char(png_uint_32 v)
fukasawa e60969
{
fukasawa e60969
   /* In fact because chunk::chunk_type is validated prior to any call to this
fukasawa e60969
    * function it will always return a-zA-Z, but the extra codes are just there
fukasawa e60969
    * to help in finding internal (programming) errors.  Note that the code only
fukasawa e60969
    * ever considers the low 7 bits of the value (so it is not necessary for the
fukasawa e60969
    * type_name function to mask of the byte.)
fukasawa e60969
    */
fukasawa e60969
   if (v & 32)
fukasawa e60969
      return "!abcdefghijklmnopqrstuvwxyz56789"[(v-96)&31];
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      return "@ABCDEFGHIJKLMNOPQRSTUVWXYZ01234"[(v-64)&31];
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
type_name(png_uint_32 type, FILE *out)
fukasawa e60969
{
fukasawa e60969
   putc(type_char(type >> 24), out);
fukasawa e60969
   putc(type_char(type >> 16), out);
fukasawa e60969
   putc(type_char(type >>  8), out);
fukasawa e60969
   putc(type_char(type      ), out);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
type_sep(FILE *out)
fukasawa e60969
{
fukasawa e60969
   putc(':', out);
fukasawa e60969
   putc(' ', out);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_uint_32 current_type(struct file *file, int code);
fukasawa e60969
fukasawa e60969
PNG_NORETURN static void
fukasawa e60969
stop(struct file *file, int code, const char *what)
fukasawa e60969
   /* Return control when a PNG file cannot be read. This outputs an 'ERR'
fukasawa e60969
    * summary line too.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   log_error(file, code, what);
fukasawa e60969
fukasawa e60969
   /* The chunk being read is typically identified by file->chunk or, if this is
fukasawa e60969
    * NULL, by file->type.  This may be wrong if libpng reads ahead, but this
fukasawa e60969
    * only happens with IDAT where libpng reads the header then jumps around
fukasawa e60969
    * finding errors in the previous chunks.  We know that is happening because
fukasawa e60969
    * we are at the start of the IDAT (i.e. no IDAT data has yet been written.)
fukasawa e60969
    *
fukasawa e60969
    * SUMMARY FORMAT (stop):
fukasawa e60969
    *
fukasawa e60969
    * IDAT ERR status code read-errno write-errno message file
fukasawa e60969
    *
fukasawa e60969
    * 'uncompressed' will be 0 if there was a problem in the IHDR.  The errno
fukasawa e60969
    * values are emit_string(strerror(errno)).
fukasawa e60969
    */
fukasawa e60969
   if (file->global->quiet < 2) /* need two quiets to stop this. */
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 type;
fukasawa e60969
fukasawa e60969
      if (file->chunk != NULL)
fukasawa e60969
         type = current_type(file, code); /* Gropes in struct chunk and IDAT */
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
         type = file->type;
fukasawa e60969
fukasawa e60969
      if (type)
fukasawa e60969
         type_name(type, stdout);
fukasawa e60969
fukasawa e60969
      else /* magic: an IDAT header, produces bogons for too many IDATs */
fukasawa e60969
         fputs("HEAD", stdout); /* not a registered chunk! */
fukasawa e60969
fukasawa e60969
      printf(" ERR %.2x %s ", file->status_code, strcode(code));
fukasawa e60969
      /* This only works one strerror at a time, because of the way strerror is
fukasawa e60969
       * implemented.
fukasawa e60969
       */
fukasawa e60969
      emit_string(strerror(file->read_errno), stdout);
fukasawa e60969
      putc(' ', stdout);
fukasawa e60969
      emit_string(strerror(file->write_errno), stdout);
fukasawa e60969
      putc(' ', stdout);
fukasawa e60969
      emit_string(what, stdout);
fukasawa e60969
      putc(' ', stdout);
fukasawa e60969
      fputs(file->file_name, stdout);
fukasawa e60969
      putc('\n', stdout);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   file->status_code |= FILE_ERROR;
fukasawa e60969
   longjmp(file->jmpbuf, code);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
PNG_NORETURN static void
fukasawa e60969
stop_invalid(struct file *file, const char *what)
fukasawa e60969
{
fukasawa e60969
   stop(file, INVALID_ERROR_CODE, what);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
type_message(struct file *file, png_uint_32 type, const char *what)
fukasawa e60969
   /* Error message for a chunk; the chunk name comes from 'type' */
fukasawa e60969
{
fukasawa e60969
   if (file->global->errors)
fukasawa e60969
   {
fukasawa e60969
      fputs(file->file_name, stderr);
fukasawa e60969
      type_sep(stderr);
fukasawa e60969
      type_name(type, stderr);
fukasawa e60969
      type_sep(stderr);
fukasawa e60969
      fputs(what, stderr);
fukasawa e60969
      putc('\n', stderr);
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Input file positioning - we jump around in the input file while reading
fukasawa e60969
 * stuff, these wrappers deal with the error handling.
fukasawa e60969
 */
fukasawa e60969
static void
fukasawa e60969
file_getpos(struct file *file, fpos_t *pos)
fukasawa e60969
{
fukasawa e60969
   if (fgetpos(file->file, pos))
fukasawa e60969
   {
fukasawa e60969
      /* This is unexpected, so perror it */
fukasawa e60969
      perror(file->file_name);
fukasawa e60969
      stop(file, READ_ERROR_CODE, "fgetpos");
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
file_setpos(struct file *file, const fpos_t *pos)
fukasawa e60969
{
fukasawa e60969
   if (fsetpos(file->file, pos))
fukasawa e60969
   {
fukasawa e60969
      perror(file->file_name);
fukasawa e60969
      stop(file, READ_ERROR_CODE, "fsetpos");
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
getpos(struct file *file)
fukasawa e60969
   /* Get the current position and store it in 'data_pos'.  The corresponding
fukasawa e60969
    * setpos() function is chunk specific because it uses the copy of the
fukasawa e60969
    * position for the specific chunk.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   file_getpos(file, &file->data_pos);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
fukasawa e60969
/* Read utility - read a single byte, returns a value in the range 0..255 or EOF
fukasawa e60969
 * on a read error.  In the latter case status_code and read_errno are updated
fukasawa e60969
 * appropriately.
fukasawa e60969
 */
fukasawa e60969
static int
fukasawa e60969
read_byte(struct file *file)
fukasawa e60969
{
fukasawa e60969
   int ch = getc(file->file);
fukasawa e60969
fukasawa e60969
   if (ch >= 0 && ch <= 255)
fukasawa e60969
   {
fukasawa e60969
      ++(file->read_count);
fukasawa e60969
      return ch;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else if (ch != EOF)
fukasawa e60969
   {
fukasawa e60969
      file->status_code |= INTERNAL_ERROR;
fukasawa e60969
      file->read_errno = ERANGE; /* out of range character */
fukasawa e60969
fukasawa e60969
      /* This is very unexpected; an error message is always output: */
fukasawa e60969
      emit_error(file, UNEXPECTED_ERROR_CODE, "file read");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
#  ifdef EINTR
fukasawa e60969
      else if (errno == EINTR) /* Interrupted, try again */
fukasawa e60969
      {
fukasawa e60969
         errno = 0;
fukasawa e60969
         return read_byte(file);
fukasawa e60969
      }
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      /* An error, it doesn't really matter what the error is but it gets
fukasawa e60969
       * recorded anyway.
fukasawa e60969
       */
fukasawa e60969
      if (ferror(file->file))
fukasawa e60969
         file->read_errno = errno;
fukasawa e60969
fukasawa e60969
      else if (feof(file->file))
fukasawa e60969
         file->read_errno = 0; /* I.e. a regular EOF, no error */
fukasawa e60969
fukasawa e60969
      else /* unexpected */
fukasawa e60969
         file->read_errno = EDOM;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* 'TRUNCATED' is used for all cases of failure to read a byte, because of
fukasawa e60969
    * the way libpng works a byte read is never attempted unless the byte is
fukasawa e60969
    * expected to be there, so EOF should not occur.
fukasawa e60969
    */
fukasawa e60969
   file->status_code |= TRUNCATED;
fukasawa e60969
   return EOF;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_byte
fukasawa e60969
reread_byte(struct file *file)
fukasawa e60969
   /* Read a byte when an error is not expected to happen because the byte has
fukasawa e60969
    * been read before without error.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   int ch = getc(file->file);
fukasawa e60969
fukasawa e60969
   if (errno != 0)
fukasawa e60969
      file->read_errno = errno;
fukasawa e60969
fukasawa e60969
   if (ch < 0 || ch > 255)
fukasawa e60969
      stop(file, UNEXPECTED_ERROR_CODE, "reread");
fukasawa e60969
fukasawa e60969
   return (png_byte)ch;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
reread_4(struct file *file)
fukasawa e60969
   /* The same but for a four byte quantity */
fukasawa e60969
{
fukasawa e60969
   png_uint_32 result = 0;
fukasawa e60969
   int i = 0;
fukasawa e60969
fukasawa e60969
   while (++i <= 4)
fukasawa e60969
      result = (result << 8) + reread_byte(file);
fukasawa e60969
fukasawa e60969
   return result;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
skip_12(struct file *file)
fukasawa e60969
   /* Skip exactly 12 bytes in the input stream - used to skip a CRC and chunk
fukasawa e60969
    * header that has been read before.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   /* Since the chunks were read before this shouldn't fail: */
fukasawa e60969
   if (fseek(file->file, 12, SEEK_CUR) != 0)
fukasawa e60969
   {
fukasawa e60969
      if (errno != 0)
fukasawa e60969
         file->read_errno = errno;
fukasawa e60969
fukasawa e60969
      stop(file, UNEXPECTED_ERROR_CODE, "reskip");
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
write_byte(struct file *file, int b)
fukasawa e60969
   /* Write one byte to the output - this causes a fatal error if the write
fukasawa e60969
    * fails and the read of this PNG file immediately terminates.  Just
fukasawa e60969
    * increments the write count if there is no output file.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   if (file->out != NULL)
fukasawa e60969
   {
fukasawa e60969
      if (putc(b, file->out) != b)
fukasawa e60969
      {
fukasawa e60969
         file->write_errno = errno;
fukasawa e60969
         file->status_code |= WRITE_ERROR;
fukasawa e60969
         stop(file, WRITE_ERROR_CODE, "write byte");
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   ++(file->write_count);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Derivatives of the read/write functions. */
fukasawa e60969
static unsigned int
fukasawa e60969
read_4(struct file *file, png_uint_32 *pu)
fukasawa e60969
   /* Read four bytes, returns the number of bytes read successfully and, if all
fukasawa e60969
    * four bytes are read, assigns the result to *pu.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   unsigned int i = 0;
fukasawa e60969
   png_uint_32 val = 0;
fukasawa e60969
fukasawa e60969
   do
fukasawa e60969
   {
fukasawa e60969
      int ch = read_byte(file);
fukasawa e60969
fukasawa e60969
      if (ch == EOF)
fukasawa e60969
         return i;
fukasawa e60969
fukasawa e60969
      val = (val << 8) + ch;
fukasawa e60969
   } while (++i < 4);
fukasawa e60969
fukasawa e60969
   *pu = val;
fukasawa e60969
   return i;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* CRC handling - read but calculate the CRC while doing so. */
fukasawa e60969
static int
fukasawa e60969
crc_read_many(struct file *file, png_uint_32 length)
fukasawa e60969
   /* Reads 'length' bytes and updates the CRC, returns true on success, false
fukasawa e60969
    * if the input is truncated.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   if (length > 0)
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 crc = file->crc;
fukasawa e60969
fukasawa e60969
      do
fukasawa e60969
      {
fukasawa e60969
         int ch = read_byte(file);
fukasawa e60969
fukasawa e60969
         if (ch == EOF)
fukasawa e60969
            return 0; /* Truncated */
fukasawa e60969
fukasawa e60969
         crc = crc_one_byte(crc, ch);
fukasawa e60969
      }
fukasawa e60969
      while (--length > 0);
fukasawa e60969
fukasawa e60969
      file->crc = crc;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 1; /* OK */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
calc_image_size(struct file *file)
fukasawa e60969
   /* Fill in the image_bytes field given the IHDR information, calls stop on
fukasawa e60969
    * error.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_uint_16 pd = file->bit_depth;
fukasawa e60969
fukasawa e60969
   switch (file->color_type)
fukasawa e60969
   {
fukasawa e60969
      default:
fukasawa e60969
         stop_invalid(file, "IHDR: colour type");
fukasawa e60969
fukasawa e60969
      invalid_bit_depth:
fukasawa e60969
         stop_invalid(file, "IHDR: bit depth");
fukasawa e60969
fukasawa e60969
      case 0: /* g */
fukasawa e60969
         if (pd != 1 && pd != 2 && pd != 4 && pd != 8 && pd != 16)
fukasawa e60969
            goto invalid_bit_depth;
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 3:
fukasawa e60969
         if (pd != 1 && pd != 2 && pd != 4 && pd != 8)
fukasawa e60969
            goto invalid_bit_depth;
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 2: /* rgb */
fukasawa e60969
         if (pd != 8 && pd != 16)
fukasawa e60969
            goto invalid_bit_depth;
fukasawa e60969
fukasawa e60969
         pd = (png_uint_16)(pd * 3);
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 4: /* ga */
fukasawa e60969
         if (pd != 8 && pd != 16)
fukasawa e60969
            goto invalid_bit_depth;
fukasawa e60969
fukasawa e60969
         pd = (png_uint_16)(pd * 2);
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 6: /* rgba */
fukasawa e60969
         if (pd != 8 && pd != 16)
fukasawa e60969
            goto invalid_bit_depth;
fukasawa e60969
fukasawa e60969
         pd = (png_uint_16)(pd * 4);
fukasawa e60969
         break;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (file->width < 1 || file->width > 0x7fffffff)
fukasawa e60969
      stop_invalid(file, "IHDR: width");
fukasawa e60969
fukasawa e60969
   else if (file->height < 1 || file->height > 0x7fffffff)
fukasawa e60969
      stop_invalid(file, "IHDR: height");
fukasawa e60969
fukasawa e60969
   else if (file->compression_method != 0)
fukasawa e60969
      stop_invalid(file, "IHDR: compression method");
fukasawa e60969
fukasawa e60969
   else if (file->filter_method != 0)
fukasawa e60969
      stop_invalid(file, "IHDR: filter method");
fukasawa e60969
fukasawa e60969
   else switch (file->interlace_method)
fukasawa e60969
   {
fukasawa e60969
      case PNG_INTERLACE_ADAM7:
fukasawa e60969
         /* Interlacing makes the image larger because of the replication of
fukasawa e60969
          * both the filter byte and the padding to a byte boundary.
fukasawa e60969
          */
fukasawa e60969
         {
fukasawa e60969
            int pass;
fukasawa e60969
            int image_digits = 0;
fukasawa e60969
            udigit row_width[2], row_bytes[3];
fukasawa e60969
fukasawa e60969
            for (pass=0; pass<=6; ++pass)
fukasawa e60969
            {
fukasawa e60969
               png_uint_32 pw = PNG_PASS_COLS(file->width, pass);
fukasawa e60969
fukasawa e60969
               if (pw > 0)
fukasawa e60969
               {
fukasawa e60969
                  int  digits;
fukasawa e60969
fukasawa e60969
                  /* calculate 1+((pw*pd+7)>>3) in row_bytes */
fukasawa e60969
                  digits = uarb_mult_digit(row_bytes, uarb_set(row_bytes, 7),
fukasawa e60969
                     row_width, uarb_set(row_width, pw), pd);
fukasawa e60969
                  digits = uarb_shift(row_bytes, digits, 3);
fukasawa e60969
                  digits = uarb_inc(row_bytes, digits, 1);
fukasawa e60969
fukasawa e60969
                  /* Add row_bytes * pass-height to the file image_bytes field
fukasawa e60969
                   */
fukasawa e60969
                  image_digits = uarb_mult32(file->image_bytes, image_digits,
fukasawa e60969
                     row_bytes, digits,
fukasawa e60969
                     PNG_PASS_ROWS(file->height, pass));
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            file->image_digits = image_digits;
fukasawa e60969
         }
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_INTERLACE_NONE:
fukasawa e60969
         {
fukasawa e60969
            int  digits;
fukasawa e60969
            udigit row_width[2], row_bytes[3];
fukasawa e60969
fukasawa e60969
            /* As above, but use image_width in place of the pass width: */
fukasawa e60969
            digits = uarb_mult_digit(row_bytes, uarb_set(row_bytes, 7),
fukasawa e60969
               row_width, uarb_set(row_width, file->width), pd);
fukasawa e60969
            digits = uarb_shift(row_bytes, digits, 3);
fukasawa e60969
            digits = uarb_inc(row_bytes, digits, 1);
fukasawa e60969
fukasawa e60969
            /* Set row_bytes * image-height to the file image_bytes field */
fukasawa e60969
            file->image_digits = uarb_mult32(file->image_bytes, 0,
fukasawa e60969
               row_bytes, digits, file->height);
fukasawa e60969
         }
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         stop_invalid(file, "IHDR: interlace method");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   assert(file->image_digits >= 1 && file->image_digits <= 5);
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* PER-CHUNK CONTROL STRUCTURE
fukasawa e60969
 * This structure is instantiated for each chunk, except for the IDAT chunks
fukasawa e60969
 * where one chunk control structure is used for the whole of a single stream of
fukasawa e60969
 * IDAT chunks (see the IDAT control structure below).
fukasawa e60969
 */
fukasawa e60969
struct chunk
fukasawa e60969
{
fukasawa e60969
   /* ANCESTORS */
fukasawa e60969
   struct file *         file;
fukasawa e60969
   struct global *       global;
fukasawa e60969
fukasawa e60969
   /* PUBLIC IDAT INFORMATION: SET BY THE ZLIB CODE */
fukasawa e60969
   udigit         uncompressed_bytes[5];
fukasawa e60969
   int            uncompressed_digits;
fukasawa e60969
   udigit         compressed_bytes[5];
fukasawa e60969
   int            compressed_digits;
fukasawa e60969
fukasawa e60969
   /* PUBLIC PER-CHUNK INFORMATION: USED BY CHUNK READ CODE */
fukasawa e60969
   /* This information is filled in by chunk_init from the data in the file
fukasawa e60969
    * control structure, but chunk_length may be changed later.
fukasawa e60969
    */
fukasawa e60969
   fpos_t         chunk_data_pos;    /* Position of first byte of chunk data */
fukasawa e60969
   png_uint_32    chunk_length;      /* From header (or modified below) */
fukasawa e60969
   png_uint_32    chunk_type;        /* From header */
fukasawa e60969
fukasawa e60969
   /* PUBLIC PER-CHUNK INFORMATION: FOR THE CHUNK WRITE CODE */
fukasawa e60969
   png_uint_32    write_crc;         /* Output CRC (may differ from read_crc) */
fukasawa e60969
   png_uint_32    rewrite_offset;    /* Count of bytes before rewrite. */
fukasawa e60969
   int            rewrite_length;    /* Number of bytes left to change */
fukasawa e60969
   png_byte       rewrite_buffer[2]; /* Buffer of new byte values */
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
chunk_message(struct chunk *chunk, const char *message)
fukasawa e60969
{
fukasawa e60969
   type_message(chunk->file, chunk->chunk_type, message);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
chunk_end(struct chunk **chunk_var)
fukasawa e60969
{
fukasawa e60969
   struct chunk *chunk = *chunk_var;
fukasawa e60969
fukasawa e60969
   *chunk_var = NULL;
fukasawa e60969
   CLEAR(*chunk);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
chunk_init(struct chunk * const chunk, struct file * const file)
fukasawa e60969
   /* When a chunk is initialized the file length/type/pos are copied into the
fukasawa e60969
    * corresponding chunk fields and the new chunk is registered in the file
fukasawa e60969
    * structure.  There can only be one chunk at a time.
fukasawa e60969
    *
fukasawa e60969
    * NOTE: this routine must onely be called from the file alloc routine!
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   assert(file->chunk == NULL);
fukasawa e60969
fukasawa e60969
   CLEAR(*chunk);
fukasawa e60969
fukasawa e60969
   chunk->file = file;
fukasawa e60969
   chunk->global = file->global;
fukasawa e60969
fukasawa e60969
   chunk->chunk_data_pos = file->data_pos;
fukasawa e60969
   chunk->chunk_length = file->length;
fukasawa e60969
   chunk->chunk_type = file->type;
fukasawa e60969
fukasawa e60969
   /* Compresssed/uncompressed size information (from the zlib control structure
fukasawa e60969
    * that is used to check the compressed data in a chunk.)
fukasawa e60969
    */
fukasawa e60969
   chunk->uncompressed_digits = 0;
fukasawa e60969
   chunk->compressed_digits = 0;
fukasawa e60969
fukasawa e60969
   file->chunk = chunk;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
current_type(struct file *file, int code)
fukasawa e60969
   /* Guess the actual chunk type that causes a stop() */
fukasawa e60969
{
fukasawa e60969
   /* This may return png_IDAT for errors detected (late) in the header; that
fukasawa e60969
    * includes any inter-chunk consistency check that libpng performs.  Assume
fukasawa e60969
    * that if the chunk_type is png_IDAT and the file write count is 8 this is
fukasawa e60969
    * what is happening.
fukasawa e60969
    */
fukasawa e60969
   if (file->chunk != NULL)
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 type = file->chunk->chunk_type;
fukasawa e60969
fukasawa e60969
      /* This is probably wrong for the excess IDATs case, because then libpng
fukasawa e60969
       * whines about too many of them (apparently in some cases erroneously)
fukasawa e60969
       * when the header is read.
fukasawa e60969
       */
fukasawa e60969
      if (code <= LIBPNG_ERROR_CODE && type == png_IDAT &&
fukasawa e60969
         file->write_count == 8)
fukasawa e60969
         type = 0; /* magic */
fukasawa e60969
fukasawa e60969
      return type;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      return file->type;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
setpos(struct chunk *chunk)
fukasawa e60969
   /* Reset the position to 'chunk_data_pos' - the start of the data for this
fukasawa e60969
    * chunk.  As a side effect the read_count in the file is reset to 8, just
fukasawa e60969
    * after the length/type header.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   chunk->file->read_count = 8;
fukasawa e60969
   file_setpos(chunk->file, &chunk->chunk_data_pos);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Specific chunk handling - called for each chunk header, all special chunk
fukasawa e60969
 * processing is initiated in these functions.
fukasawa e60969
 */
fukasawa e60969
/* The next functions handle special processing for those chunks with LZ data,
fukasawa e60969
 * the data is identified and checked for validity.  If there are problems which
fukasawa e60969
 * cannot be corrected the routines return false, otherwise true (although
fukasawa e60969
 * modification to the zlib header may be required.)
fukasawa e60969
 *
fukasawa e60969
 * The compressed data is in zlib format (RFC1950) and consequently has a
fukasawa e60969
 * minimum length of 7 bytes.
fukasawa e60969
 */
fukasawa e60969
static int zlib_check(struct file *file, png_uint_32 offset);
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
process_zTXt_iCCP(struct file *file)
fukasawa e60969
   /* zTXt and iCCP have exactly the same form - keyword, null, compression
fukasawa e60969
    * method then compressed data.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   struct chunk *chunk = file->chunk;
fukasawa e60969
   png_uint_32 length;
fukasawa e60969
   png_uint_32 index = 0;
fukasawa e60969
fukasawa e60969
   assert(chunk != NULL && file->idat == NULL);
fukasawa e60969
   length = chunk->chunk_length;
fukasawa e60969
   setpos(chunk);
fukasawa e60969
fukasawa e60969
   while (length >= 9)
fukasawa e60969
   {
fukasawa e60969
      --length;
fukasawa e60969
      ++index;
fukasawa e60969
      if (reread_byte(file) == 0) /* keyword null terminator */
fukasawa e60969
      {
fukasawa e60969
         --length;
fukasawa e60969
         ++index;
fukasawa e60969
         (void)reread_byte(file); /* compression method */
fukasawa e60969
         return zlib_check(file, index);
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   chunk_message(chunk, "too short");
fukasawa e60969
   return 0; /* skip */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
process_iTXt(struct file *file)
fukasawa e60969
{
fukasawa e60969
   /* Like zTXt but more fields. */
fukasawa e60969
   struct chunk *chunk = file->chunk;
fukasawa e60969
   png_uint_32 length;
fukasawa e60969
   png_uint_32 index = 0;
fukasawa e60969
fukasawa e60969
   assert(chunk != NULL && file->idat == NULL);
fukasawa e60969
   length = chunk->chunk_length;
fukasawa e60969
   setpos(chunk);
fukasawa e60969
fukasawa e60969
   while (length >= 5)
fukasawa e60969
   {
fukasawa e60969
      --length;
fukasawa e60969
      ++index;
fukasawa e60969
      if (reread_byte(file) == 0) /* keyword null terminator */
fukasawa e60969
      {
fukasawa e60969
         --length;
fukasawa e60969
         ++index;
fukasawa e60969
         if (reread_byte(file) == 0) /* uncompressed text */
fukasawa e60969
            return 1; /* nothing to check */
fukasawa e60969
fukasawa e60969
         --length;
fukasawa e60969
         ++index;
fukasawa e60969
         (void)reread_byte(file); /* compression method */
fukasawa e60969
fukasawa e60969
         /* Skip the language tag (null terminated). */
fukasawa e60969
         while (length >= 9)
fukasawa e60969
         {
fukasawa e60969
            --length;
fukasawa e60969
            ++index;
fukasawa e60969
            if (reread_byte(file) == 0) /* terminator */
fukasawa e60969
            {
fukasawa e60969
               /* Skip the translated keyword */
fukasawa e60969
               while (length >= 8)
fukasawa e60969
               {
fukasawa e60969
                  --length;
fukasawa e60969
                  ++index;
fukasawa e60969
                  if (reread_byte(file) == 0) /* terminator */
fukasawa e60969
                     return zlib_check(file, index);
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         /* Ran out of bytes in the compressed case. */
fukasawa e60969
         break;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   log_error(file, INVALID_ERROR_CODE, "iTXt chunk length");
fukasawa e60969
fukasawa e60969
   return 0; /* skip */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* IDAT READ/WRITE CONTROL STRUCTURE */
fukasawa e60969
struct IDAT
fukasawa e60969
{
fukasawa e60969
   /* ANCESTORS */
fukasawa e60969
   struct file *         file;
fukasawa e60969
   struct global *       global;
fukasawa e60969
fukasawa e60969
   /* PROTECTED IDAT INFORMATION: SET BY THE IDAT READ CODE */
fukasawa e60969
   struct IDAT_list *idat_list_head; /* START of the list of IDAT information */
fukasawa e60969
   struct IDAT_list *idat_list_tail; /* *END* of the list of IDAT information */
fukasawa e60969
fukasawa e60969
   /* PROTECTED IDAT INFORMATION: USED BY THE IDAT WRITE CODE */
fukasawa e60969
   struct IDAT_list *idat_cur;       /* Current list entry */
fukasawa e60969
   unsigned int      idat_count;     /* And the *current* index into the list */
fukasawa e60969
   png_uint_32       idat_index;     /* Index of *next* input byte to write */
fukasawa e60969
   png_uint_32       idat_length;    /* Cache of current chunk length */
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
/* NOTE: there is currently no IDAT_reset, so a stream cannot contain more than
fukasawa e60969
 * one IDAT sequence (i.e. MNG is not supported).
fukasawa e60969
 */
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
IDAT_end(struct IDAT **idat_var)
fukasawa e60969
{
fukasawa e60969
   struct IDAT *idat = *idat_var;
fukasawa e60969
   struct file *file = idat->file;
fukasawa e60969
fukasawa e60969
   *idat_var = NULL;
fukasawa e60969
fukasawa e60969
   CLEAR(*idat);
fukasawa e60969
fukasawa e60969
   assert(file->chunk != NULL);
fukasawa e60969
   chunk_end(&file->chunk);
fukasawa e60969
fukasawa e60969
   /* Regardless of why the IDAT was killed set the state back to CHUNKS (it may
fukasawa e60969
    * already be CHUNKS because the state isn't changed until process_IDAT
fukasawa e60969
    * returns; a stop will cause IDAT_end to be entered in state CHUNKS!)
fukasawa e60969
    */
fukasawa e60969
   file->state = STATE_CHUNKS;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
IDAT_init(struct IDAT * const idat, struct file * const file)
fukasawa e60969
   /* When the chunk is png_IDAT instantiate an IDAT control structure in place
fukasawa e60969
    * of a chunk control structure.  The IDAT will instantiate a chunk control
fukasawa e60969
    * structure using the file alloc routine.
fukasawa e60969
    *
fukasawa e60969
    * NOTE: this routine must only be called from the file alloc routine!
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   assert(file->chunk == NULL);
fukasawa e60969
   assert(file->idat == NULL);
fukasawa e60969
fukasawa e60969
   CLEAR(*idat);
fukasawa e60969
fukasawa e60969
   idat->file = file;
fukasawa e60969
   idat->global = file->global;
fukasawa e60969
fukasawa e60969
   /* Initialize the tail to the pre-allocated buffer and set the count to 0
fukasawa e60969
    * (empty.)
fukasawa e60969
    */
fukasawa e60969
   idat->global->idat_cache.count = 0;
fukasawa e60969
   idat->idat_list_head = idat->idat_list_tail = &idat->global->idat_cache;
fukasawa e60969
fukasawa e60969
   /* Now the chunk.  The allocator calls the initializer of the new chunk and
fukasawa e60969
    * stores the result in file->chunk:
fukasawa e60969
    */
fukasawa e60969
   file->alloc(file, 0/*chunk*/);
fukasawa e60969
   assert(file->chunk != NULL);
fukasawa e60969
fukasawa e60969
   /* And store this for cleanup (and to check for double alloc or failure to
fukasawa e60969
    * free.)
fukasawa e60969
    */
fukasawa e60969
   file->idat = idat;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
rechunk_length(struct IDAT *idat)
fukasawa e60969
   /* Return the length for the next IDAT chunk, taking into account
fukasawa e60969
    * rechunking.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_uint_32 len = idat->global->idat_max;
fukasawa e60969
fukasawa e60969
   if (len == 0) /* use original chunk lengths */
fukasawa e60969
   {
fukasawa e60969
      const struct IDAT_list *cur;
fukasawa e60969
      unsigned int count;
fukasawa e60969
fukasawa e60969
      if (idat->idat_index == 0) /* at the new chunk (first time) */
fukasawa e60969
         return idat->idat_length; /* use the cache */
fukasawa e60969
fukasawa e60969
      /* Otherwise rechunk_length is called at the end of a chunk for the length
fukasawa e60969
       * of the next one.
fukasawa e60969
       */
fukasawa e60969
      cur = idat->idat_cur;
fukasawa e60969
      count = idat->idat_count;
fukasawa e60969
fukasawa e60969
      assert(idat->idat_index == idat->idat_length &&
fukasawa e60969
         idat->idat_length == cur->lengths[count]);
fukasawa e60969
fukasawa e60969
      /* Return length of the *next* chunk */
fukasawa e60969
      if (++count < cur->count)
fukasawa e60969
         return cur->lengths[count];
fukasawa e60969
fukasawa e60969
      /* End of this list */
fukasawa e60969
      assert(cur != idat->idat_list_tail);
fukasawa e60969
      cur = cur->next;
fukasawa e60969
      assert(cur != NULL && cur->count > 0);
fukasawa e60969
      return cur->lengths[0];
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else /* rechunking */
fukasawa e60969
   {
fukasawa e60969
      /* The chunk size is the lesser of file->idat_max and the number
fukasawa e60969
       * of remaining bytes.
fukasawa e60969
       */
fukasawa e60969
      png_uint_32 have = idat->idat_length - idat->idat_index;
fukasawa e60969
fukasawa e60969
      if (len > have)
fukasawa e60969
      {
fukasawa e60969
         struct IDAT_list *cur = idat->idat_cur;
fukasawa e60969
         unsigned int j = idat->idat_count+1; /* the next IDAT in the list */
fukasawa e60969
fukasawa e60969
         do
fukasawa e60969
         {
fukasawa e60969
            /* Add up the remaining bytes.  This can't overflow because the
fukasawa e60969
             * individual lengths are always <= 0x7fffffff, so when we add two
fukasawa e60969
             * of them overflow is not possible.
fukasawa e60969
             */
fukasawa e60969
            assert(cur != NULL);
fukasawa e60969
fukasawa e60969
            for (;;)
fukasawa e60969
            {
fukasawa e60969
               /* NOTE: IDAT_list::count here, not IDAT_list::length */
fukasawa e60969
               for (; j < cur->count; ++j)
fukasawa e60969
               {
fukasawa e60969
                  have += cur->lengths[j];
fukasawa e60969
                  if (len <= have)
fukasawa e60969
                     return len;
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               /* If this was the end return the count of the available bytes */
fukasawa e60969
               if (cur == idat->idat_list_tail)
fukasawa e60969
                  return have;
fukasawa e60969
fukasawa e60969
               cur = cur->next;
fukasawa e60969
               j = 0;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
         while (len > have);
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      return len;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
process_IDAT(struct file *file)
fukasawa e60969
   /* Process the IDAT stream, this is the more complex than the preceding
fukasawa e60969
    * cases because the compressed data is spread across multiple IDAT chunks
fukasawa e60969
    * (typically).  Rechunking of the data is not handled here; all this
fukasawa e60969
    * function does is establish whether the zlib header needs to be modified.
fukasawa e60969
    *
fukasawa e60969
    * Initially the function returns false, indicating that the chunk should not
fukasawa e60969
    * be written.  It does this until the last IDAT chunk is passed in, then it
fukasawa e60969
    * checks the zlib data and returns true.
fukasawa e60969
    *
fukasawa e60969
    * It does not return false on a fatal error; it calls stop instead.
fukasawa e60969
    *
fukasawa e60969
    * The caller must have an instantiated (IDAT) control structure and it must
fukasawa e60969
    * have extent over the whole read of the IDAT stream.  For a PNG this means
fukasawa e60969
    * the whole PNG read, for MNG it could have lesser extent.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   struct IDAT_list *list;
fukasawa e60969
fukasawa e60969
   assert(file->idat != NULL && file->chunk != NULL);
fukasawa e60969
fukasawa e60969
   /* We need to first check the entire sequence of IDAT chunks to ensure the
fukasawa e60969
    * stream is in sync.  Do this by building a list of all the chunks and
fukasawa e60969
    * recording the length of each because the length may have been fixed up by
fukasawa e60969
    * sync_stream below.
fukasawa e60969
    *
fukasawa e60969
    * At the end of the list of chunks, where the type of the next chunk is not
fukasawa e60969
    * png_IDAT, process the whole stream using the list data to check validity
fukasawa e60969
    * then return control to the start and rewrite everything.
fukasawa e60969
    */
fukasawa e60969
   list = file->idat->idat_list_tail;
fukasawa e60969
fukasawa e60969
   if (list->count == list->length)
fukasawa e60969
   {
fukasawa e60969
      list = IDAT_list_extend(list);
fukasawa e60969
fukasawa e60969
      if (list == NULL)
fukasawa e60969
         stop(file, READ_ERROR_CODE, "out of memory");
fukasawa e60969
fukasawa e60969
      /* Move to the next block */
fukasawa e60969
      list->count = 0;
fukasawa e60969
      file->idat->idat_list_tail = list;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* And fill in the next IDAT information buffer. */
fukasawa e60969
   list->lengths[(list->count)++] = file->chunk->chunk_length;
fukasawa e60969
fukasawa e60969
   /* The type of the next chunk was recorded in the file control structure by
fukasawa e60969
    * the caller, if this is png_IDAT return 'skip' to the caller.
fukasawa e60969
    */
fukasawa e60969
   if (file->type == png_IDAT)
fukasawa e60969
      return 0; /* skip this for the moment */
fukasawa e60969
fukasawa e60969
   /* This is the final IDAT chunk, so run the tests to check for the too far
fukasawa e60969
    * back error and possibly optimize the window bits.  This means going back
fukasawa e60969
    * to the start of the first chunk data, which is stored in the original
fukasawa e60969
    * chunk allocation.
fukasawa e60969
    */
fukasawa e60969
   setpos(file->chunk);
fukasawa e60969
fukasawa e60969
   if (zlib_check(file, 0))
fukasawa e60969
   {
fukasawa e60969
      struct IDAT *idat;
fukasawa e60969
      int cmp;
fukasawa e60969
fukasawa e60969
      /* The IDAT stream was successfully uncompressed; see whether it
fukasawa e60969
       * contained the correct number of bytes of image data.
fukasawa e60969
       */
fukasawa e60969
      cmp = uarb_cmp(file->image_bytes, file->image_digits,
fukasawa e60969
         file->chunk->uncompressed_bytes, file->chunk->uncompressed_digits);
fukasawa e60969
fukasawa e60969
      if (cmp < 0)
fukasawa e60969
         type_message(file, png_IDAT, "extra uncompressed data");
fukasawa e60969
fukasawa e60969
      else if (cmp > 0)
fukasawa e60969
         stop(file, LIBPNG_ERROR_CODE, "IDAT: uncompressed data too small");
fukasawa e60969
fukasawa e60969
      /* Return the stream to the start of the first IDAT chunk; the length
fukasawa e60969
       * is set in the write case below but the input chunk variables must be
fukasawa e60969
       * set (once) here:
fukasawa e60969
       */
fukasawa e60969
      setpos(file->chunk);
fukasawa e60969
fukasawa e60969
      idat = file->idat;
fukasawa e60969
      idat->idat_cur = idat->idat_list_head;
fukasawa e60969
      idat->idat_length = idat->idat_cur->lengths[0];
fukasawa e60969
      idat->idat_count = 0; /* Count of chunks read in current list */
fukasawa e60969
      idat->idat_index = 0; /* Index into chunk data */
fukasawa e60969
fukasawa e60969
      /* Update the chunk length to the correct value for the IDAT chunk: */
fukasawa e60969
      file->chunk->chunk_length = rechunk_length(idat);
fukasawa e60969
fukasawa e60969
      /* Change the state to writing IDAT chunks */
fukasawa e60969
      file->state = STATE_IDAT;
fukasawa e60969
fukasawa e60969
      return 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else /* Failure to decompress the IDAT stream; give up. */
fukasawa e60969
      stop(file, ZLIB_ERROR_CODE, "could not uncompress IDAT");
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* ZLIB CONTROL STRUCTURE */
fukasawa e60969
struct zlib
fukasawa e60969
{
fukasawa e60969
   /* ANCESTORS */
fukasawa e60969
   struct IDAT *  idat;          /* NOTE: May be NULL */
fukasawa e60969
   struct chunk * chunk;
fukasawa e60969
   struct file *  file;
fukasawa e60969
   struct global *global;
fukasawa e60969
fukasawa e60969
   /* GLOBAL ZLIB INFORMATION: SET BY THE CALLER */
fukasawa e60969
   png_uint_32    rewrite_offset;
fukasawa e60969
fukasawa e60969
   /* GLOBAL ZLIB INFORMATION: SET BY THE ZLIB READ CODE */
fukasawa e60969
   udigit         compressed_bytes[5];
fukasawa e60969
   int            compressed_digits;
fukasawa e60969
   udigit         uncompressed_bytes[5];
fukasawa e60969
   int            uncompressed_digits;
fukasawa e60969
   int            file_bits;             /* window bits from the file */
fukasawa e60969
   int            ok_bits;               /* Set <16 on a successful read */
fukasawa e60969
   int            cksum;                 /* Set on a checksum error */
fukasawa e60969
fukasawa e60969
   /* PROTECTED ZLIB INFORMATION: USED BY THE ZLIB ROUTINES */
fukasawa e60969
   z_stream       z;
fukasawa e60969
   png_uint_32    extra_bytes;   /* Count of extra compressed bytes */
fukasawa e60969
   int            state;
fukasawa e60969
   int            rc;            /* Last return code */
fukasawa e60969
   int            window_bits;   /* 0 if no change */
fukasawa e60969
   png_byte       header[2];
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static const char *
fukasawa e60969
zlib_flevel(struct zlib *zlib)
fukasawa e60969
{
fukasawa e60969
   switch (zlib->header[1] >> 6)
fukasawa e60969
   {
fukasawa e60969
      case 0:  return "supfast";
fukasawa e60969
      case 1:  return "stdfast";
fukasawa e60969
      case 2:  return "default";
fukasawa e60969
      case 3:  return "maximum";
fukasawa e60969
      default: assert(UNREACHED);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return "COMPILER BUG";
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static const char *
fukasawa e60969
zlib_rc(struct zlib *zlib)
fukasawa e60969
   /* Return a string for the zlib return code */
fukasawa e60969
{
fukasawa e60969
   switch (zlib->rc)
fukasawa e60969
   {
fukasawa e60969
      case Z_OK:              return "Z_OK";
fukasawa e60969
      case Z_STREAM_END:      return "Z_STREAM_END";
fukasawa e60969
      case Z_NEED_DICT:       return "Z_NEED_DICT";
fukasawa e60969
      case Z_ERRNO:           return "Z_ERRNO";
fukasawa e60969
      case Z_STREAM_ERROR:    return "Z_STREAM_ERROR";
fukasawa e60969
      case Z_DATA_ERROR:      return "Z_DATA_ERROR";
fukasawa e60969
      case Z_MEM_ERROR:       return "Z_MEM_ERROR";
fukasawa e60969
      case Z_BUF_ERROR:       return "Z_BUF_ERROR";
fukasawa e60969
      case Z_VERSION_ERROR:   return "Z_VERSION_ERROR";
fukasawa e60969
      default:                return "Z_*INVALID_RC*";
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
zlib_message(struct zlib *zlib, int unexpected)
fukasawa e60969
   /* Output a message given a zlib rc */
fukasawa e60969
{
fukasawa e60969
   if (zlib->global->errors)
fukasawa e60969
   {
fukasawa e60969
      const char *reason = zlib->z.msg;
fukasawa e60969
fukasawa e60969
      if (reason == NULL)
fukasawa e60969
         reason = "[no message]";
fukasawa e60969
fukasawa e60969
      fputs(zlib->file->file_name, stderr);
fukasawa e60969
      type_sep(stderr);
fukasawa e60969
      type_name(zlib->chunk->chunk_type, stderr);
fukasawa e60969
      fprintf(stderr, ": %szlib error: %d (%s) (%s)\n",
fukasawa e60969
         unexpected ? "unexpected " : "", zlib->rc, zlib_rc(zlib), reason);
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
zlib_end(struct zlib *zlib)
fukasawa e60969
{
fukasawa e60969
   /* Output the summary line now; this ensures a summary line always gets
fukasawa e60969
    * output regardless of the manner of exit.
fukasawa e60969
    */
fukasawa e60969
   if (!zlib->global->quiet)
fukasawa e60969
   {
fukasawa e60969
      if (zlib->ok_bits < 16) /* stream was read ok */
fukasawa e60969
      {
fukasawa e60969
         const char *reason;
fukasawa e60969
fukasawa e60969
         if (zlib->cksum)
fukasawa e60969
            reason = "CHK"; /* checksum error */
fukasawa e60969
fukasawa e60969
         else if (zlib->ok_bits > zlib->file_bits)
fukasawa e60969
            reason = "TFB"; /* fixing a too-far-back error */
fukasawa e60969
fukasawa e60969
         else if (zlib->ok_bits == zlib->file_bits)
fukasawa e60969
            reason = "OK ";
fukasawa e60969
fukasawa e60969
         else
fukasawa e60969
            reason = "OPT"; /* optimizing window bits */
fukasawa e60969
fukasawa e60969
         /* SUMMARY FORMAT (for a successful zlib inflate):
fukasawa e60969
          *
fukasawa e60969
          * IDAT reason flevel file-bits ok-bits compressed uncompressed file
fukasawa e60969
          */
fukasawa e60969
         type_name(zlib->chunk->chunk_type, stdout);
fukasawa e60969
         printf(" %s %s %d %d ", reason, zlib_flevel(zlib), zlib->file_bits,
fukasawa e60969
            zlib->ok_bits);
fukasawa e60969
         uarb_print(zlib->compressed_bytes, zlib->compressed_digits, stdout);
fukasawa e60969
         putc(' ', stdout);
fukasawa e60969
         uarb_print(zlib->uncompressed_bytes, zlib->uncompressed_digits,
fukasawa e60969
            stdout);
fukasawa e60969
         putc(' ', stdout);
fukasawa e60969
         fputs(zlib->file->file_name, stdout);
fukasawa e60969
         putc('\n', stdout);
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         /* This is a zlib read error; the chunk will be skipped.  For an IDAT
fukasawa e60969
          * stream this will also cause a fatal read error (via stop()).
fukasawa e60969
          *
fukasawa e60969
          * SUMMARY FORMAT:
fukasawa e60969
          *
fukasawa e60969
          * IDAT SKP flevel file-bits z-rc compressed message file
fukasawa e60969
          *
fukasawa e60969
          * z-rc is the zlib failure code; message is the error message with
fukasawa e60969
          * spaces replaced by '-'.  The compressed byte count indicates where
fukasawa e60969
          * in the zlib stream the error occurred.
fukasawa e60969
          */
fukasawa e60969
         type_name(zlib->chunk->chunk_type, stdout);
fukasawa e60969
         printf(" SKP %s %d %s ", zlib_flevel(zlib), zlib->file_bits,
fukasawa e60969
            zlib_rc(zlib));
fukasawa e60969
         uarb_print(zlib->compressed_bytes, zlib->compressed_digits, stdout);
fukasawa e60969
         putc(' ', stdout);
fukasawa e60969
         emit_string(zlib->z.msg ? zlib->z.msg : "[no_message]", stdout);
fukasawa e60969
         putc(' ', stdout);
fukasawa e60969
         fputs(zlib->file->file_name, stdout);
fukasawa e60969
         putc('\n', stdout);
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (zlib->state >= 0)
fukasawa e60969
   {
fukasawa e60969
      zlib->rc = inflateEnd(&zlib->z);
fukasawa e60969
fukasawa e60969
      if (zlib->rc != Z_OK)
fukasawa e60969
         zlib_message(zlib, 1/*unexpected*/);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   CLEAR(*zlib);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
zlib_reset(struct zlib *zlib, int window_bits)
fukasawa e60969
   /* Reinitializes a zlib with a different window_bits */
fukasawa e60969
{
fukasawa e60969
   assert(zlib->state >= 0); /* initialized by zlib_init */
fukasawa e60969
fukasawa e60969
   zlib->z.next_in = Z_NULL;
fukasawa e60969
   zlib->z.avail_in = 0;
fukasawa e60969
   zlib->z.next_out = Z_NULL;
fukasawa e60969
   zlib->z.avail_out = 0;
fukasawa e60969
fukasawa e60969
   zlib->window_bits = window_bits;
fukasawa e60969
   zlib->compressed_digits = 0;
fukasawa e60969
   zlib->uncompressed_digits = 0;
fukasawa e60969
fukasawa e60969
   zlib->state = 0; /* initialized, once */
fukasawa e60969
   zlib->rc = inflateReset2(&zlib->z, 0);
fukasawa e60969
   if (zlib->rc != Z_OK)
fukasawa e60969
   {
fukasawa e60969
      zlib_message(zlib, 1/*unexpected*/);
fukasawa e60969
      return 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
zlib_init(struct zlib *zlib, struct IDAT *idat, struct chunk *chunk,
fukasawa e60969
   int window_bits, png_uint_32 offset)
fukasawa e60969
   /* Initialize a zlib_control; the result is true/false */
fukasawa e60969
{
fukasawa e60969
   CLEAR(*zlib);
fukasawa e60969
fukasawa e60969
   zlib->idat = idat;
fukasawa e60969
   zlib->chunk = chunk;
fukasawa e60969
   zlib->file = chunk->file;
fukasawa e60969
   zlib->global = chunk->global;
fukasawa e60969
   zlib->rewrite_offset = offset; /* never changed for this zlib */
fukasawa e60969
fukasawa e60969
   /* *_out does not need to be set: */
fukasawa e60969
   zlib->z.next_in = Z_NULL;
fukasawa e60969
   zlib->z.avail_in = 0;
fukasawa e60969
   zlib->z.zalloc = Z_NULL;
fukasawa e60969
   zlib->z.zfree = Z_NULL;
fukasawa e60969
   zlib->z.opaque = Z_NULL;
fukasawa e60969
fukasawa e60969
   zlib->state = -1;
fukasawa e60969
   zlib->window_bits = window_bits;
fukasawa e60969
fukasawa e60969
   zlib->compressed_digits = 0;
fukasawa e60969
   zlib->uncompressed_digits = 0;
fukasawa e60969
fukasawa e60969
   /* These values are sticky across reset (in addition to the stuff in the
fukasawa e60969
    * first block, which is actually constant.)
fukasawa e60969
    */
fukasawa e60969
   zlib->file_bits = 24;
fukasawa e60969
   zlib->ok_bits = 16; /* unset */
fukasawa e60969
   zlib->cksum = 0; /* set when a checksum error is detected */
fukasawa e60969
fukasawa e60969
   /* '0' means use the header; inflateInit2 should always succeed because it
fukasawa e60969
    * does nothing apart from allocating the internal zstate.
fukasawa e60969
    */
fukasawa e60969
   zlib->rc = inflateInit2(&zlib->z, 0);
fukasawa e60969
   if (zlib->rc != Z_OK)
fukasawa e60969
   {
fukasawa e60969
      zlib_message(zlib, 1/*unexpected*/);
fukasawa e60969
      return 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      zlib->state = 0; /* initialized */
fukasawa e60969
      return 1;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
max_window_bits(uarbc size, int ndigits)
fukasawa e60969
   /* Return the zlib stream window bits required for data of the given size. */
fukasawa e60969
{
fukasawa e60969
   png_uint_16 cb;
fukasawa e60969
fukasawa e60969
   if (ndigits > 1)
fukasawa e60969
      return 15;
fukasawa e60969
fukasawa e60969
   cb = size[0];
fukasawa e60969
fukasawa e60969
   if (cb > 16384) return 15;
fukasawa e60969
   if (cb >  8192) return 14;
fukasawa e60969
   if (cb >  4096) return 13;
fukasawa e60969
   if (cb >  2048) return 12;
fukasawa e60969
   if (cb >  1024) return 11;
fukasawa e60969
   if (cb >   512) return 10;
fukasawa e60969
   if (cb >   256) return  9;
fukasawa e60969
   return 8;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
zlib_advance(struct zlib *zlib, png_uint_32 nbytes)
fukasawa e60969
   /* Read nbytes compressed bytes; the stream will be initialized if required.
fukasawa e60969
    * Bytes are always being reread and errors are fatal.  The return code is as
fukasawa e60969
    * follows:
fukasawa e60969
    *
fukasawa e60969
    *    -1: saw the "too far back" error
fukasawa e60969
    *     0: ok, keep going
fukasawa e60969
    *     1: saw Z_STREAM_END (zlib->extra_bytes indicates too much data)
fukasawa e60969
    *     2: a zlib error that cannot be corrected (error message already
fukasawa e60969
    *        output if required.)
fukasawa e60969
    */
fukasawa e60969
#  define ZLIB_TOO_FAR_BACK (-1)
fukasawa e60969
#  define ZLIB_OK           0
fukasawa e60969
#  define ZLIB_STREAM_END   1
fukasawa e60969
#  define ZLIB_FATAL        2
fukasawa e60969
{
fukasawa e60969
   int state = zlib->state;
fukasawa e60969
   int endrc = ZLIB_OK;
fukasawa e60969
   png_uint_32 in_bytes = 0;
fukasawa e60969
   struct file *file = zlib->file;
fukasawa e60969
fukasawa e60969
   assert(state >= 0);
fukasawa e60969
fukasawa e60969
   while (in_bytes < nbytes && endrc == ZLIB_OK)
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 out_bytes;
fukasawa e60969
      int flush;
fukasawa e60969
      png_byte bIn = reread_byte(file);
fukasawa e60969
      png_byte bOut;
fukasawa e60969
fukasawa e60969
      switch (state)
fukasawa e60969
      {
fukasawa e60969
         case 0: /* first header byte */
fukasawa e60969
            {
fukasawa e60969
               int file_bits = 8+(bIn >> 4);
fukasawa e60969
               int new_bits = zlib->window_bits;
fukasawa e60969
fukasawa e60969
               zlib->file_bits = file_bits;
fukasawa e60969
fukasawa e60969
               /* Check against the existing value - it may not need to be
fukasawa e60969
                * changed.  Note that a bogus file_bits is allowed through once,
fukasawa e60969
                * to see if it works, but the window_bits value is set to 15,
fukasawa e60969
                * the maximum.
fukasawa e60969
                */
fukasawa e60969
               if (new_bits == 0) /* no change */
fukasawa e60969
                  zlib->window_bits = ((file_bits > 15) ? 15 : file_bits);
fukasawa e60969
fukasawa e60969
               else if (new_bits != file_bits) /* rewrite required */
fukasawa e60969
                  bIn = (png_byte)((bIn & 0xf) + ((new_bits-8) << 4));
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            zlib->header[0] = bIn;
fukasawa e60969
            zlib->state = state = 1;
fukasawa e60969
            break;
fukasawa e60969
fukasawa e60969
         case 1: /* second header byte */
fukasawa e60969
            {
fukasawa e60969
               int b2 = bIn & 0xe0; /* top 3 bits */
fukasawa e60969
fukasawa e60969
               /* The checksum calculation, on the first 11 bits: */
fukasawa e60969
               b2 += 0x1f - ((zlib->header[0] << 8) + b2) % 0x1f;
fukasawa e60969
fukasawa e60969
               /* Update the checksum byte if required: */
fukasawa e60969
               if (bIn != b2)
fukasawa e60969
               {
fukasawa e60969
                  /* If the first byte wasn't changed this indicates an error in
fukasawa e60969
                   * the checksum calculation; signal this by setting 'cksum'.
fukasawa e60969
                   */
fukasawa e60969
                  if (zlib->file_bits == zlib->window_bits)
fukasawa e60969
                     zlib->cksum = 1;
fukasawa e60969
fukasawa e60969
                  bIn = (png_byte)b2;
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            zlib->header[1] = bIn;
fukasawa e60969
            zlib->state = state = 2;
fukasawa e60969
            break;
fukasawa e60969
fukasawa e60969
         default: /* After the header bytes */
fukasawa e60969
            break;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* For some streams, perhaps only those compressed with 'superfast
fukasawa e60969
       * compression' (which results in a lot of copying) Z_BUF_ERROR can happen
fukasawa e60969
       * immediately after all output has been flushed on the next input byte.
fukasawa e60969
       * This is handled below when Z_BUF_ERROR is detected by adding an output
fukasawa e60969
       * byte.
fukasawa e60969
       */
fukasawa e60969
      zlib->z.next_in = &bIn;
fukasawa e60969
      zlib->z.avail_in = 1;
fukasawa e60969
      zlib->z.next_out = &bOut;
fukasawa e60969
      zlib->z.avail_out = 0;     /* Initially */
fukasawa e60969
fukasawa e60969
      /* Initially use Z_NO_FLUSH in an attempt to persuade zlib to look at this
fukasawa e60969
       * byte without confusing what is going on with output.
fukasawa e60969
       */
fukasawa e60969
      flush = Z_NO_FLUSH;
fukasawa e60969
      out_bytes = 0;
fukasawa e60969
fukasawa e60969
      /* NOTE: expression 3 is only evaluted on 'continue', because of the
fukasawa e60969
       * 'break' at the end of this loop below.
fukasawa e60969
       */
fukasawa e60969
      for (;endrc == ZLIB_OK;
fukasawa e60969
         flush = Z_SYNC_FLUSH,
fukasawa e60969
         zlib->z.next_out = &bOut,
fukasawa e60969
         zlib->z.avail_out = 1,
fukasawa e60969
         ++out_bytes)
fukasawa e60969
      {
fukasawa e60969
         zlib->rc = inflate(&zlib->z, flush);
fukasawa e60969
         out_bytes -= zlib->z.avail_out;
fukasawa e60969
fukasawa e60969
         switch (zlib->rc)
fukasawa e60969
         {
fukasawa e60969
            case Z_BUF_ERROR:
fukasawa e60969
               if (zlib->z.avail_out == 0)
fukasawa e60969
                  continue; /* Try another output byte. */
fukasawa e60969
fukasawa e60969
               if (zlib->z.avail_in == 0)
fukasawa e60969
                  break; /* Try another input byte */
fukasawa e60969
fukasawa e60969
               /* Both avail_out and avail_in are 1 yet zlib returned a code
fukasawa e60969
                * indicating no progress was possible.  This is unexpected.
fukasawa e60969
                */
fukasawa e60969
               zlib_message(zlib, 1/*unexpected*/);
fukasawa e60969
               endrc = ZLIB_FATAL; /* stop processing */
fukasawa e60969
               break;
fukasawa e60969
fukasawa e60969
            case Z_OK:
fukasawa e60969
               /* Zlib is supposed to have made progress: */
fukasawa e60969
               assert(zlib->z.avail_out == 0 || zlib->z.avail_in == 0);
fukasawa e60969
               continue;
fukasawa e60969
fukasawa e60969
            case Z_STREAM_END:
fukasawa e60969
               /* This is the successful end. */
fukasawa e60969
               zlib->state = 3; /* end of stream */
fukasawa e60969
               endrc = ZLIB_STREAM_END;
fukasawa e60969
               break;
fukasawa e60969
fukasawa e60969
            case Z_NEED_DICT:
fukasawa e60969
               zlib_message(zlib, 0/*stream error*/);
fukasawa e60969
               endrc = ZLIB_FATAL;
fukasawa e60969
               break;
fukasawa e60969
fukasawa e60969
            case Z_DATA_ERROR:
fukasawa e60969
               /* The too far back error can be corrected, others cannot: */
fukasawa e60969
               if (zlib->z.msg != NULL &&
fukasawa e60969
                  strcmp(zlib->z.msg, "invalid distance too far back") == 0)
fukasawa e60969
               {
fukasawa e60969
                  endrc = ZLIB_TOO_FAR_BACK;
fukasawa e60969
                  break;
fukasawa e60969
               }
fukasawa e60969
               /* FALL THROUGH */
fukasawa e60969
fukasawa e60969
            default:
fukasawa e60969
               zlib_message(zlib, 0/*stream error*/);
fukasawa e60969
               endrc = ZLIB_FATAL;
fukasawa e60969
               break;
fukasawa e60969
         } /* switch (inflate rc) */
fukasawa e60969
fukasawa e60969
         /* Control gets here when further output is not possible; endrc may
fukasawa e60969
          * still be ZLIB_OK if more input is required.
fukasawa e60969
          */
fukasawa e60969
         break;
fukasawa e60969
      } /* for (output bytes) */
fukasawa e60969
fukasawa e60969
      /* Keep a running count of output byte produced: */
fukasawa e60969
      zlib->uncompressed_digits = uarb_add32(zlib->uncompressed_bytes,
fukasawa e60969
         zlib->uncompressed_digits, out_bytes);
fukasawa e60969
fukasawa e60969
      /* Keep going, the loop will terminate when endrc is no longer set to
fukasawa e60969
       * ZLIB_OK or all the input bytes have been consumed; meanwhile keep
fukasawa e60969
       * adding input bytes.
fukasawa e60969
       */
fukasawa e60969
      assert(zlib->z.avail_in == 0 || endrc != ZLIB_OK);
fukasawa e60969
fukasawa e60969
      in_bytes += 1 - zlib->z.avail_in;
fukasawa e60969
   } /* while (input bytes) */
fukasawa e60969
fukasawa e60969
   assert(in_bytes == nbytes || endrc != ZLIB_OK);
fukasawa e60969
fukasawa e60969
   /* Update the running total of input bytes consumed */
fukasawa e60969
   zlib->compressed_digits = uarb_add32(zlib->compressed_bytes,
fukasawa e60969
      zlib->compressed_digits, in_bytes - zlib->z.avail_in);
fukasawa e60969
fukasawa e60969
   /* At the end of the stream update the chunk with the accumulated
fukasawa e60969
    * information if it is an improvement:
fukasawa e60969
    */
fukasawa e60969
   if (endrc == ZLIB_STREAM_END && zlib->window_bits < zlib->ok_bits)
fukasawa e60969
   {
fukasawa e60969
      struct chunk *chunk = zlib->chunk;
fukasawa e60969
fukasawa e60969
      chunk->uncompressed_digits = uarb_copy(chunk->uncompressed_bytes,
fukasawa e60969
         zlib->uncompressed_bytes, zlib->uncompressed_digits);
fukasawa e60969
      chunk->compressed_digits = uarb_copy(chunk->compressed_bytes,
fukasawa e60969
         zlib->compressed_bytes, zlib->compressed_digits);
fukasawa e60969
      chunk->rewrite_buffer[0] = zlib->header[0];
fukasawa e60969
      chunk->rewrite_buffer[1] = zlib->header[1];
fukasawa e60969
fukasawa e60969
      if (zlib->window_bits != zlib->file_bits || zlib->cksum)
fukasawa e60969
      {
fukasawa e60969
         /* A rewrite is required */
fukasawa e60969
         chunk->rewrite_offset = zlib->rewrite_offset;
fukasawa e60969
         chunk->rewrite_length = 2;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         chunk->rewrite_offset = 0;
fukasawa e60969
         chunk->rewrite_length = 0;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      if (in_bytes < nbytes)
fukasawa e60969
         chunk_message(chunk, "extra compressed data");
fukasawa e60969
fukasawa e60969
      zlib->extra_bytes = nbytes - in_bytes;
fukasawa e60969
      zlib->ok_bits = zlib->window_bits;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return endrc;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
zlib_run(struct zlib *zlib)
fukasawa e60969
   /* Like zlib_advance but also handles a stream of IDAT chunks. */
fukasawa e60969
{
fukasawa e60969
   /* The 'extra_bytes' field is set by zlib_advance if there is extra
fukasawa e60969
    * compressed data in the chunk it handles (if it sees Z_STREAM_END before
fukasawa e60969
    * all the input data has been used.)  This function uses the value to update
fukasawa e60969
    * the correct chunk length, so the problem should only ever be detected once
fukasawa e60969
    * for each chunk.  zlib_advance outputs the error message, though see the
fukasawa e60969
    * IDAT specific check below.
fukasawa e60969
    */
fukasawa e60969
   zlib->extra_bytes = 0;
fukasawa e60969
fukasawa e60969
   if (zlib->idat != NULL)
fukasawa e60969
   {
fukasawa e60969
      struct IDAT_list *list = zlib->idat->idat_list_head;
fukasawa e60969
      struct IDAT_list *last = zlib->idat->idat_list_tail;
fukasawa e60969
      int        skip = 0;
fukasawa e60969
fukasawa e60969
      /* 'rewrite_offset' is the offset of the LZ data within the chunk, for
fukasawa e60969
       * IDAT it should be 0:
fukasawa e60969
       */
fukasawa e60969
      assert(zlib->rewrite_offset == 0);
fukasawa e60969
fukasawa e60969
      /* Process each IDAT_list in turn; the caller has left the stream
fukasawa e60969
       * positioned at the start of the first IDAT chunk data.
fukasawa e60969
       */
fukasawa e60969
      for (;;)
fukasawa e60969
      {
fukasawa e60969
         const unsigned int count = list->count;
fukasawa e60969
         unsigned int i;
fukasawa e60969
fukasawa e60969
         for (i = 0; i
fukasawa e60969
         {
fukasawa e60969
            int rc;
fukasawa e60969
fukasawa e60969
            if (skip > 0) /* Skip CRC and next IDAT header */
fukasawa e60969
               skip_12(zlib->file);
fukasawa e60969
fukasawa e60969
            skip = 12; /* for the next time */
fukasawa e60969
fukasawa e60969
            rc = zlib_advance(zlib, list->lengths[i]);
fukasawa e60969
fukasawa e60969
            switch (rc)
fukasawa e60969
            {
fukasawa e60969
               case ZLIB_OK: /* keep going */
fukasawa e60969
                  break;
fukasawa e60969
fukasawa e60969
               case ZLIB_STREAM_END: /* stop */
fukasawa e60969
                  /* There may be extra chunks; if there are and one of them is
fukasawa e60969
                   * not zero length output the 'extra data' message.  Only do
fukasawa e60969
                   * this check if errors are being output.
fukasawa e60969
                   */
fukasawa e60969
                  if (zlib->global->errors && zlib->extra_bytes == 0)
fukasawa e60969
                  {
fukasawa e60969
                     struct IDAT_list *check = list;
fukasawa e60969
                     int j = i+1, jcount = count;
fukasawa e60969
fukasawa e60969
                     for (;;)
fukasawa e60969
                     {
fukasawa e60969
                        for (; j
fukasawa e60969
                           if (check->lengths[j] > 0)
fukasawa e60969
                           {
fukasawa e60969
                              chunk_message(zlib->chunk,
fukasawa e60969
                                 "extra compressed data");
fukasawa e60969
                              goto end_check;
fukasawa e60969
                           }
fukasawa e60969
fukasawa e60969
                        if (check == last)
fukasawa e60969
                           break;
fukasawa e60969
fukasawa e60969
                        check = check->next;
fukasawa e60969
                        jcount = check->count;
fukasawa e60969
                        j = 0;
fukasawa e60969
                     }
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
               end_check:
fukasawa e60969
                  /* Terminate the list at the current position, reducing the
fukasawa e60969
                   * length of the last IDAT too if required.
fukasawa e60969
                   */
fukasawa e60969
                  list->lengths[i] -= zlib->extra_bytes;
fukasawa e60969
                  list->count = i+1;
fukasawa e60969
                  zlib->idat->idat_list_tail = list;
fukasawa e60969
                  /* FALL THROUGH */
fukasawa e60969
fukasawa e60969
               default:
fukasawa e60969
                  return rc;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         /* At the end of the compressed data and Z_STREAM_END was not seen. */
fukasawa e60969
         if (list == last)
fukasawa e60969
            return ZLIB_OK;
fukasawa e60969
fukasawa e60969
         list = list->next;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      struct chunk *chunk = zlib->chunk;
fukasawa e60969
      int rc;
fukasawa e60969
fukasawa e60969
      assert(zlib->rewrite_offset < chunk->chunk_length);
fukasawa e60969
fukasawa e60969
      rc = zlib_advance(zlib, chunk->chunk_length - zlib->rewrite_offset);
fukasawa e60969
fukasawa e60969
      /* The extra bytes in the chunk are handled now by adjusting the chunk
fukasawa e60969
       * length to exclude them; the zlib data is always stored at the end of
fukasawa e60969
       * the PNG chunk (although clearly this is not necessary.)  zlib_advance
fukasawa e60969
       * has already output a warning message.
fukasawa e60969
       */
fukasawa e60969
      chunk->chunk_length -= zlib->extra_bytes;
fukasawa e60969
      return rc;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int /* global function; not a member function */
fukasawa e60969
zlib_check(struct file *file, png_uint_32 offset)
fukasawa e60969
   /* Check the stream of zlib compressed data in either idat (if given) or (if
fukasawa e60969
    * not) chunk.  In fact it is zlib_run that handles the difference in reading
fukasawa e60969
    * a single chunk and a list of IDAT chunks.
fukasawa e60969
    *
fukasawa e60969
    * In either case the input file must be positioned at the first byte of zlib
fukasawa e60969
    * compressed data (the first header byte).
fukasawa e60969
    *
fukasawa e60969
    * The return value is true on success, including the case where the zlib
fukasawa e60969
    * header may need to be rewritten, and false on an unrecoverable error.
fukasawa e60969
    *
fukasawa e60969
    * In the case of IDAT chunks 'offset' should be 0.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   fpos_t start_pos;
fukasawa e60969
   struct zlib zlib;
fukasawa e60969
fukasawa e60969
   /* Record the start of the LZ data to allow a re-read. */
fukasawa e60969
   file_getpos(file, &start_pos);
fukasawa e60969
fukasawa e60969
   /* First test the existing (file) window bits: */
fukasawa e60969
   if (zlib_init(&zlib, file->idat, file->chunk, 0/*window bits*/, offset))
fukasawa e60969
   {
fukasawa e60969
      int min_bits, max_bits, rc;
fukasawa e60969
fukasawa e60969
      /* The first run using the existing window bits. */
fukasawa e60969
      rc = zlib_run(&zlib);
fukasawa e60969
fukasawa e60969
      switch (rc)
fukasawa e60969
      {
fukasawa e60969
         case ZLIB_TOO_FAR_BACK:
fukasawa e60969
            /* too far back error */
fukasawa e60969
            file->status_code |= TOO_FAR_BACK;
fukasawa e60969
            min_bits = zlib.window_bits + 1;
fukasawa e60969
            max_bits = 15;
fukasawa e60969
            break;
fukasawa e60969
fukasawa e60969
         case ZLIB_STREAM_END:
fukasawa e60969
            if (!zlib.global->optimize_zlib &&
fukasawa e60969
               zlib.window_bits == zlib.file_bits && !zlib.cksum)
fukasawa e60969
            {
fukasawa e60969
               /* The trivial case where the stream is ok and optimization was
fukasawa e60969
                * not requested.
fukasawa e60969
                */
fukasawa e60969
               zlib_end(&zlib);
fukasawa e60969
               return 1;
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            max_bits = max_window_bits(zlib.uncompressed_bytes,
fukasawa e60969
               zlib.uncompressed_digits);
fukasawa e60969
            if (zlib.ok_bits < max_bits)
fukasawa e60969
               max_bits = zlib.ok_bits;
fukasawa e60969
            min_bits = 8;
fukasawa e60969
fukasawa e60969
            /* cksum is set if there is an error in the zlib header checksum
fukasawa e60969
             * calculation in the original file (and this may be the only reason
fukasawa e60969
             * a rewrite is required).  We can't rely on the file window bits in
fukasawa e60969
             * this case, so do the optimization anyway.
fukasawa e60969
             */
fukasawa e60969
            if (zlib.cksum)
fukasawa e60969
               chunk_message(zlib.chunk, "zlib checkum");
fukasawa e60969
            break;
fukasawa e60969
fukasawa e60969
fukasawa e60969
         case ZLIB_OK:
fukasawa e60969
            /* Truncated stream; unrecoverable, gets converted to ZLIB_FATAL */
fukasawa e60969
            zlib.z.msg = PNGZ_MSG_CAST("[truncated]");
fukasawa e60969
            zlib_message(&zlib, 0/*expected*/);
fukasawa e60969
            /* FALL THROUGH */
fukasawa e60969
fukasawa e60969
         default:
fukasawa e60969
            /* Unrecoverable error; skip the chunk; a zlib_message has already
fukasawa e60969
             * been output.
fukasawa e60969
             */
fukasawa e60969
            zlib_end(&zlib);
fukasawa e60969
            return 0;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* Optimize window bits or fix a too-far-back error.  min_bits and
fukasawa e60969
       * max_bits have been set appropriately, ok_bits records the bit value
fukasawa e60969
       * known to work.
fukasawa e60969
       */
fukasawa e60969
      while (min_bits < max_bits || max_bits < zlib.ok_bits/*if 16*/)
fukasawa e60969
      {
fukasawa e60969
         int test_bits = (min_bits + max_bits) >> 1;
fukasawa e60969
fukasawa e60969
         if (zlib_reset(&zlib, test_bits))
fukasawa e60969
         {
fukasawa e60969
            file_setpos(file, &start_pos);
fukasawa e60969
            rc = zlib_run(&zlib);
fukasawa e60969
fukasawa e60969
            switch (rc)
fukasawa e60969
            {
fukasawa e60969
               case ZLIB_TOO_FAR_BACK:
fukasawa e60969
                  min_bits = test_bits+1;
fukasawa e60969
                  if (min_bits > max_bits)
fukasawa e60969
                  {
fukasawa e60969
                     /* This happens when the stream really is damaged and it
fukasawa e60969
                      * contains a distance code that addresses bytes before
fukasawa e60969
                      * the start of the uncompressed data.
fukasawa e60969
                      */
fukasawa e60969
                     assert(test_bits == 15);
fukasawa e60969
fukasawa e60969
                     /* Output the error that wasn't output before: */
fukasawa e60969
                     if (zlib.z.msg == NULL)
fukasawa e60969
                        zlib.z.msg = PNGZ_MSG_CAST(
fukasawa e60969
                           "invalid distance too far back");
fukasawa e60969
                     zlib_message(&zlib, 0/*stream error*/);
fukasawa e60969
                     zlib_end(&zlib);
fukasawa e60969
                     return 0;
fukasawa e60969
                  }
fukasawa e60969
                  break;
fukasawa e60969
fukasawa e60969
               case ZLIB_STREAM_END: /* success */
fukasawa e60969
                  max_bits = test_bits;
fukasawa e60969
                  break;
fukasawa e60969
fukasawa e60969
               default:
fukasawa e60969
                  /* A fatal error; this happens if a too-far-back error was
fukasawa e60969
                   * hiding a more serious error, zlib_advance has already
fukasawa e60969
                   * output a zlib_message.
fukasawa e60969
                   */
fukasawa e60969
                  zlib_end(&zlib);
fukasawa e60969
                  return 0;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         else /* inflateReset2 failed */
fukasawa e60969
         {
fukasawa e60969
            zlib_end(&zlib);
fukasawa e60969
            return 0;
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* The loop guarantees this */
fukasawa e60969
      assert(zlib.ok_bits == max_bits);
fukasawa e60969
      zlib_end(&zlib);
fukasawa e60969
      return 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else /* zlib initialization failed - skip the chunk */
fukasawa e60969
   {
fukasawa e60969
      zlib_end(&zlib);
fukasawa e60969
      return 0;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/***************************** LIBPNG CALLBACKS *******************************/
fukasawa e60969
/* The strategy here is to run a regular libpng PNG file read but examine the
fukasawa e60969
 * input data (from the file) before passing it to libpng so as to be aware of
fukasawa e60969
 * the state we expect libpng to be in.  Warning and error callbacks are also
fukasawa e60969
 * intercepted so that they can be quieted and interpreted.  Interpretation
fukasawa e60969
 * depends on a somewhat risky string match for known error messages; let us
fukasawa e60969
 * hope that this can be fixed in the next version of libpng.
fukasawa e60969
 *
fukasawa e60969
 * The control structure is pointed to by the libpng error pointer.  It contains
fukasawa e60969
 * that set of structures which must persist across multiple read callbacks,
fukasawa e60969
 * which is pretty much everything except the 'zlib' control structure.
fukasawa e60969
 *
fukasawa e60969
 * The file structure is instantiated in the caller of the per-file routine, but
fukasawa e60969
 * the per-file routine contains the chunk and IDAT control structures.
fukasawa e60969
 */
fukasawa e60969
/* The three routines read_chunk, process_chunk and sync_stream can only be
fukasawa e60969
 * called via a call to read_chunk and only exit at a return from process_chunk.
fukasawa e60969
 * These routines could have been written as one confusing large routine,
fukasawa e60969
 * instead this code relies on the compiler to do tail call elimination.  The
fukasawa e60969
 * possible calls are as follows:
fukasawa e60969
 *
fukasawa e60969
 * read_chunk
fukasawa e60969
 *    -> sync_stream
fukasawa e60969
 *       -> process_chunk
fukasawa e60969
 *    -> process_chunk
fukasawa e60969
 *       -> read_chunk
fukasawa e60969
 *       returns
fukasawa e60969
 */
fukasawa e60969
static void read_chunk(struct file *file);
fukasawa e60969
static void
fukasawa e60969
process_chunk(struct file *file, png_uint_32 file_crc, png_uint_32 next_length,
fukasawa e60969
   png_uint_32 next_type)
fukasawa e60969
   /* Called when the chunk data has been read, next_length and next_type
fukasawa e60969
    * will be set for the next chunk (or 0 if this is IEND).
fukasawa e60969
    *
fukasawa e60969
    * When this routine returns, chunk_length and chunk_type will be set for the
fukasawa e60969
    * next chunk to write because if a chunk is skipped this return calls back
fukasawa e60969
    * to read_chunk.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   const png_uint_32 type = file->type;
fukasawa e60969
fukasawa e60969
   if (file->global->verbose > 1)
fukasawa e60969
   {
fukasawa e60969
      fputs("  ", stderr);
fukasawa e60969
      type_name(file->type, stderr);
fukasawa e60969
      fprintf(stderr, " %lu 0x%.8x 0x%.8x\n", (unsigned long)file->length,
fukasawa e60969
         file->crc ^ 0xffffffff, file_crc);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* The basic structure seems correct but the CRC may not match, in this
fukasawa e60969
    * case assume that it is simply a bad CRC, either wrongly calculated or
fukasawa e60969
    * because of damaged stream data.
fukasawa e60969
    */
fukasawa e60969
   if ((file->crc ^ 0xffffffff) != file_crc)
fukasawa e60969
   {
fukasawa e60969
      /* The behavior is set by the 'skip' setting; if it is anything other
fukasawa e60969
       * than SKIP_BAD_CRC ignore the bad CRC and return the chunk, with a
fukasawa e60969
       * corrected CRC and possibly processed, to libpng.  Otherwise skip the
fukasawa e60969
       * chunk, which will result in a fatal error if the chunk is critical.
fukasawa e60969
       */
fukasawa e60969
      file->status_code |= CRC_ERROR;
fukasawa e60969
fukasawa e60969
      /* Ignore the bad CRC  */
fukasawa e60969
      if (file->global->skip != SKIP_BAD_CRC)
fukasawa e60969
         type_message(file, type, "bad CRC");
fukasawa e60969
fukasawa e60969
      /* This will cause an IEND with a bad CRC to stop */
fukasawa e60969
      else if (CRITICAL(type))
fukasawa e60969
         stop(file, READ_ERROR_CODE, "bad CRC in critical chunk");
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         type_message(file, type, "skipped: bad CRC");
fukasawa e60969
fukasawa e60969
         /* NOTE: this cannot be reached for IEND because it is critical. */
fukasawa e60969
         goto skip_chunk;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Check for other 'skip' cases and handle these; these only apply to
fukasawa e60969
    * ancillary chunks (and not tRNS, which should probably have been a critical
fukasawa e60969
    * chunk.)
fukasawa e60969
    */
fukasawa e60969
   if (skip_chunk_type(file->global, type))
fukasawa e60969
      goto skip_chunk;
fukasawa e60969
fukasawa e60969
   /* The chunk may still be skipped if problems are detected in the LZ data,
fukasawa e60969
    * however the LZ data check requires a chunk.  Handle this by instantiating
fukasawa e60969
    * a chunk unless an IDAT is already instantiated (IDAT control structures
fukasawa e60969
    * instantiate their own chunk.)
fukasawa e60969
    */
fukasawa e60969
   if (type != png_IDAT)
fukasawa e60969
      file->alloc(file, 0/*chunk*/);
fukasawa e60969
fukasawa e60969
   else if (file->idat == NULL)
fukasawa e60969
      file->alloc(file, 1/*IDAT*/);
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      /* The chunk length must be updated for process_IDAT */
fukasawa e60969
      assert(file->chunk != NULL);
fukasawa e60969
      assert(file->chunk->chunk_type == png_IDAT);
fukasawa e60969
      file->chunk->chunk_length = file->length;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Record the 'next' information too, now that the original values for
fukasawa e60969
    * this chunk have been copied.  Notice that the IDAT chunks only make a
fukasawa e60969
    * copy of the position of the first chunk, this is fine - process_IDAT does
fukasawa e60969
    * not need the position of this chunk.
fukasawa e60969
    */
fukasawa e60969
   file->length = next_length;
fukasawa e60969
   file->type = next_type;
fukasawa e60969
   getpos(file);
fukasawa e60969
fukasawa e60969
   /* Do per-type processing, note that if this code does not return from the
fukasawa e60969
    * function the chunk will be skipped.  The rewrite is cancelled here so that
fukasawa e60969
    * it can be set in the per-chunk processing.
fukasawa e60969
    */
fukasawa e60969
   file->chunk->rewrite_length = 0;
fukasawa e60969
   file->chunk->rewrite_offset = 0;
fukasawa e60969
   switch (type)
fukasawa e60969
   {
fukasawa e60969
      default:
fukasawa e60969
         return;
fukasawa e60969
fukasawa e60969
      case png_IHDR:
fukasawa e60969
         /* Read this now and update the control structure with the information
fukasawa e60969
          * it contains.  The header is validated completely to ensure this is a
fukasawa e60969
          * PNG.
fukasawa e60969
          */
fukasawa e60969
         {
fukasawa e60969
            struct chunk *chunk = file->chunk;
fukasawa e60969
fukasawa e60969
            if (chunk->chunk_length != 13)
fukasawa e60969
               stop_invalid(file, "IHDR length");
fukasawa e60969
fukasawa e60969
            /* Read all the IHDR information and validate it. */
fukasawa e60969
            setpos(chunk);
fukasawa e60969
            file->width = reread_4(file);
fukasawa e60969
            file->height = reread_4(file);
fukasawa e60969
            file->bit_depth = reread_byte(file);
fukasawa e60969
            file->color_type = reread_byte(file);
fukasawa e60969
            file->compression_method = reread_byte(file);
fukasawa e60969
            file->filter_method = reread_byte(file);
fukasawa e60969
            file->interlace_method = reread_byte(file);
fukasawa e60969
fukasawa e60969
            /* This validates all the fields, and calls stop_invalid if
fukasawa e60969
             * there is a problem.
fukasawa e60969
             */
fukasawa e60969
            calc_image_size(file);
fukasawa e60969
         }
fukasawa e60969
         return;
fukasawa e60969
fukasawa e60969
         /* Ancillary chunks that require further processing: */
fukasawa e60969
      case png_zTXt: case png_iCCP:
fukasawa e60969
         if (process_zTXt_iCCP(file))
fukasawa e60969
            return;
fukasawa e60969
         chunk_end(&file->chunk);
fukasawa e60969
         file_setpos(file, &file->data_pos);
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case png_iTXt:
fukasawa e60969
         if (process_iTXt(file))
fukasawa e60969
            return;
fukasawa e60969
         chunk_end(&file->chunk);
fukasawa e60969
         file_setpos(file, &file->data_pos);
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case png_IDAT:
fukasawa e60969
         if (process_IDAT(file))
fukasawa e60969
            return;
fukasawa e60969
         /* First pass: */
fukasawa e60969
         assert(next_type == png_IDAT);
fukasawa e60969
         break;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Control reaches this point if the chunk must be skipped.  For chunks other
fukasawa e60969
    * than IDAT this means that the zlib compressed data is fatally damanged and
fukasawa e60969
    * the chunk will not be passed to libpng.  For IDAT it means that the end of
fukasawa e60969
    * the IDAT stream has not yet been reached and we must handle the next
fukasawa e60969
    * (IDAT) chunk.  If the LZ data in an IDAT stream cannot be read 'stop' must
fukasawa e60969
    * be used to halt parsing of the PNG.
fukasawa e60969
    */
fukasawa e60969
   read_chunk(file);
fukasawa e60969
   return;
fukasawa e60969
fukasawa e60969
   /* This is the generic code to skip the current chunk; simply jump to the
fukasawa e60969
    * next one.
fukasawa e60969
    */
fukasawa e60969
skip_chunk:
fukasawa e60969
   file->length = next_length;
fukasawa e60969
   file->type = next_type;
fukasawa e60969
   getpos(file);
fukasawa e60969
   read_chunk(file);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
get32(png_bytep buffer, int offset)
fukasawa e60969
   /* Read a 32-bit value from an 8-byte circular buffer (used only below).
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   return
fukasawa e60969
      (buffer[ offset    & 7] << 24) +
fukasawa e60969
      (buffer[(offset+1) & 7] << 16) +
fukasawa e60969
      (buffer[(offset+2) & 7] <<  8) +
fukasawa e60969
      (buffer[(offset+3) & 7]      );
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
sync_stream(struct file *file)
fukasawa e60969
   /* The stream seems to be messed up, attempt to resync from the current chunk
fukasawa e60969
    * header.  Executes stop on a fatal error, otherwise calls process_chunk.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_uint_32 file_crc;
fukasawa e60969
fukasawa e60969
   file->status_code |= STREAM_ERROR;
fukasawa e60969
fukasawa e60969
   if (file->global->verbose)
fukasawa e60969
   {
fukasawa e60969
      fputs(" SYNC ", stderr);
fukasawa e60969
      type_name(file->type, stderr);
fukasawa e60969
      putc('\n', stderr);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Return to the start of the chunk data */
fukasawa e60969
   file_setpos(file, &file->data_pos);
fukasawa e60969
   file->read_count = 8;
fukasawa e60969
fukasawa e60969
   if (read_4(file, &file_crc) == 4) /* else completely truncated */
fukasawa e60969
   {
fukasawa e60969
      /* Ignore the recorded chunk length, proceed through the data looking for
fukasawa e60969
       * a leading sequence of bytes that match the CRC in the following four
fukasawa e60969
       * bytes.  Each time a match is found check the next 8 bytes for a valid
fukasawa e60969
       * length, chunk-type pair.
fukasawa e60969
       */
fukasawa e60969
      png_uint_32 length;
fukasawa e60969
      png_uint_32 type = file->type;
fukasawa e60969
      png_uint_32 crc = crc_init_4(type);
fukasawa e60969
      png_byte buffer[8];
fukasawa e60969
      unsigned int nread = 0, nused = 0;
fukasawa e60969
fukasawa e60969
      for (length=0; length <= 0x7fffffff; ++length)
fukasawa e60969
      {
fukasawa e60969
         int ch;
fukasawa e60969
fukasawa e60969
         if ((crc ^ 0xffffffff) == file_crc)
fukasawa e60969
         {
fukasawa e60969
            /* A match on the CRC; for IEND this is sufficient, but for anything
fukasawa e60969
             * else expect a following chunk header.
fukasawa e60969
             */
fukasawa e60969
            if (type == png_IEND)
fukasawa e60969
            {
fukasawa e60969
               file->length = length;
fukasawa e60969
               process_chunk(file, file_crc, 0, 0);
fukasawa e60969
               return;
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            else
fukasawa e60969
            {
fukasawa e60969
               /* Need 8 bytes */
fukasawa e60969
               while (nread < 8+nused)
fukasawa e60969
               {
fukasawa e60969
                  ch = read_byte(file);
fukasawa e60969
                  if (ch == EOF)
fukasawa e60969
                     goto truncated;
fukasawa e60969
                  buffer[(nread++) & 7] = (png_byte)ch;
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               /* Prevent overflow */
fukasawa e60969
               nread -= nused & ~7;
fukasawa e60969
               nused -= nused & ~7; /* or, nused &= 7 ;-) */
fukasawa e60969
fukasawa e60969
               /* Examine the 8 bytes for a valid chunk header. */
fukasawa e60969
               {
fukasawa e60969
                  png_uint_32 next_length = get32(buffer, nused);
fukasawa e60969
fukasawa e60969
                  if (next_length < 0x7fffffff)
fukasawa e60969
                  {
fukasawa e60969
                     png_uint_32 next_type = get32(buffer, nused+4);
fukasawa e60969
fukasawa e60969
                     if (chunk_type_valid(next_type))
fukasawa e60969
                     {
fukasawa e60969
                        file->read_count -= 8;
fukasawa e60969
                        process_chunk(file, file_crc, next_length, next_type);
fukasawa e60969
                        return;
fukasawa e60969
                     }
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  /* Not valid, keep going. */
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         /* This catches up with the circular buffer which gets filled above
fukasawa e60969
          * while checking a chunk header.  This code is slightly tricky - if
fukasawa e60969
          * the chunk_type is IEND the buffer will never be used, if it is not
fukasawa e60969
          * the code will always read ahead exactly 8 bytes and pass this on to
fukasawa e60969
          * process_chunk.  So the invariant that IEND leaves the file position
fukasawa e60969
          * after the IEND CRC and other chunk leave it after the *next* chunk
fukasawa e60969
          * header is not broken.
fukasawa e60969
          */
fukasawa e60969
         if (nread <= nused)
fukasawa e60969
         {
fukasawa e60969
            ch = read_byte(file);
fukasawa e60969
fukasawa e60969
            if (ch == EOF)
fukasawa e60969
               goto truncated;
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         else
fukasawa e60969
            ch = buffer[(++nused) & 7];
fukasawa e60969
fukasawa e60969
         crc = crc_one_byte(crc, file_crc >> 24);
fukasawa e60969
         file_crc = (file_crc << 8) + ch;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* Control gets to here if when 0x7fffffff bytes (plus 8) have been read,
fukasawa e60969
       * ok, treat this as a damaged stream too:
fukasawa e60969
       */
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
truncated:
fukasawa e60969
   stop(file, READ_ERROR_CODE, "damaged PNG stream");
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
read_chunk(struct file *file)
fukasawa e60969
   /* On entry file::data_pos must be set to the position of the first byte
fukasawa e60969
    * of the chunk data *and* the input file must be at this position.  This
fukasawa e60969
    * routine (via process_chunk) instantiates a chunk or IDAT control structure
fukasawa e60969
    * based on file::length and file::type and also resets these fields and
fukasawa e60969
    * file::data_pos for the chunk after this one.  For an IDAT chunk the whole
fukasawa e60969
    * stream of IDATs will be read, until something other than an IDAT is
fukasawa e60969
    * encountered, and the file fields will be set for the chunk after the end
fukasawa e60969
    * of the stream of IDATs.
fukasawa e60969
    *
fukasawa e60969
    * For IEND the file::type field will be set to 0, and nothing beyond the end
fukasawa e60969
    * of the IEND chunk will have been read.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_uint_32 length = file->length;
fukasawa e60969
   png_uint_32 type = file->type;
fukasawa e60969
fukasawa e60969
   /* After IEND file::type is set to 0, if libpng attempts to read
fukasawa e60969
    * more data at this point this is a bug in libpng.
fukasawa e60969
    */
fukasawa e60969
   if (type == 0)
fukasawa e60969
      stop(file, UNEXPECTED_ERROR_CODE, "read beyond IEND");
fukasawa e60969
fukasawa e60969
   if (file->global->verbose > 2)
fukasawa e60969
   {
fukasawa e60969
      fputs("   ", stderr);
fukasawa e60969
      type_name(type, stderr);
fukasawa e60969
      fprintf(stderr, " %lu\n", (unsigned long)length);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Start the read_crc calculation with the chunk type, then read to the end
fukasawa e60969
    * of the chunk data (without processing it in any way) to check that it is
fukasawa e60969
    * all there and calculate the CRC.
fukasawa e60969
    */
fukasawa e60969
   file->crc = crc_init_4(type);
fukasawa e60969
   if (crc_read_many(file, length)) /* else it was truncated */
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 file_crc; /* CRC read from file */
fukasawa e60969
      unsigned int nread = read_4(file, &file_crc);
fukasawa e60969
fukasawa e60969
      if (nread == 4)
fukasawa e60969
      {
fukasawa e60969
         if (type != png_IEND) /* do not read beyond IEND */
fukasawa e60969
         {
fukasawa e60969
            png_uint_32 next_length;
fukasawa e60969
fukasawa e60969
            nread += read_4(file, &next_length);
fukasawa e60969
            if (nread == 8 && next_length <= 0x7fffffff)
fukasawa e60969
            {
fukasawa e60969
               png_uint_32 next_type;
fukasawa e60969
fukasawa e60969
               nread += read_4(file, &next_type);
fukasawa e60969
fukasawa e60969
               if (nread == 12 && chunk_type_valid(next_type))
fukasawa e60969
               {
fukasawa e60969
                  /* Adjust the read count back to the correct value for this
fukasawa e60969
                   * chunk.
fukasawa e60969
                   */
fukasawa e60969
                  file->read_count -= 8;
fukasawa e60969
                  process_chunk(file, file_crc, next_length, next_type);
fukasawa e60969
                  return;
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         else /* IEND */
fukasawa e60969
         {
fukasawa e60969
            process_chunk(file, file_crc, 0, 0);
fukasawa e60969
            return;
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Control gets to here if the the stream seems invalid or damaged in some
fukasawa e60969
    * way.  Either there was a problem reading all the expected data (this
fukasawa e60969
    * chunk's data, its CRC and the length and type of the next chunk) or the
fukasawa e60969
    * next chunk length/type are invalid.  Notice that the cases that end up
fukasawa e60969
    * here all correspond to cases that would otherwise terminate the read of
fukasawa e60969
    * the PNG file.
fukasawa e60969
    */
fukasawa e60969
   sync_stream(file);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* This returns a file* from a png_struct in an implementation specific way. */
fukasawa e60969
static struct file *get_control(png_const_structrp png_ptr);
fukasawa e60969
fukasawa e60969
static void PNGCBAPI
fukasawa e60969
error_handler(png_structp png_ptr, png_const_charp message)
fukasawa e60969
{
fukasawa e60969
   stop(get_control(png_ptr),  LIBPNG_ERROR_CODE, message);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void PNGCBAPI
fukasawa e60969
warning_handler(png_structp png_ptr, png_const_charp message)
fukasawa e60969
{
fukasawa e60969
   struct file *file = get_control(png_ptr);
fukasawa e60969
fukasawa e60969
   if (file->global->warnings)
fukasawa e60969
      emit_error(file, LIBPNG_WARNING_CODE, message);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Read callback - this is where the work gets done to check the stream before
fukasawa e60969
 * passing it to libpng
fukasawa e60969
 */
fukasawa e60969
static void PNGCBAPI
fukasawa e60969
read_callback(png_structp png_ptr, png_bytep buffer, size_t count)
fukasawa e60969
   /* Return 'count' bytes to libpng in 'buffer' */
fukasawa e60969
{
fukasawa e60969
   struct file *file = get_control(png_ptr);
fukasawa e60969
   png_uint_32 type, length; /* For the chunk be *WRITTEN* */
fukasawa e60969
   struct chunk *chunk;
fukasawa e60969
fukasawa e60969
   /* libpng should always ask for at least one byte */
fukasawa e60969
   if (count == 0)
fukasawa e60969
      stop(file, UNEXPECTED_ERROR_CODE, "read callback for 0 bytes");
fukasawa e60969
fukasawa e60969
   /* The callback always reads ahead by 8 bytes - the signature or chunk header
fukasawa e60969
    * - these bytes are stored in chunk_length and chunk_type.  This block is
fukasawa e60969
    * executed once for the signature and once for the first chunk right at the
fukasawa e60969
    * start.
fukasawa e60969
    */
fukasawa e60969
   if (file->read_count < 8)
fukasawa e60969
   {
fukasawa e60969
      assert(file->read_count == 0);
fukasawa e60969
      assert((file->status_code & TRUNCATED) == 0);
fukasawa e60969
fukasawa e60969
      (void)read_4(file, &file->length);
fukasawa e60969
fukasawa e60969
      if (file->read_count == 4)
fukasawa e60969
         (void)read_4(file, &file->type);
fukasawa e60969
fukasawa e60969
      if (file->read_count < 8)
fukasawa e60969
      {
fukasawa e60969
         assert((file->status_code & TRUNCATED) != 0);
fukasawa e60969
         stop(file, READ_ERROR_CODE, "not a PNG (too short)");
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      if (file->state == STATE_SIGNATURE)
fukasawa e60969
      {
fukasawa e60969
         if (file->length != sig1 || file->type != sig2)
fukasawa e60969
            stop(file, LIBPNG_ERROR_CODE, "not a PNG (signature)");
fukasawa e60969
fukasawa e60969
         /* Else write it (this is the initialization of write_count, prior to
fukasawa e60969
          * this it contains CLEAR garbage.)
fukasawa e60969
          */
fukasawa e60969
         file->write_count = 0;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         assert(file->state == STATE_CHUNKS);
fukasawa e60969
fukasawa e60969
         /* The first chunk must be a well formed IHDR (this could be relaxed to
fukasawa e60969
          * use the checks in process_chunk, but that seems unnecessary.)
fukasawa e60969
          */
fukasawa e60969
         if (file->length != 13 || file->type != png_IHDR)
fukasawa e60969
            stop(file, LIBPNG_ERROR_CODE, "not a PNG (IHDR)");
fukasawa e60969
fukasawa e60969
         /* The position of the data must be stored too */
fukasawa e60969
         getpos(file);
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Retrieve previous state (because the read callbacks are made pretty much
fukasawa e60969
    * byte-by-byte in the sequential reader prior to 1.7).
fukasawa e60969
    */
fukasawa e60969
   chunk = file->chunk;
fukasawa e60969
fukasawa e60969
   if (chunk != NULL)
fukasawa e60969
   {
fukasawa e60969
      length = chunk->chunk_length;
fukasawa e60969
      type = chunk->chunk_type;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      /* This is the signature case; for IDAT and other chunks these values will
fukasawa e60969
       * be overwritten when read_chunk is called below.
fukasawa e60969
       */
fukasawa e60969
      length = file->length;
fukasawa e60969
      type = file->type;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   do
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 b;
fukasawa e60969
fukasawa e60969
      /* Complete the read of a chunk; as a side effect this also instantiates
fukasawa e60969
       * a chunk control structure and sets the file length/type/data_pos fields
fukasawa e60969
       * for the *NEXT* chunk header.
fukasawa e60969
       *
fukasawa e60969
       * NOTE: at an IDAT any following IDAT chunks will also be read and the
fukasawa e60969
       * next_ fields will refer to the chunk after the last IDAT.
fukasawa e60969
       *
fukasawa e60969
       * NOTE: read_chunk only returns when it has read a chunk that must now be
fukasawa e60969
       * written.
fukasawa e60969
       */
fukasawa e60969
      if (file->state != STATE_SIGNATURE && chunk == NULL)
fukasawa e60969
      {
fukasawa e60969
         assert(file->read_count == 8);
fukasawa e60969
         assert(file->idat == NULL);
fukasawa e60969
         read_chunk(file);
fukasawa e60969
         chunk = file->chunk;
fukasawa e60969
         assert(chunk != NULL);
fukasawa e60969
fukasawa e60969
         /* Do the initialization that was not done before. */
fukasawa e60969
         length = chunk->chunk_length;
fukasawa e60969
         type = chunk->chunk_type;
fukasawa e60969
fukasawa e60969
         /* And start writing the new chunk. */
fukasawa e60969
         file->write_count = 0;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* The chunk_ fields describe a chunk that must be written, or hold the
fukasawa e60969
       * signature.  Write the header first.  In the signature case this
fukasawa e60969
       * rewrites the signature.
fukasawa e60969
       */
fukasawa e60969
      switch (file->write_count)
fukasawa e60969
      {
fukasawa e60969
         case 0: b = length >> 24; break;
fukasawa e60969
         case 1: b = length >> 16; break;
fukasawa e60969
         case 2: b = length >>  8; break;
fukasawa e60969
         case 3: b = length      ; break;
fukasawa e60969
fukasawa e60969
         case 4: b = type >> 24; break;
fukasawa e60969
         case 5: b = type >> 16; break;
fukasawa e60969
         case 6: b = type >>  8; break;
fukasawa e60969
         case 7: b = type      ; break;
fukasawa e60969
fukasawa e60969
         case 8:
fukasawa e60969
            /* The header has been written.  If this is really the signature
fukasawa e60969
             * that's all that is required and we can go to normal chunk
fukasawa e60969
             * processing.
fukasawa e60969
             */
fukasawa e60969
            if (file->state == STATE_SIGNATURE)
fukasawa e60969
            {
fukasawa e60969
               /* The signature has been written, the tail call to read_callback
fukasawa e60969
                * below (it's just a goto to the start with a decent compiler)
fukasawa e60969
                * will read the IHDR header ahead and validate it.
fukasawa e60969
                */
fukasawa e60969
               assert(length == sig1 && type == sig2);
fukasawa e60969
               file->read_count = 0; /* Forces a header read */
fukasawa e60969
               file->state = STATE_CHUNKS; /* IHDR: checked above */
fukasawa e60969
               read_callback(png_ptr, buffer, count);
fukasawa e60969
               return;
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            else
fukasawa e60969
            {
fukasawa e60969
               assert(chunk != NULL);
fukasawa e60969
fukasawa e60969
               /* Set up for write, notice that repositioning the input stream
fukasawa e60969
                * is only necessary if something is to be read from it.  Also
fukasawa e60969
                * notice that for the IDAT stream this must only happen once -
fukasawa e60969
                * on the first IDAT - to get back to the start of the list and
fukasawa e60969
                * this is done inside process_IDAT:
fukasawa e60969
                */
fukasawa e60969
               chunk->write_crc = crc_init_4(type);
fukasawa e60969
               if (file->state != STATE_IDAT && length > 0)
fukasawa e60969
                  setpos(chunk);
fukasawa e60969
            }
fukasawa e60969
            /* FALL THROUGH */
fukasawa e60969
fukasawa e60969
         default:
fukasawa e60969
            assert(chunk != NULL);
fukasawa e60969
fukasawa e60969
            /* NOTE: the arithmetic below overflows and gives a large positive
fukasawa e60969
             * png_uint_32 value until the whole chunk data has been written.
fukasawa e60969
             */
fukasawa e60969
            switch (file->write_count - length)
fukasawa e60969
            {
fukasawa e60969
               /* Write the chunk data, normally this just comes from
fukasawa e60969
                * the file.  The only exception is for that part of a
fukasawa e60969
                * chunk which is zlib data and which must be rewritten,
fukasawa e60969
                * and IDAT chunks which can be completely
fukasawa e60969
                * reconstructed.
fukasawa e60969
                */
fukasawa e60969
               default:
fukasawa e60969
                  if (file->state == STATE_IDAT)
fukasawa e60969
                  {
fukasawa e60969
                     struct IDAT *idat = file->idat;
fukasawa e60969
fukasawa e60969
                     assert(idat != NULL);
fukasawa e60969
fukasawa e60969
                     /* Read an IDAT byte from the input stream of IDAT chunks.
fukasawa e60969
                      * Because the IDAT stream can be re-chunked this stream is
fukasawa e60969
                      * held in the struct IDAT members.  The chunk members, in
fukasawa e60969
                      * particular chunk_length (and therefore the length local)
fukasawa e60969
                      * refer to the output chunk.
fukasawa e60969
                      */
fukasawa e60969
                     while (idat->idat_index >= idat->idat_length)
fukasawa e60969
                     {
fukasawa e60969
                        /* Advance one chunk */
fukasawa e60969
                        struct IDAT_list *cur = idat->idat_cur;
fukasawa e60969
fukasawa e60969
                        assert(idat->idat_index == idat->idat_length);
fukasawa e60969
                        assert(cur != NULL && cur->count > 0);
fukasawa e60969
fukasawa e60969
                        /* NOTE: IDAT_list::count here, not IDAT_list::length */
fukasawa e60969
                        if (++(idat->idat_count) >= cur->count)
fukasawa e60969
                        {
fukasawa e60969
                           assert(idat->idat_count == cur->count);
fukasawa e60969
fukasawa e60969
                           /* Move on to the next IDAT_list: */
fukasawa e60969
                           cur = cur->next;
fukasawa e60969
fukasawa e60969
                           /* This is an internal error - read beyond the end of
fukasawa e60969
                            * the pre-calculated stream.
fukasawa e60969
                            */
fukasawa e60969
                           if (cur == NULL || cur->count == 0)
fukasawa e60969
                              stop(file, UNEXPECTED_ERROR_CODE,
fukasawa e60969
                                 "read beyond end of IDAT");
fukasawa e60969
fukasawa e60969
                           idat->idat_count = 0;
fukasawa e60969
                           idat->idat_cur = cur;
fukasawa e60969
                        }
fukasawa e60969
fukasawa e60969
                        idat->idat_index = 0;
fukasawa e60969
                        /* Zero length IDAT chunks are permitted, so the length
fukasawa e60969
                         * here may be 0.
fukasawa e60969
                         */
fukasawa e60969
                        idat->idat_length = cur->lengths[idat->idat_count];
fukasawa e60969
fukasawa e60969
                        /* And skip 12 bytes to the next chunk data */
fukasawa e60969
                        skip_12(file);
fukasawa e60969
                     }
fukasawa e60969
fukasawa e60969
                     /* The index is always that of the next byte, the rest of
fukasawa e60969
                      * the information is always the current IDAT chunk and the
fukasawa e60969
                      * current list.
fukasawa e60969
                      */
fukasawa e60969
                     ++(idat->idat_index);
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  /* Read the byte from the stream. */
fukasawa e60969
                  b = reread_byte(file);
fukasawa e60969
fukasawa e60969
                  /* If the byte must be rewritten handle that here */
fukasawa e60969
                  if (chunk->rewrite_length > 0)
fukasawa e60969
                  {
fukasawa e60969
                     if (chunk->rewrite_offset > 0)
fukasawa e60969
                        --(chunk->rewrite_offset);
fukasawa e60969
fukasawa e60969
                     else
fukasawa e60969
                     {
fukasawa e60969
                        b = chunk->rewrite_buffer[0];
fukasawa e60969
                        memmove(chunk->rewrite_buffer, chunk->rewrite_buffer+1,
fukasawa e60969
                           (sizeof chunk->rewrite_buffer)-
fukasawa e60969
                              (sizeof chunk->rewrite_buffer[0]));
fukasawa e60969
fukasawa e60969
                        --(chunk->rewrite_length);
fukasawa e60969
                     }
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  chunk->write_crc = crc_one_byte(chunk->write_crc, b);
fukasawa e60969
                  break;
fukasawa e60969
fukasawa e60969
               /* The CRC is written at:
fukasawa e60969
                *
fukasawa e60969
                *    chunk_write == chunk_length+8..chunk_length+11
fukasawa e60969
                *
fukasawa e60969
                * so 8 to 11.  The CRC is not (yet) conditioned.
fukasawa e60969
                */
fukasawa e60969
               case  8: b = chunk->write_crc >> 24; goto write_crc;
fukasawa e60969
               case  9: b = chunk->write_crc >> 16; goto write_crc;
fukasawa e60969
               case 10: b = chunk->write_crc >>  8; goto write_crc;
fukasawa e60969
               case 11:
fukasawa e60969
                  /* This must happen before the chunk_end below: */
fukasawa e60969
                  b = chunk->write_crc;
fukasawa e60969
fukasawa e60969
                  if (file->global->verbose > 2)
fukasawa e60969
                  {
fukasawa e60969
                     fputs("   ", stderr);
fukasawa e60969
                     type_name(type, stderr);
fukasawa e60969
                     fprintf(stderr, " %lu 0x%.8x\n", (unsigned long)length,
fukasawa e60969
                        chunk->write_crc ^ 0xffffffff);
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  /* The IDAT stream is written without a call to read_chunk
fukasawa e60969
                   * until the end is reached.  rechunk_length() calculates the
fukasawa e60969
                   * length of the output chunks.  Control gets to this point at
fukasawa e60969
                   * the end of an *output* chunk - the length calculated by
fukasawa e60969
                   * rechunk_length.  If this corresponds to the end of the
fukasawa e60969
                   * input stream stop writing IDAT chunks, otherwise continue.
fukasawa e60969
                   */
fukasawa e60969
                  if (file->state == STATE_IDAT &&
fukasawa e60969
                     (file->idat->idat_index < file->idat->idat_length ||
fukasawa e60969
                      1+file->idat->idat_count < file->idat->idat_cur->count ||
fukasawa e60969
                      file->idat->idat_cur != file->idat->idat_list_tail))
fukasawa e60969
                  {
fukasawa e60969
                     /* Write another IDAT chunk.  Call rechunk_length to
fukasawa e60969
                      * calculate the length required.
fukasawa e60969
                      */
fukasawa e60969
                     length = chunk->chunk_length = rechunk_length(file->idat);
fukasawa e60969
                     assert(type == png_IDAT);
fukasawa e60969
                     file->write_count = 0; /* for the new chunk */
fukasawa e60969
                     --(file->write_count); /* fake out the increment below */
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  else
fukasawa e60969
                  {
fukasawa e60969
                     /* Entered at the end of a non-IDAT chunk and at the end of
fukasawa e60969
                      * the IDAT stream.  The rewrite should have been cleared.
fukasawa e60969
                      */
fukasawa e60969
                     if (chunk->rewrite_length > 0 || chunk->rewrite_offset > 0)
fukasawa e60969
                        stop(file, UNEXPECTED_ERROR_CODE, "pending rewrite");
fukasawa e60969
fukasawa e60969
                     /* This is the last byte so reset chunk_read for the next
fukasawa e60969
                      * chunk and move the input file to the position after the
fukasawa e60969
                      * *next* chunk header if required.
fukasawa e60969
                      */
fukasawa e60969
                     file->read_count = 8;
fukasawa e60969
                     file_setpos(file, &file->data_pos);
fukasawa e60969
fukasawa e60969
                     if (file->idat == NULL)
fukasawa e60969
                        chunk_end(&file->chunk);
fukasawa e60969
fukasawa e60969
                     else
fukasawa e60969
                        IDAT_end(&file->idat);
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
               write_crc:
fukasawa e60969
                  b ^= 0xff; /* conditioning */
fukasawa e60969
                  break;
fukasawa e60969
            }
fukasawa e60969
            break;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* Write one byte */
fukasawa e60969
      b &= 0xff;
fukasawa e60969
      *buffer++ = (png_byte)b;
fukasawa e60969
      --count;
fukasawa e60969
      write_byte(file, (png_byte)b); /* increments chunk_write */
fukasawa e60969
   }
fukasawa e60969
   while (count > 0);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Bundle the file and an uninitialized chunk and IDAT control structure
fukasawa e60969
 * together to allow implementation of the chunk/IDAT allocate routine.
fukasawa e60969
 */
fukasawa e60969
struct control
fukasawa e60969
{
fukasawa e60969
   struct file  file;
fukasawa e60969
   struct chunk chunk;
fukasawa e60969
   struct IDAT  idat;
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
control_end(struct control *control)
fukasawa e60969
{
fukasawa e60969
   return file_end(&control->file);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static struct file *
fukasawa e60969
get_control(png_const_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   /* This just returns the (file*).  The chunk and idat control structures
fukasawa e60969
    * don't always exist.
fukasawa e60969
    */
fukasawa e60969
   struct control *control = voidcast(struct control*,
fukasawa e60969
      png_get_error_ptr(png_ptr));
fukasawa e60969
   return &control->file;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
allocate(struct file *file, int allocate_idat)
fukasawa e60969
{
fukasawa e60969
   struct control *control = voidcast(struct control*, file->alloc_ptr);
fukasawa e60969
fukasawa e60969
   if (allocate_idat)
fukasawa e60969
   {
fukasawa e60969
      assert(file->idat == NULL);
fukasawa e60969
      IDAT_init(&control->idat, file);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else /* chunk */
fukasawa e60969
   {
fukasawa e60969
      assert(file->chunk == NULL);
fukasawa e60969
      chunk_init(&control->chunk, file);
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
control_init(struct control *control, struct global *global,
fukasawa e60969
   const char *file_name, const char *out_name)
fukasawa e60969
   /* This wraps file_init(&control::file) and simply returns the result from
fukasawa e60969
    * file_init.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   return file_init(&control->file, global, file_name, out_name, control,
fukasawa e60969
      allocate);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
read_png(struct control *control)
fukasawa e60969
   /* Read a PNG, return 0 on success else an error (status) code; a bit mask as
fukasawa e60969
    * defined for file::status_code as above.
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_structp png_ptr;
fukasawa e60969
   png_infop info_ptr = NULL;
fukasawa e60969
   volatile int rc;
fukasawa e60969
fukasawa e60969
   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, control,
fukasawa e60969
      error_handler, warning_handler);
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
   {
fukasawa e60969
      /* This is not really expected. */
fukasawa e60969
      log_error(&control->file, LIBPNG_ERROR_CODE, "OOM allocating png_struct");
fukasawa e60969
      control->file.status_code |= INTERNAL_ERROR;
fukasawa e60969
      return LIBPNG_ERROR_CODE;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   rc = setjmp(control->file.jmpbuf);
fukasawa e60969
   if (rc == 0)
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_SET_USER_LIMITS_SUPPORTED
fukasawa e60969
         /* Remove any limits on the size of PNG files that can be read,
fukasawa e60969
          * without this we may reject files based on built-in safety
fukasawa e60969
          * limits.
fukasawa e60969
          */
fukasawa e60969
         png_set_user_limits(png_ptr, 0x7fffffff, 0x7fffffff);
fukasawa e60969
         png_set_chunk_cache_max(png_ptr, 0);
fukasawa e60969
         png_set_chunk_malloc_max(png_ptr, 0);
fukasawa e60969
#     endif
fukasawa e60969
fukasawa e60969
      png_set_read_fn(png_ptr, control, read_callback);
fukasawa e60969
fukasawa e60969
      info_ptr = png_create_info_struct(png_ptr);
fukasawa e60969
      if (info_ptr == NULL)
fukasawa e60969
         png_error(png_ptr, "OOM allocating info structure");
fukasawa e60969
fukasawa e60969
      if (control->file.global->verbose)
fukasawa e60969
         fprintf(stderr, " INFO\n");
fukasawa e60969
fukasawa e60969
      png_read_info(png_ptr, info_ptr);
fukasawa e60969
fukasawa e60969
      {
fukasawa e60969
        png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
fukasawa e60969
        int passes = png_set_interlace_handling(png_ptr);
fukasawa e60969
        int pass;
fukasawa e60969
fukasawa e60969
        png_start_read_image(png_ptr);
fukasawa e60969
fukasawa e60969
        for (pass = 0; pass < passes; ++pass)
fukasawa e60969
        {
fukasawa e60969
           png_uint_32 y = height;
fukasawa e60969
fukasawa e60969
           /* NOTE: this skips asking libpng to return either version of
fukasawa e60969
            * the image row, but libpng still reads the rows.
fukasawa e60969
            */
fukasawa e60969
           while (y-- > 0)
fukasawa e60969
              png_read_row(png_ptr, NULL, NULL);
fukasawa e60969
        }
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      if (control->file.global->verbose)
fukasawa e60969
         fprintf(stderr, " END\n");
fukasawa e60969
fukasawa e60969
      /* Make sure to read to the end of the file: */
fukasawa e60969
      png_read_end(png_ptr, info_ptr);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fukasawa e60969
   return rc;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
one_file(struct global *global, const char *file_name, const char *out_name)
fukasawa e60969
{
fukasawa e60969
   int rc;
fukasawa e60969
   struct control control;
fukasawa e60969
fukasawa e60969
   if (global->verbose)
fukasawa e60969
      fprintf(stderr, "FILE %s -> %s\n", file_name,
fukasawa e60969
         out_name ? out_name : "<none>");</none>
fukasawa e60969
fukasawa e60969
   /* Although control_init can return a failure code the structure is always
fukasawa e60969
    * initialized, so control_end can be used to accumulate any status codes.
fukasawa e60969
    */
fukasawa e60969
   rc = control_init(&control, global, file_name, out_name);
fukasawa e60969
fukasawa e60969
   if (rc == 0)
fukasawa e60969
      rc = read_png(&control);
fukasawa e60969
fukasawa e60969
   rc |= control_end(&control);
fukasawa e60969
fukasawa e60969
   return rc;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
usage(const char *prog)
fukasawa e60969
{
fukasawa e60969
   /* ANSI C-90 limits strings to 509 characters, so use a string array: */
fukasawa e60969
   size_t i;
fukasawa e60969
   static const char *usage_string[] = {
fukasawa e60969
"  Tests, optimizes and optionally fixes the zlib header in PNG files.",
fukasawa e60969
"  Optionally, when fixing, strips ancilliary chunks from the file.",
fukasawa e60969
0,
fukasawa e60969
"OPTIONS",
fukasawa e60969
"  OPERATION",
fukasawa e60969
"      By default files are just checked for readability with a summary of the",
fukasawa e60969
"      of zlib issues founds for each compressed chunk and the IDAT stream in",
fukasawa e60969
"      the file.",
fukasawa e60969
"    --optimize (-o):",
fukasawa e60969
"      Find the smallest deflate window size for the compressed data.",
fukasawa e60969
"    --strip=[none|crc|unsafe|unused|transform|color|all]:",
fukasawa e60969
"        none (default):   Retain all chunks.",
fukasawa e60969
"        crc:    Remove chunks with a bad CRC.",
fukasawa e60969
"        unsafe: Remove chunks that may be unsafe to retain if the image data",
fukasawa e60969
"                is modified.  This is set automatically if --max is given but",
fukasawa e60969
"                may be cancelled by a later --strip=none.",
fukasawa e60969
"        unused: Remove chunks not used by libpng when decoding an image.",
fukasawa e60969
"                This retains any chunks that might be used by libpng image",
fukasawa e60969
"                transformations.",
fukasawa e60969
"        transform: unused+bKGD.",
fukasawa e60969
"        color:  transform+iCCP and cHRM.",
fukasawa e60969
"        all:    color+gAMA and sRGB.",
fukasawa e60969
"      Only ancillary chunks are ever removed.  In addition the tRNS and sBIT",
fukasawa e60969
"      chunks are never removed as they affect exact interpretation of the",
fukasawa e60969
"      image pixel values.  The following known chunks are treated specially",
fukasawa e60969
"      by the above options:",
fukasawa e60969
"        gAMA, sRGB [all]: These specify the gamma encoding used for the pixel",
fukasawa e60969
"            values.",
fukasawa e60969
"        cHRM, iCCP [color]: These specify how colors are encoded.  iCCP also",
fukasawa e60969
"            specifies the exact encoding of a pixel value; however, in",
fukasawa e60969
"            practice most programs will ignore it.",
fukasawa e60969
"        bKGD [transform]: This is used by libpng transforms."
fukasawa e60969
"    --max=<number>:",</number>
fukasawa e60969
"      Use IDAT chunks sized <number>.  If no number is given the the IDAT",</number>
fukasawa e60969
"      chunks will be the maximum size permitted; 2^31-1 bytes.  If the option",
fukasawa e60969
"      is omitted the original chunk sizes will not be changed.  When the",
fukasawa e60969
"      option is given --strip=unsafe is set automatically. This may be",
fukasawa e60969
"      cancelled if you know that all unknown unsafe-to-copy chunks really are",
fukasawa e60969
"      safe to copy across an IDAT size change.  This is true of all chunks",
fukasawa e60969
"      that have ever been formally proposed as PNG extensions.",
fukasawa e60969
"  MESSAGES",
fukasawa e60969
"      By default the program only outputs summaries for each file.",
fukasawa e60969
"    --quiet (-q):",
fukasawa e60969
"      Do not output the summaries except for files that cannot be read. With",
fukasawa e60969
"      two --quiets these are not output either.",
fukasawa e60969
"    --errors (-e):",
fukasawa e60969
"      Output errors from libpng and the program (except too-far-back).",
fukasawa e60969
"    --warnings (-w):",
fukasawa e60969
"      Output warnings from libpng.",
fukasawa e60969
"  OUTPUT",
fukasawa e60969
"      By default nothing is written.",
fukasawa e60969
"    --out=<file>:",</file>
fukasawa e60969
"      Write the optimized/corrected version of the next PNG to <file>.  This",</file>
fukasawa e60969
"      overrides the following two options",
fukasawa e60969
"    --suffix=<suffix>:",</suffix>
fukasawa e60969
"      Set --out=<name><suffix> for all following files unless overridden on",</suffix></name>
fukasawa e60969
"      a per-file basis by explicit --out.",
fukasawa e60969
"    --prefix=<prefix>:",</prefix>
fukasawa e60969
"      Set --out=<prefix><name> for all the following files unless overridden",</name></prefix>
fukasawa e60969
"      on a per-file basis by explicit --out.",
fukasawa e60969
"      These two options can be used together to produce a suffix and prefix.",
fukasawa e60969
"  INTERNAL OPTIONS",
fukasawa e60969
#if 0 /*NYI*/
fukasawa e60969
#ifdef PNG_MAXIMUM_INFLATE_WINDOW
fukasawa e60969
"    --test:",
fukasawa e60969
"      Test the PNG_MAXIMUM_INFLATE_WINDOW option.  Setting this disables",
fukasawa e60969
"      output as this would produce a broken file.",
fukasawa e60969
#endif
fukasawa e60969
#endif
fukasawa e60969
0,
fukasawa e60969
"EXIT CODES",
fukasawa e60969
"  *** SUBJECT TO CHANGE ***",
fukasawa e60969
"  The program exit code is value in the range 0..127 holding a bit mask of",
fukasawa e60969
"  the following codes.  Notice that the results for each file are combined",
fukasawa e60969
"  together - check one file at a time to get a meaningful error code!",
fukasawa e60969
"    0x01: The zlib too-far-back error existed in at least one chunk.",
fukasawa e60969
"    0x02: At least one chunk had a CRC error.",
fukasawa e60969
"    0x04: A chunk length was incorrect.",
fukasawa e60969
"    0x08: The file was truncated.",
fukasawa e60969
"  Errors less than 16 are potentially recoverable, for a single file if the",
fukasawa e60969
"  exit code is less than 16 the file could be read (with corrections if a",
fukasawa e60969
"  non-zero code is returned).",
fukasawa e60969
"    0x10: The file could not be read, even with corrections.",
fukasawa e60969
"    0x20: The output file could not be written.",
fukasawa e60969
"    0x40: An unexpected, potentially internal, error occurred.",
fukasawa e60969
"  If the command line arguments are incorrect the program exits with exit",
fukasawa e60969
"  255.  Some older operating systems only support 7-bit exit codes, on those",
fukasawa e60969
"  systems it is suggested that this program is first tested by supplying",
fukasawa e60969
"  invalid arguments.",
fukasawa e60969
0,
fukasawa e60969
"DESCRIPTION",
fukasawa e60969
"  " PROGRAM_NAME ":",
fukasawa e60969
"  checks each PNG file on the command line for errors.  By default errors are",
fukasawa e60969
"  not output and the program just returns an exit code and prints a summary.",
fukasawa e60969
"  With the --quiet (-q) option the summaries are suppressed too and the",
fukasawa e60969
"  program only outputs unexpected errors (internal errors and file open",
fukasawa e60969
"  errors).",
fukasawa e60969
"  Various known problems in PNG files are fixed while the file is being read",
fukasawa e60969
"  The exit code says what problems were fixed.  In particular the zlib error:",
fukasawa e60969
0,
fukasawa e60969
"        \"invalid distance too far back\"",
fukasawa e60969
0,
fukasawa e60969
"  caused by an incorrect optimization of a zlib stream is fixed in any",
fukasawa e60969
"  compressed chunk in which it is encountered.  An integrity problem of the",
fukasawa e60969
"  PNG stream caused by a bug in libpng which wrote an incorrect chunk length",
fukasawa e60969
"  is also fixed.  Chunk CRC errors are automatically fixed up.",
fukasawa e60969
0,
fukasawa e60969
"  Setting one of the \"OUTPUT\" options causes the possibly modified file to",
fukasawa e60969
"  be written to a new file.",
fukasawa e60969
0,
fukasawa e60969
"  Notice that some PNG files with the zlib optimization problem can still be",
fukasawa e60969
"  read by libpng under some circumstances.  This program will still detect",
fukasawa e60969
"  and, if requested, correct the error.",
fukasawa e60969
0,
fukasawa e60969
"  The program will reliably process all files on the command line unless",
fukasawa e60969
"  either an invalid argument causes the usage message (this message) to be",
fukasawa e60969
"  produced or the program crashes.",
fukasawa e60969
0,
fukasawa e60969
"  The summary lines describe issues encountered with the zlib compressed",
fukasawa e60969
"  stream of a chunk.  They have the following format, which is SUBJECT TO",
fukasawa e60969
"  CHANGE in the future:",
fukasawa e60969
0,
fukasawa e60969
"     chunk reason comp-level p1 p2 p3 p4 file",
fukasawa e60969
0,
fukasawa e60969
"  p1 through p4 vary according to the 'reason'.  There are always 8 space",
fukasawa e60969
"  separated fields.  Reasons specific formats are:",
fukasawa e60969
0,
fukasawa e60969
"     chunk ERR status code read-errno write-errno message file",
fukasawa e60969
"     chunk SKP comp-level file-bits zlib-rc compressed message file",
fukasawa e60969
"     chunk ??? comp-level file-bits ok-bits compressed uncompress file",
fukasawa e60969
0,
fukasawa e60969
"  The various fields are",
fukasawa e60969
0,
fukasawa e60969
"$1 chunk:      The chunk type of a chunk in the file or 'HEAD' if a problem",
fukasawa e60969
"               is reported by libpng at the start of the IDAT stream.",
fukasawa e60969
"$2 reason:     One of:",
fukasawa e60969
"          CHK: A zlib header checksum was detected and fixed.",
fukasawa e60969
"          TFB: The zlib too far back error was detected and fixed.",
fukasawa e60969
"          OK : No errors were detected in the zlib stream and optimization",
fukasawa e60969
"               was not requested, or was not possible.",
fukasawa e60969
"          OPT: The zlib stream window bits value could be improved (and was).",
fukasawa e60969
"          SKP: The chunk was skipped because of a zlib issue (zlib-rc) with",
fukasawa e60969
"               explanation 'message'",
fukasawa e60969
"          ERR: The read of the file was aborted.  The parameters explain why.",
fukasawa e60969
"$3 status:     For 'ERR' the accumulated status code from 'EXIT CODES' above.",
fukasawa e60969
"               This is printed as a 2 digit hexadecimal value",
fukasawa e60969
"   comp-level: The recorded compression level (FLEVEL) of a zlib stream",
fukasawa e60969
"               expressed as a string {supfast,stdfast,default,maximum}",
fukasawa e60969
"$4 code:       The file exit code; where stop was called, as a fairly terse",
fukasawa e60969
"               string {warning,libpng,zlib,invalid,read,write,unexpected}.",
fukasawa e60969
"   file-bits:  The zlib window bits recorded in the file.",
fukasawa e60969
"$5 read-errno: A system errno value from a read translated by strerror(3).",
fukasawa e60969
"   zlib-rc:    A zlib return code as a string (see zlib.h).",
fukasawa e60969
"   ok-bits:    The smallest zlib window bits value that works.",
fukasawa e60969
"$6 write-errno:A system errno value from a write translated by strerror(3).",
fukasawa e60969
"   compressed: The count of compressed bytes in the zlib stream, when the",
fukasawa e60969
"               reason is 'SKP'; this is a count of the bytes read from the",
fukasawa e60969
"               stream when the fatal error was encountered.",
fukasawa e60969
"$7 message:    An error message (spaces replaced by _, as in all parameters),",
fukasawa e60969
"   uncompress: The count of bytes from uncompressing the zlib stream; this",
fukasawa e60969
"               may not be the same as the number of bytes in the image.",
fukasawa e60969
"$8 file:       The name of the file (this may contain spaces).",
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
   fprintf(stderr, "Usage: %s {[options] png-file}\n", prog);
fukasawa e60969
fukasawa e60969
   for (i=0; i < (sizeof usage_string)/(sizeof usage_string[0]); ++i)
fukasawa e60969
   {
fukasawa e60969
      if (usage_string[i] != 0)
fukasawa e60969
         fputs(usage_string[i], stderr);
fukasawa e60969
fukasawa e60969
      fputc('\n', stderr);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   exit(255);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
int
fukasawa e60969
main(int argc, const char **argv)
fukasawa e60969
{
fukasawa e60969
   char temp_name[FILENAME_MAX+1];
fukasawa e60969
   const char *  prog = *argv;
fukasawa e60969
   const char *  outfile = NULL;
fukasawa e60969
   const char *  suffix = NULL;
fukasawa e60969
   const char *  prefix = NULL;
fukasawa e60969
   int           done = 0; /* if at least one file is processed */
fukasawa e60969
   struct global global;
fukasawa e60969
fukasawa e60969
   global_init(&global);
fukasawa e60969
fukasawa e60969
   while (--argc > 0)
fukasawa e60969
   {
fukasawa e60969
      ++argv;
fukasawa e60969
fukasawa e60969
      if (strcmp(*argv, "--debug") == 0)
fukasawa e60969
      {
fukasawa e60969
         /* To help debugging problems: */
fukasawa e60969
         global.errors = global.warnings = 1;
fukasawa e60969
         global.quiet = 0;
fukasawa e60969
         global.verbose = 7;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else if (strncmp(*argv, "--max=", 6) == 0)
fukasawa e60969
      {
fukasawa e60969
         global.idat_max = (png_uint_32)atol(6+*argv);
fukasawa e60969
fukasawa e60969
         if (global.skip < SKIP_UNSAFE)
fukasawa e60969
            global.skip = SKIP_UNSAFE;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--max") == 0)
fukasawa e60969
      {
fukasawa e60969
         global.idat_max = 0x7fffffff;
fukasawa e60969
fukasawa e60969
         if (global.skip < SKIP_UNSAFE)
fukasawa e60969
            global.skip = SKIP_UNSAFE;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--optimize") == 0 || strcmp(*argv, "-o") == 0)
fukasawa e60969
         global.optimize_zlib = 1;
fukasawa e60969
fukasawa e60969
      else if (strncmp(*argv, "--out=", 6) == 0)
fukasawa e60969
         outfile = 6+*argv;
fukasawa e60969
fukasawa e60969
      else if (strncmp(*argv, "--suffix=", 9) == 0)
fukasawa e60969
         suffix = 9+*argv;
fukasawa e60969
fukasawa e60969
      else if (strncmp(*argv, "--prefix=", 9) == 0)
fukasawa e60969
         prefix = 9+*argv;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=none") == 0)
fukasawa e60969
         global.skip = SKIP_NONE;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=crc") == 0)
fukasawa e60969
         global.skip = SKIP_BAD_CRC;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=unsafe") == 0)
fukasawa e60969
         global.skip = SKIP_UNSAFE;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=unused") == 0)
fukasawa e60969
         global.skip = SKIP_UNUSED;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=transform") == 0)
fukasawa e60969
         global.skip = SKIP_TRANSFORM;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=color") == 0)
fukasawa e60969
         global.skip = SKIP_COLOR;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--strip=all") == 0)
fukasawa e60969
         global.skip = SKIP_ALL;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--errors") == 0 || strcmp(*argv, "-e") == 0)
fukasawa e60969
         global.errors = 1;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--warnings") == 0 || strcmp(*argv, "-w") == 0)
fukasawa e60969
         global.warnings = 1;
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--quiet") == 0 || strcmp(*argv, "-q") == 0)
fukasawa e60969
      {
fukasawa e60969
         if (global.quiet)
fukasawa e60969
            global.quiet = 2;
fukasawa e60969
fukasawa e60969
         else
fukasawa e60969
            global.quiet = 1;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else if (strcmp(*argv, "--verbose") == 0 || strcmp(*argv, "-v") == 0)
fukasawa e60969
         ++global.verbose;
fukasawa e60969
fukasawa e60969
#if 0
fukasawa e60969
      /* NYI */
fukasawa e60969
#     ifdef PNG_MAXIMUM_INFLATE_WINDOW
fukasawa e60969
         else if (strcmp(*argv, "--test") == 0)
fukasawa e60969
            ++set_option;
fukasawa e60969
#     endif
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
      else if ((*argv)[0] == '-')
fukasawa e60969
         usage(prog);
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         size_t outlen = strlen(*argv);
fukasawa e60969
fukasawa e60969
         if (outfile == NULL) /* else this takes precedence */
fukasawa e60969
         {
fukasawa e60969
            /* Consider the prefix/suffix options */
fukasawa e60969
            if (prefix != NULL)
fukasawa e60969
            {
fukasawa e60969
               size_t prefixlen = strlen(prefix);
fukasawa e60969
fukasawa e60969
               if (prefixlen+outlen > FILENAME_MAX)
fukasawa e60969
               {
fukasawa e60969
                  fprintf(stderr, "%s: output file name too long: %s%s%s\n",
fukasawa e60969
                     prog, prefix, *argv, suffix ? suffix : "");
fukasawa e60969
                  global.status_code |= WRITE_ERROR;
fukasawa e60969
                  continue;
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               memcpy(temp_name, prefix, prefixlen);
fukasawa e60969
               memcpy(temp_name+prefixlen, *argv, outlen);
fukasawa e60969
               outlen += prefixlen;
fukasawa e60969
               outfile = temp_name;
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            else if (suffix != NULL)
fukasawa e60969
               memcpy(temp_name, *argv, outlen);
fukasawa e60969
fukasawa e60969
            temp_name[outlen] = 0;
fukasawa e60969
fukasawa e60969
            if (suffix != NULL)
fukasawa e60969
            {
fukasawa e60969
               size_t suffixlen = strlen(suffix);
fukasawa e60969
fukasawa e60969
               if (outlen+suffixlen > FILENAME_MAX)
fukasawa e60969
               {
fukasawa e60969
                  fprintf(stderr, "%s: output file name too long: %s%s\n",
fukasawa e60969
                     prog, *argv, suffix);
fukasawa e60969
                  global.status_code |= WRITE_ERROR;
fukasawa e60969
                  continue;
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               memcpy(temp_name+outlen, suffix, suffixlen);
fukasawa e60969
               outlen += suffixlen;
fukasawa e60969
               temp_name[outlen] = 0;
fukasawa e60969
               outfile = temp_name;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         (void)one_file(&global, *argv, outfile);
fukasawa e60969
         ++done;
fukasawa e60969
         outfile = NULL;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (!done)
fukasawa e60969
      usage(prog);
fukasawa e60969
fukasawa e60969
   return global_end(&global);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#else /* ZLIB_VERNUM < 0x1240 */
fukasawa e60969
int
fukasawa e60969
main(void)
fukasawa e60969
{
fukasawa e60969
   fprintf(stderr,
fukasawa e60969
      "pngfix needs libpng with a zlib >=1.2.4 (not 0x%x)\n",
fukasawa e60969
      ZLIB_VERNUM);
fukasawa e60969
   return 77;
fukasawa e60969
}
fukasawa e60969
#endif /* ZLIB_VERNUM */
fukasawa e60969
fukasawa e60969
#else /* No read support */
fukasawa e60969
fukasawa e60969
int
fukasawa e60969
main(void)
fukasawa e60969
{
fukasawa e60969
   fprintf(stderr, "pngfix does not work without read deinterlace support\n");
fukasawa e60969
   return 77;
fukasawa e60969
}
fukasawa e60969
#endif /* PNG_READ_SUPPORTED && PNG_EASY_ACCESS_SUPPORTED */
fukasawa e60969
#else /* No setjmp support */
fukasawa e60969
int
fukasawa e60969
main(void)
fukasawa e60969
{
fukasawa e60969
   fprintf(stderr, "pngfix does not work without setjmp support\n");
fukasawa e60969
   return 77;
fukasawa e60969
}
fukasawa e60969
#endif /* PNG_SETJMP_SUPPORTED */
fukasawa e60969