1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /* pngtest.c - a simple test program to test libpng
  26  *
  27  * This file is available under and governed by the GNU General Public
  28  * License version 2 only, as published by the Free Software Foundation.
  29  * However, the following notice accompanied the original version of this
  30  * file and, per its terms, should not be removed:
  31  *
  32  * Last changed in libpng 1.5.25 [December 3, 2015]
  33  * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  34  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  35  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  36  *
  37  * This code is released under the libpng license.
  38  * For conditions of distribution and use, see the disclaimer
  39  * and license in png.h
  40  *
  41  * This program reads in a PNG image, writes it out again, and then
  42  * compares the two files.  If the files are identical, this shows that
  43  * the basic chunk handling, filtering, and (de)compression code is working
  44  * properly.  It does not currently test all of the transforms, although
  45  * it probably should.
  46  *
  47  * The program will report "FAIL" in certain legitimate cases:
  48  * 1) when the compression level or filter selection method is changed.
  49  * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
  50  * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks
  51  *    exist in the input file.
  52  * 4) others not listed here...
  53  * In these cases, it is best to check with another tool such as "pngcheck"
  54  * to see what the differences between the two files are.
  55  *
  56  * If a filename is given on the command-line, then this file is used
  57  * for the input, rather than the default "pngtest.png".  This allows
  58  * testing a wide variety of files easily.  You can also test a number
  59  * of files at once by typing "pngtest -m file1.png file2.png ..."
  60  */
  61 
  62 #define _POSIX_SOURCE 1
  63 
  64 #include <stdio.h>
  65 #include <stdlib.h>
  66 #include <string.h>
  67 
  68 /* Defined so I can write to a file on gui/windowing platforms */
  69 /*  #define STDERR stderr  */
  70 #define STDERR stdout   /* For DOS */
  71 
  72 #include "png.h"
  73 
  74 /* 1.6.1 added support for the configure test harness, which uses 77 to indicate
  75  * a skipped test, in earlier versions we need to succeed on a skipped test, so:
  76  */
  77 #if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
  78 #  define SKIP 77
  79 #else
  80 #  define SKIP 0
  81 #endif
  82 
  83 /* Known chunks that exist in pngtest.png must be supported or pngtest will fail
  84  * simply as a result of re-ordering them.  This may be fixed in 1.7
  85  *
  86  * pngtest allocates a single row buffer for each row and overwrites it,
  87  * therefore if the write side doesn't support the writing of interlaced images
  88  * nothing can be done for an interlaced image (and the code below will fail
  89  * horribly trying to write extra data after writing garbage).
  90  */
  91 #if defined PNG_READ_SUPPORTED && /* else nothing can be done */\
  92    defined PNG_READ_bKGD_SUPPORTED &&\
  93    defined PNG_READ_cHRM_SUPPORTED &&\
  94    defined PNG_READ_gAMA_SUPPORTED &&\
  95    defined PNG_READ_oFFs_SUPPORTED &&\
  96    defined PNG_READ_pCAL_SUPPORTED &&\
  97    defined PNG_READ_pHYs_SUPPORTED &&\
  98    defined PNG_READ_sBIT_SUPPORTED &&\
  99    defined PNG_READ_sCAL_SUPPORTED &&\
 100    defined PNG_READ_sRGB_SUPPORTED &&\
 101    defined PNG_READ_sPLT_SUPPORTED &&\
 102    defined PNG_READ_tEXt_SUPPORTED &&\
 103    defined PNG_READ_tIME_SUPPORTED &&\
 104    defined PNG_READ_zTXt_SUPPORTED &&\
 105    (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
 106 
 107 #ifdef PNG_ZLIB_HEADER
 108 #  include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
 109 #else
 110 #  include "zlib.h"
 111 #endif
 112 
 113 /* Copied from pngpriv.h but only used in error messages below. */
 114 #ifndef PNG_ZBUF_SIZE
 115 #  define PNG_ZBUF_SIZE 8192
 116 #endif
 117 #define FCLOSE(file) fclose(file)
 118 
 119 #ifndef PNG_STDIO_SUPPORTED
 120 typedef FILE                * png_FILE_p;
 121 #endif
 122 
 123 /* Makes pngtest verbose so we can find problems. */
 124 #ifndef PNG_DEBUG
 125 #  define PNG_DEBUG 0
 126 #endif
 127 
 128 #if PNG_DEBUG > 1
 129 #  define pngtest_debug(m)        ((void)fprintf(stderr, m "\n"))
 130 #  define pngtest_debug1(m,p1)    ((void)fprintf(stderr, m "\n", p1))
 131 #  define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2))
 132 #else
 133 #  define pngtest_debug(m)        ((void)0)
 134 #  define pngtest_debug1(m,p1)    ((void)0)
 135 #  define pngtest_debug2(m,p1,p2) ((void)0)
 136 #endif
 137 
 138 #if !PNG_DEBUG
 139 #  define SINGLE_ROWBUF_ALLOC  /* Makes buffer overruns easier to nail */
 140 #endif
 141 
 142 #ifndef PNG_UNUSED
 143 #  define PNG_UNUSED(param) (void)param;
 144 #endif
 145 
 146 /* Turn on CPU timing
 147 #define PNGTEST_TIMING
 148 */
 149 
 150 #ifndef PNG_FLOATING_POINT_SUPPORTED
 151 #undef PNGTEST_TIMING
 152 #endif
 153 
 154 #ifdef PNGTEST_TIMING
 155 static float t_start, t_stop, t_decode, t_encode, t_misc;
 156 #include <time.h>
 157 #endif
 158 
 159 #ifdef PNG_TIME_RFC1123_SUPPORTED
 160 #define PNG_tIME_STRING_LENGTH 29
 161 static int tIME_chunk_present = 0;
 162 static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";
 163 
 164 #if PNG_LIBPNG_VER < 10619
 165 #define png_convert_to_rfc1123_buffer(ts, t) tIME_to_str(read_ptr, ts, t)
 166 
 167 static int
 168 tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t)
 169 {
 170     png_const_charp str = png_convert_to_rfc1123(png_ptr, t);
 171 
 172     if (str == NULL)
 173         return 0;
 174 
 175     strcpy(ts, str);
 176     return 1;
 177 }
 178 #endif /* older libpng */
 179 #endif
 180 
 181 static int verbose = 0;
 182 static int strict = 0;
 183 static int relaxed = 0;
 184 static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */
 185 static int error_count = 0; /* count calls to png_error */
 186 static int warning_count = 0; /* count calls to png_warning */
 187 
 188 /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
 189 #ifndef png_jmpbuf
 190 #  define png_jmpbuf(png_ptr) png_ptr->jmpbuf
 191 #endif
 192 
 193 /* Defines for unknown chunk handling if required. */
 194 #ifndef PNG_HANDLE_CHUNK_ALWAYS
 195 #  define PNG_HANDLE_CHUNK_ALWAYS       3
 196 #endif
 197 #ifndef PNG_HANDLE_CHUNK_IF_SAFE
 198 #  define PNG_HANDLE_CHUNK_IF_SAFE      2
 199 #endif
 200 
 201 /* Utility to save typing/errors, the argument must be a name */
 202 #define MEMZERO(var) ((void)memset(&var, 0, sizeof var))
 203 
 204 /* Example of using row callbacks to make a simple progress meter */
 205 static int status_pass = 1;
 206 static int status_dots_requested = 0;
 207 static int status_dots = 1;
 208 
 209 static void PNGCBAPI
 210 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 211 {
 212    if (png_ptr == NULL || row_number > PNG_UINT_31_MAX)
 213       return;
 214 
 215    if (status_pass != pass)
 216    {
 217       fprintf(stdout, "\n Pass %d: ", pass);
 218       status_pass = pass;
 219       status_dots = 31;
 220    }
 221 
 222    status_dots--;
 223 
 224    if (status_dots == 0)
 225    {
 226       fprintf(stdout, "\n         ");
 227       status_dots=30;
 228    }
 229 
 230    fprintf(stdout, "r");
 231 }
 232 
 233 #ifdef PNG_WRITE_SUPPORTED
 234 static void PNGCBAPI
 235 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 236 {
 237    if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7)
 238       return;
 239 
 240    fprintf(stdout, "w");
 241 }
 242 #endif
 243 
 244 
 245 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
 246 /* Example of using a user transform callback (doesn't do anything at present).
 247  */
 248 static void PNGCBAPI
 249 read_user_callback(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 250 {
 251    PNG_UNUSED(png_ptr)
 252    PNG_UNUSED(row_info)
 253    PNG_UNUSED(data)
 254 }
 255 #endif
 256 
 257 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
 258 /* Example of using user transform callback (we don't transform anything,
 259  * but merely count the zero samples)
 260  */
 261 
 262 static png_uint_32 zero_samples;
 263 
 264 static void PNGCBAPI
 265 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 266 {
 267    png_bytep dp = data;
 268    if (png_ptr == NULL)
 269       return;
 270 
 271    /* Contents of row_info:
 272     *  png_uint_32 width      width of row
 273     *  png_uint_32 rowbytes   number of bytes in row
 274     *  png_byte color_type    color type of pixels
 275     *  png_byte bit_depth     bit depth of samples
 276     *  png_byte channels      number of channels (1-4)
 277     *  png_byte pixel_depth   bits per pixel (depth*channels)
 278     */
 279 
 280     /* Counts the number of zero samples (or zero pixels if color_type is 3 */
 281 
 282     if (row_info->color_type == 0 || row_info->color_type == 3)
 283     {
 284        int pos = 0;
 285        png_uint_32 n, nstop;
 286 
 287        for (n = 0, nstop=row_info->width; n<nstop; n++)
 288        {
 289           if (row_info->bit_depth == 1)
 290           {
 291              if (((*dp << pos++ ) & 0x80) == 0)
 292                 zero_samples++;
 293 
 294              if (pos == 8)
 295              {
 296                 pos = 0;
 297                 dp++;
 298              }
 299           }
 300 
 301           if (row_info->bit_depth == 2)
 302           {
 303              if (((*dp << (pos+=2)) & 0xc0) == 0)
 304                 zero_samples++;
 305 
 306              if (pos == 8)
 307              {
 308                 pos = 0;
 309                 dp++;
 310              }
 311           }
 312 
 313           if (row_info->bit_depth == 4)
 314           {
 315              if (((*dp << (pos+=4)) & 0xf0) == 0)
 316                 zero_samples++;
 317 
 318              if (pos == 8)
 319              {
 320                 pos = 0;
 321                 dp++;
 322              }
 323           }
 324 
 325           if (row_info->bit_depth == 8)
 326              if (*dp++ == 0)
 327                 zero_samples++;
 328 
 329           if (row_info->bit_depth == 16)
 330           {
 331              if ((*dp | *(dp+1)) == 0)
 332                 zero_samples++;
 333              dp+=2;
 334           }
 335        }
 336     }
 337     else /* Other color types */
 338     {
 339        png_uint_32 n, nstop;
 340        int channel;
 341        int color_channels = row_info->channels;
 342        if (row_info->color_type > 3)
 343           color_channels--;
 344 
 345        for (n = 0, nstop=row_info->width; n<nstop; n++)
 346        {
 347           for (channel = 0; channel < color_channels; channel++)
 348           {
 349              if (row_info->bit_depth == 8)
 350                 if (*dp++ == 0)
 351                    zero_samples++;
 352 
 353              if (row_info->bit_depth == 16)
 354              {
 355                 if ((*dp | *(dp+1)) == 0)
 356                    zero_samples++;
 357 
 358                 dp+=2;
 359              }
 360           }
 361           if (row_info->color_type > 3)
 362           {
 363              dp++;
 364              if (row_info->bit_depth == 16)
 365                 dp++;
 366           }
 367        }
 368     }
 369 }
 370 #endif /* WRITE_USER_TRANSFORM */
 371 
 372 #ifndef PNG_STDIO_SUPPORTED
 373 /* START of code to validate stdio-free compilation */
 374 /* These copies of the default read/write functions come from pngrio.c and
 375  * pngwio.c.  They allow "don't include stdio" testing of the library.
 376  * This is the function that does the actual reading of data.  If you are
 377  * not reading from a standard C stream, you should create a replacement
 378  * read_data function and use it at run time with png_set_read_fn(), rather
 379  * than changing the library.
 380  */
 381 
 382 #ifdef PNG_IO_STATE_SUPPORTED
 383 void
 384 pngtest_check_io_state(png_structp png_ptr, png_size_t data_length,
 385    png_uint_32 io_op);
 386 void
 387 pngtest_check_io_state(png_structp png_ptr, png_size_t data_length,
 388    png_uint_32 io_op)
 389 {
 390    png_uint_32 io_state = png_get_io_state(png_ptr);
 391    int err = 0;
 392 
 393    /* Check if the current operation (reading / writing) is as expected. */
 394    if ((io_state & PNG_IO_MASK_OP) != io_op)
 395       png_error(png_ptr, "Incorrect operation in I/O state");
 396 
 397    /* Check if the buffer size specific to the current location
 398     * (file signature / header / data / crc) is as expected.
 399     */
 400    switch (io_state & PNG_IO_MASK_LOC)
 401    {
 402    case PNG_IO_SIGNATURE:
 403       if (data_length > 8)
 404          err = 1;
 405       break;
 406    case PNG_IO_CHUNK_HDR:
 407       if (data_length != 8)
 408          err = 1;
 409       break;
 410    case PNG_IO_CHUNK_DATA:
 411       break;  /* no restrictions here */
 412    case PNG_IO_CHUNK_CRC:
 413       if (data_length != 4)
 414          err = 1;
 415       break;
 416    default:
 417       err = 1;  /* uninitialized */
 418    }
 419    if (err != 0)
 420       png_error(png_ptr, "Bad I/O state or buffer size");
 421 }
 422 #endif
 423 
 424 static void PNGCBAPI
 425 pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 426 {
 427    png_size_t check = 0;
 428    png_voidp io_ptr;
 429 
 430    /* fread() returns 0 on error, so it is OK to store this in a png_size_t
 431     * instead of an int, which is what fread() actually returns.
 432     */
 433    io_ptr = png_get_io_ptr(png_ptr);
 434    if (io_ptr != NULL)
 435    {
 436       check = fread(data, 1, length, (png_FILE_p)io_ptr);
 437    }
 438 
 439    if (check != length)
 440    {
 441       png_error(png_ptr, "Read Error");
 442    }
 443 
 444 #ifdef PNG_IO_STATE_SUPPORTED
 445    pngtest_check_io_state(png_ptr, length, PNG_IO_READING);
 446 #endif
 447 }
 448 
 449 #ifdef PNG_WRITE_FLUSH_SUPPORTED
 450 static void PNGCBAPI
 451 pngtest_flush(png_structp png_ptr)
 452 {
 453    /* Do nothing; fflush() is said to be just a waste of energy. */
 454    PNG_UNUSED(png_ptr)   /* Stifle compiler warning */
 455 }
 456 #endif
 457 
 458 /* This is the function that does the actual writing of data.  If you are
 459  * not writing to a standard C stream, you should create a replacement
 460  * write_data function and use it at run time with png_set_write_fn(), rather
 461  * than changing the library.
 462  */
 463 static void PNGCBAPI
 464 pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 465 {
 466    png_size_t check;
 467 
 468    check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr));
 469 
 470    if (check != length)
 471    {
 472       png_error(png_ptr, "Write Error");
 473    }
 474 
 475 #ifdef PNG_IO_STATE_SUPPORTED
 476    pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING);
 477 #endif
 478 }
 479 #endif /* !STDIO */
 480 
 481 /* This function is called when there is a warning, but the library thinks
 482  * it can continue anyway.  Replacement functions don't have to do anything
 483  * here if you don't want to.  In the default configuration, png_ptr is
 484  * not used, but it is passed in case it may be useful.
 485  */
 486 typedef struct
 487 {
 488    PNG_CONST char *file_name;
 489 }  pngtest_error_parameters;
 490 
 491 static void PNGCBAPI
 492 pngtest_warning(png_structp png_ptr, png_const_charp message)
 493 {
 494    PNG_CONST char *name = "UNKNOWN (ERROR!)";
 495    pngtest_error_parameters *test =
 496       (pngtest_error_parameters*)png_get_error_ptr(png_ptr);
 497 
 498    ++warning_count;
 499 
 500    if (test != NULL && test->file_name != NULL)
 501       name = test->file_name;
 502 
 503    fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
 504 }
 505 
 506 /* This is the default error handling function.  Note that replacements for
 507  * this function MUST NOT RETURN, or the program will likely crash.  This
 508  * function is used by default, or if the program supplies NULL for the
 509  * error function pointer in png_set_error_fn().
 510  */
 511 static void PNGCBAPI
 512 pngtest_error(png_structp png_ptr, png_const_charp message)
 513 {
 514    ++error_count;
 515 
 516    pngtest_warning(png_ptr, message);
 517    /* We can return because png_error calls the default handler, which is
 518     * actually OK in this case.
 519     */
 520 }
 521 
 522 /* END of code to validate stdio-free compilation */
 523 
 524 /* START of code to validate memory allocation and deallocation */
 525 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 526 
 527 /* Allocate memory.  For reasonable files, size should never exceed
 528  * 64K.  However, zlib may allocate more than 64K if you don't tell
 529  * it not to.  See zconf.h and png.h for more information.  zlib does
 530  * need to allocate exactly 64K, so whatever you call here must
 531  * have the ability to do that.
 532  *
 533  * This piece of code can be compiled to validate max 64K allocations
 534  * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K.
 535  */
 536 typedef struct memory_information
 537 {
 538    png_alloc_size_t          size;
 539    png_voidp                 pointer;
 540    struct memory_information *next;
 541 } memory_information;
 542 typedef memory_information *memory_infop;
 543 
 544 static memory_infop pinformation = NULL;
 545 static int current_allocation = 0;
 546 static int maximum_allocation = 0;
 547 static int total_allocation = 0;
 548 static int num_allocations = 0;
 549 
 550 png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr,
 551     png_alloc_size_t size));
 552 void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));
 553 
 554 png_voidp
 555 PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
 556 {
 557 
 558    /* png_malloc has already tested for NULL; png_create_struct calls
 559     * png_debug_malloc directly, with png_ptr == NULL which is OK
 560     */
 561 
 562    if (size == 0)
 563       return (NULL);
 564 
 565    /* This calls the library allocator twice, once to get the requested
 566       buffer and once to get a new free list entry. */
 567    {
 568       /* Disable malloc_fn and free_fn */
 569       memory_infop pinfo;
 570       png_set_mem_fn(png_ptr, NULL, NULL, NULL);
 571       pinfo = (memory_infop)png_malloc(png_ptr,
 572          (sizeof *pinfo));
 573       pinfo->size = size;
 574       current_allocation += size;
 575       total_allocation += size;
 576       num_allocations ++;
 577 
 578       if (current_allocation > maximum_allocation)
 579          maximum_allocation = current_allocation;
 580 
 581       pinfo->pointer = png_malloc(png_ptr, size);
 582       /* Restore malloc_fn and free_fn */
 583 
 584       png_set_mem_fn(png_ptr,
 585           NULL, png_debug_malloc, png_debug_free);
 586 
 587       if (size != 0 && pinfo->pointer == NULL)
 588       {
 589          current_allocation -= size;
 590          total_allocation -= size;
 591          png_error(png_ptr,
 592            "out of memory in pngtest->png_debug_malloc");
 593       }
 594 
 595       pinfo->next = pinformation;
 596       pinformation = pinfo;
 597       /* Make sure the caller isn't assuming zeroed memory. */
 598       memset(pinfo->pointer, 0xdd, pinfo->size);
 599 
 600       if (verbose != 0)
 601          printf("png_malloc %lu bytes at %p\n", (unsigned long)size,
 602             pinfo->pointer);
 603 
 604       return (png_voidp)(pinfo->pointer);
 605    }
 606 }
 607 
 608 /* Free a pointer.  It is removed from the list at the same time. */
 609 void PNGCBAPI
 610 png_debug_free(png_structp png_ptr, png_voidp ptr)
 611 {
 612    if (png_ptr == NULL)
 613       fprintf(STDERR, "NULL pointer to png_debug_free.\n");
 614 
 615    if (ptr == 0)
 616    {
 617 #if 0 /* This happens all the time. */
 618       fprintf(STDERR, "WARNING: freeing NULL pointer\n");
 619 #endif
 620       return;
 621    }
 622 
 623    /* Unlink the element from the list. */
 624    if (pinformation != NULL)
 625    {
 626       memory_infop *ppinfo = &pinformation;
 627 
 628       for (;;)
 629       {
 630          memory_infop pinfo = *ppinfo;
 631 
 632          if (pinfo->pointer == ptr)
 633          {
 634             *ppinfo = pinfo->next;
 635             current_allocation -= pinfo->size;
 636             if (current_allocation < 0)
 637                fprintf(STDERR, "Duplicate free of memory\n");
 638             /* We must free the list element too, but first kill
 639                the memory that is to be freed. */
 640             memset(ptr, 0x55, pinfo->size);
 641             free(pinfo);
 642             pinfo = NULL;
 643             break;
 644          }
 645 
 646          if (pinfo->next == NULL)
 647          {
 648             fprintf(STDERR, "Pointer %p not found\n", ptr);
 649             break;
 650          }
 651 
 652          ppinfo = &pinfo->next;
 653       }
 654    }
 655 
 656    /* Finally free the data. */
 657    if (verbose != 0)
 658       printf("Freeing %p\n", ptr);
 659 
 660    if (ptr != NULL)
 661       free(ptr);
 662    ptr = NULL;
 663 }
 664 #endif /* USER_MEM && DEBUG */
 665 /* END of code to test memory allocation/deallocation */
 666 
 667 
 668 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
 669 /* Demonstration of user chunk support of the sTER and vpAg chunks */
 670 
 671 /* (sTER is a public chunk not yet known by libpng.  vpAg is a private
 672 chunk used in ImageMagick to store "virtual page" size).  */
 673 
 674 static struct user_chunk_data
 675 {
 676    png_const_infop info_ptr;
 677    png_uint_32     vpAg_width, vpAg_height;
 678    png_byte        vpAg_units;
 679    png_byte        sTER_mode;
 680    int             location[2];
 681 }
 682 user_chunk_data;
 683 
 684 /* Used for location and order; zero means nothing. */
 685 #define have_sTER   0x01
 686 #define have_vpAg   0x02
 687 #define before_PLTE 0x10
 688 #define before_IDAT 0x20
 689 #define after_IDAT  0x40
 690 
 691 static void
 692 init_callback_info(png_const_infop info_ptr)
 693 {
 694    MEMZERO(user_chunk_data);
 695    user_chunk_data.info_ptr = info_ptr;
 696 }
 697 
 698 static int
 699 set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
 700 {
 701    int location;
 702 
 703    if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
 704       return 0; /* already have one of these */
 705 
 706    /* Find where we are (the code below zeroes info_ptr to indicate that the
 707     * chunks before the first IDAT have been read.)
 708     */
 709    if (data->info_ptr == NULL) /* after IDAT */
 710       location = what | after_IDAT;
 711 
 712    else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
 713       location = what | before_IDAT;
 714 
 715    else
 716       location = what | before_PLTE;
 717 
 718    if (data->location[0] == 0)
 719       data->location[0] = location;
 720 
 721    else
 722       data->location[1] = location;
 723 
 724    return 1; /* handled */
 725 }
 726 
 727 static int PNGCBAPI
 728 read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
 729 {
 730    struct user_chunk_data *my_user_chunk_data =
 731       (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
 732 
 733    if (my_user_chunk_data == NULL)
 734       png_error(png_ptr, "lost user chunk pointer");
 735 
 736    /* Return one of the following:
 737     *    return (-n);  chunk had an error
 738     *    return (0);  did not recognize
 739     *    return (n);  success
 740     *
 741     * The unknown chunk structure contains the chunk data:
 742     * png_byte name[5];
 743     * png_byte *data;
 744     * png_size_t size;
 745     *
 746     * Note that libpng has already taken care of the CRC handling.
 747     */
 748 
 749    if (chunk->name[0] == 115 && chunk->name[1] ==  84 &&     /* s  T */
 750        chunk->name[2] ==  69 && chunk->name[3] ==  82)       /* E  R */
 751       {
 752          /* Found sTER chunk */
 753          if (chunk->size != 1)
 754             return (-1); /* Error return */
 755 
 756          if (chunk->data[0] != 0 && chunk->data[0] != 1)
 757             return (-1);  /* Invalid mode */
 758 
 759          if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
 760          {
 761             my_user_chunk_data->sTER_mode=chunk->data[0];
 762             return (1);
 763          }
 764 
 765          else
 766             return (0); /* duplicate sTER - give it to libpng */
 767       }
 768 
 769    if (chunk->name[0] != 118 || chunk->name[1] != 112 ||    /* v  p */
 770        chunk->name[2] !=  65 || chunk->name[3] != 103)      /* A  g */
 771       return (0); /* Did not recognize */
 772 
 773    /* Found ImageMagick vpAg chunk */
 774 
 775    if (chunk->size != 9)
 776       return (-1); /* Error return */
 777 
 778    if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
 779       return (0);  /* duplicate vpAg */
 780 
 781    my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
 782    my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);
 783    my_user_chunk_data->vpAg_units = chunk->data[8];
 784 
 785    return (1);
 786 }
 787 
 788 #ifdef PNG_WRITE_SUPPORTED
 789 static void
 790 write_sTER_chunk(png_structp write_ptr)
 791 {
 792    png_byte sTER[5] = {115,  84,  69,  82, '\0'};
 793 
 794    if (verbose != 0)
 795       fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
 796 
 797    png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
 798 }
 799 
 800 static void
 801 write_vpAg_chunk(png_structp write_ptr)
 802 {
 803    png_byte vpAg[5] = {118, 112,  65, 103, '\0'};
 804 
 805    png_byte vpag_chunk_data[9];
 806 
 807    if (verbose != 0)
 808       fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
 809         (unsigned long)user_chunk_data.vpAg_width,
 810         (unsigned long)user_chunk_data.vpAg_height,
 811         user_chunk_data.vpAg_units);
 812 
 813    png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
 814    png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
 815    vpag_chunk_data[8] = user_chunk_data.vpAg_units;
 816    png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
 817 }
 818 
 819 static void
 820 write_chunks(png_structp write_ptr, int location)
 821 {
 822    int i;
 823 
 824    /* Notice that this preserves the original chunk order, however chunks
 825     * intercepted by the callback will be written *after* chunks passed to
 826     * libpng.  This will actually reverse a pair of sTER chunks or a pair of
 827     * vpAg chunks, resulting in an error later.  This is not worth worrying
 828     * about - the chunks should not be duplicated!
 829     */
 830    for (i=0; i<2; ++i)
 831    {
 832       if (user_chunk_data.location[i] == (location | have_sTER))
 833          write_sTER_chunk(write_ptr);
 834 
 835       else if (user_chunk_data.location[i] == (location | have_vpAg))
 836          write_vpAg_chunk(write_ptr);
 837    }
 838 }
 839 #endif /* WRITE */
 840 #else /* !READ_USER_CHUNKS */
 841 #  define write_chunks(pp,loc) ((void)0)
 842 #endif
 843 /* END of code to demonstrate user chunk support */
 844 
 845 /* START of code to check that libpng has the required text support; this only
 846  * checks for the write support because if read support is missing the chunk
 847  * will simply not be reported back to pngtest.
 848  */
 849 #ifdef PNG_TEXT_SUPPORTED
 850 static void
 851 pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr,
 852    int num_text)
 853 {
 854    while (num_text > 0)
 855    {
 856       switch (text_ptr[--num_text].compression)
 857       {
 858          case PNG_TEXT_COMPRESSION_NONE:
 859             break;
 860 
 861          case PNG_TEXT_COMPRESSION_zTXt:
 862 #           ifndef PNG_WRITE_zTXt_SUPPORTED
 863                ++unsupported_chunks;
 864                /* In libpng 1.7 this now does an app-error, so stop it: */
 865                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
 866 #           endif
 867             break;
 868 
 869          case PNG_ITXT_COMPRESSION_NONE:
 870          case PNG_ITXT_COMPRESSION_zTXt:
 871 #           ifndef PNG_WRITE_iTXt_SUPPORTED
 872                ++unsupported_chunks;
 873                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
 874 #           endif
 875             break;
 876 
 877          default:
 878             /* This is an error */
 879             png_error(png_ptr, "invalid text chunk compression field");
 880             break;
 881       }
 882    }
 883 }
 884 #endif
 885 /* END of code to check that libpng has the required text support */
 886 
 887 /* Test one file */
 888 static int
 889 test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
 890 {
 891    static png_FILE_p fpin;
 892    static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
 893    pngtest_error_parameters error_parameters;
 894    png_structp read_ptr;
 895    png_infop read_info_ptr, end_info_ptr;
 896 #ifdef PNG_WRITE_SUPPORTED
 897    png_structp write_ptr;
 898    png_infop write_info_ptr;
 899    png_infop write_end_info_ptr;
 900 #ifdef PNG_WRITE_FILTER_SUPPORTED
 901    int interlace_preserved = 1;
 902 #endif /* WRITE_FILTER */
 903 #else /* !WRITE */
 904    png_structp write_ptr = NULL;
 905    png_infop write_info_ptr = NULL;
 906    png_infop write_end_info_ptr = NULL;
 907 #endif /* !WRITE */
 908    png_bytep row_buf;
 909    png_uint_32 y;
 910    png_uint_32 width, height;
 911    volatile int num_passes;
 912    int pass;
 913    int bit_depth, color_type;
 914 
 915    row_buf = NULL;
 916    error_parameters.file_name = inname;
 917 
 918    if ((fpin = fopen(inname, "rb")) == NULL)
 919    {
 920       fprintf(STDERR, "Could not find input file %s\n", inname);
 921       return (1);
 922    }
 923 
 924    if ((fpout = fopen(outname, "wb")) == NULL)
 925    {
 926       fprintf(STDERR, "Could not open output file %s\n", outname);
 927       FCLOSE(fpin);
 928       return (1);
 929    }
 930 
 931    pngtest_debug("Allocating read and write structures");
 932 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 933    read_ptr =
 934       png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL,
 935       NULL, NULL, NULL, png_debug_malloc, png_debug_free);
 936 #else
 937    read_ptr =
 938       png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 939 #endif
 940    png_set_error_fn(read_ptr, &error_parameters, pngtest_error,
 941       pngtest_warning);
 942 
 943 #ifdef PNG_WRITE_SUPPORTED
 944 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 945    write_ptr =
 946       png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL,
 947       NULL, NULL, NULL, png_debug_malloc, png_debug_free);
 948 #else
 949    write_ptr =
 950       png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 951 #endif
 952    png_set_error_fn(write_ptr, &error_parameters, pngtest_error,
 953       pngtest_warning);
 954 #endif
 955    pngtest_debug("Allocating read_info, write_info and end_info structures");
 956    read_info_ptr = png_create_info_struct(read_ptr);
 957    end_info_ptr = png_create_info_struct(read_ptr);
 958 #ifdef PNG_WRITE_SUPPORTED
 959    write_info_ptr = png_create_info_struct(write_ptr);
 960    write_end_info_ptr = png_create_info_struct(write_ptr);
 961 #endif
 962 
 963 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
 964    init_callback_info(read_info_ptr);
 965    png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
 966      read_user_chunk_callback);
 967 #endif
 968 
 969 #ifdef PNG_SETJMP_SUPPORTED
 970    pngtest_debug("Setting jmpbuf for read struct");
 971    if (setjmp(png_jmpbuf(read_ptr)))
 972    {
 973       fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
 974       png_free(read_ptr, row_buf);
 975       row_buf = NULL;
 976       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
 977 #ifdef PNG_WRITE_SUPPORTED
 978       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
 979       png_destroy_write_struct(&write_ptr, &write_info_ptr);
 980 #endif
 981       FCLOSE(fpin);
 982       FCLOSE(fpout);
 983       return (1);
 984    }
 985 
 986 #ifdef PNG_WRITE_SUPPORTED
 987    pngtest_debug("Setting jmpbuf for write struct");
 988 
 989    if (setjmp(png_jmpbuf(write_ptr)))
 990    {
 991       fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
 992       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
 993       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
 994 #ifdef PNG_WRITE_SUPPORTED
 995       png_destroy_write_struct(&write_ptr, &write_info_ptr);
 996 #endif
 997       FCLOSE(fpin);
 998       FCLOSE(fpout);
 999       return (1);
1000    }
1001 #endif
1002 #endif
1003 
1004    if (strict != 0)
1005    {
1006       /* Treat png_benign_error() as errors on read */
1007       png_set_benign_errors(read_ptr, 0);
1008 
1009 #ifdef PNG_WRITE_SUPPORTED
1010       /* Treat them as errors on write */
1011       png_set_benign_errors(write_ptr, 0);
1012 #endif
1013 
1014       /* if strict is not set, then app warnings and errors are treated as
1015        * warnings in release builds, but not in unstable builds; this can be
1016        * changed with '--relaxed'.
1017        */
1018    }
1019 
1020    else if (relaxed != 0)
1021    {
1022       /* Allow application (pngtest) errors and warnings to pass */
1023       png_set_benign_errors(read_ptr, 1);
1024 
1025 #ifdef PNG_WRITE_SUPPORTED
1026       png_set_benign_errors(write_ptr, 1);
1027 #endif
1028    }
1029 
1030    pngtest_debug("Initializing input and output streams");
1031 #ifdef PNG_STDIO_SUPPORTED
1032    png_init_io(read_ptr, fpin);
1033 #  ifdef PNG_WRITE_SUPPORTED
1034    png_init_io(write_ptr, fpout);
1035 #  endif
1036 #else
1037    png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
1038 #  ifdef PNG_WRITE_SUPPORTED
1039    png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
1040 #    ifdef PNG_WRITE_FLUSH_SUPPORTED
1041       pngtest_flush);
1042 #    else
1043       NULL);
1044 #    endif
1045 #  endif
1046 #endif
1047 
1048    if (status_dots_requested == 1)
1049    {
1050 #ifdef PNG_WRITE_SUPPORTED
1051       png_set_write_status_fn(write_ptr, write_row_callback);
1052 #endif
1053       png_set_read_status_fn(read_ptr, read_row_callback);
1054    }
1055 
1056    else
1057    {
1058 #ifdef PNG_WRITE_SUPPORTED
1059       png_set_write_status_fn(write_ptr, NULL);
1060 #endif
1061       png_set_read_status_fn(read_ptr, NULL);
1062    }
1063 
1064 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1065    png_set_read_user_transform_fn(read_ptr, read_user_callback);
1066 #endif
1067 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1068    zero_samples = 0;
1069    png_set_write_user_transform_fn(write_ptr, count_zero_samples);
1070 #endif
1071 
1072 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
1073    /* Preserve all the unknown chunks, if possible.  If this is disabled then,
1074     * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
1075     * libpng to *save* the unknown chunks on read (because we can't switch the
1076     * save option on!)
1077     *
1078     * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
1079     * unknown chunks and write will write them all.
1080     */
1081 #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
1082    png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
1083       NULL, 0);
1084 #endif
1085 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1086    png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
1087       NULL, 0);
1088 #endif
1089 #endif
1090 
1091    pngtest_debug("Reading info struct");
1092    png_read_info(read_ptr, read_info_ptr);
1093 
1094 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1095    /* This is a bit of a hack; there is no obvious way in the callback function
1096     * to determine that the chunks before the first IDAT have been read, so
1097     * remove the info_ptr (which is only used to determine position relative to
1098     * PLTE) here to indicate that we are after the IDAT.
1099     */
1100    user_chunk_data.info_ptr = NULL;
1101 #endif
1102 
1103    pngtest_debug("Transferring info struct");
1104    {
1105       int interlace_type, compression_type, filter_type;
1106 
1107       if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
1108           &color_type, &interlace_type, &compression_type, &filter_type) != 0)
1109       {
1110          png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
1111             color_type, interlace_type, compression_type, filter_type);
1112          /* num_passes may not be available below if interlace support is not
1113           * provided by libpng for both read and write.
1114           */
1115          switch (interlace_type)
1116          {
1117             case PNG_INTERLACE_NONE:
1118                num_passes = 1;
1119                break;
1120 
1121             case PNG_INTERLACE_ADAM7:
1122                num_passes = 7;
1123                break;
1124 
1125             default:
1126                png_error(read_ptr, "invalid interlace type");
1127                /*NOT REACHED*/
1128          }
1129       }
1130 
1131       else
1132          png_error(read_ptr, "png_get_IHDR failed");
1133    }
1134 #ifdef PNG_FIXED_POINT_SUPPORTED
1135 #ifdef PNG_cHRM_SUPPORTED
1136    {
1137       png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
1138          blue_y;
1139 
1140       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y,
1141          &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
1142       {
1143          png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
1144             red_y, green_x, green_y, blue_x, blue_y);
1145       }
1146    }
1147 #endif
1148 #ifdef PNG_gAMA_SUPPORTED
1149    {
1150       png_fixed_point gamma;
1151 
1152       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0)
1153          png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
1154    }
1155 #endif
1156 #else /* Use floating point versions */
1157 #ifdef PNG_FLOATING_POINT_SUPPORTED
1158 #ifdef PNG_cHRM_SUPPORTED
1159    {
1160       double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
1161          blue_y;
1162 
1163       if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
1164          &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
1165       {
1166          png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
1167             red_y, green_x, green_y, blue_x, blue_y);
1168       }
1169    }
1170 #endif
1171 #ifdef PNG_gAMA_SUPPORTED
1172    {
1173       double gamma;
1174 
1175       if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0)
1176          png_set_gAMA(write_ptr, write_info_ptr, gamma);
1177    }
1178 #endif
1179 #endif /* Floating point */
1180 #endif /* Fixed point */
1181 #ifdef PNG_iCCP_SUPPORTED
1182    {
1183       png_charp name;
1184       png_bytep profile;
1185       png_uint_32 proflen;
1186       int compression_type;
1187 
1188       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
1189                       &profile, &proflen) != 0)
1190       {
1191          png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
1192                       profile, proflen);
1193       }
1194    }
1195 #endif
1196 #ifdef PNG_sRGB_SUPPORTED
1197    {
1198       int intent;
1199 
1200       if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0)
1201          png_set_sRGB(write_ptr, write_info_ptr, intent);
1202    }
1203 #endif
1204    {
1205       png_colorp palette;
1206       int num_palette;
1207 
1208       if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)
1209          png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
1210    }
1211 #ifdef PNG_bKGD_SUPPORTED
1212    {
1213       png_color_16p background;
1214 
1215       if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
1216       {
1217          png_set_bKGD(write_ptr, write_info_ptr, background);
1218       }
1219    }
1220 #endif
1221 #ifdef PNG_hIST_SUPPORTED
1222    {
1223       png_uint_16p hist;
1224 
1225       if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0)
1226          png_set_hIST(write_ptr, write_info_ptr, hist);
1227    }
1228 #endif
1229 #ifdef PNG_oFFs_SUPPORTED
1230    {
1231       png_int_32 offset_x, offset_y;
1232       int unit_type;
1233 
1234       if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
1235           &unit_type) != 0)
1236       {
1237          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
1238       }
1239    }
1240 #endif
1241 #ifdef PNG_pCAL_SUPPORTED
1242    {
1243       png_charp purpose, units;
1244       png_charpp params;
1245       png_int_32 X0, X1;
1246       int type, nparams;
1247 
1248       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
1249          &nparams, &units, &params) != 0)
1250       {
1251          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
1252             nparams, units, params);
1253       }
1254    }
1255 #endif
1256 #ifdef PNG_pHYs_SUPPORTED
1257    {
1258       png_uint_32 res_x, res_y;
1259       int unit_type;
1260 
1261       if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y,
1262           &unit_type) != 0)
1263          png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
1264    }
1265 #endif
1266 #ifdef PNG_sBIT_SUPPORTED
1267    {
1268       png_color_8p sig_bit;
1269 
1270       if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0)
1271          png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
1272    }
1273 #endif
1274 #ifdef PNG_sCAL_SUPPORTED
1275 #if defined(PNG_FLOATING_POINT_SUPPORTED) && \
1276    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
1277    {
1278       int unit;
1279       double scal_width, scal_height;
1280 
1281       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
1282          &scal_height) != 0)
1283       {
1284          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
1285       }
1286    }
1287 #else
1288 #ifdef PNG_FIXED_POINT_SUPPORTED
1289    {
1290       int unit;
1291       png_charp scal_width, scal_height;
1292 
1293       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
1294           &scal_height) != 0)
1295       {
1296          png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,
1297              scal_height);
1298       }
1299    }
1300 #endif
1301 #endif
1302 #endif
1303 
1304 #ifdef PNG_sPLT_SUPPORTED
1305    {
1306        png_sPLT_tp entries;
1307 
1308        int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);
1309        if (num_entries)
1310        {
1311            png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
1312        }
1313    }
1314 #endif
1315 
1316 #ifdef PNG_TEXT_SUPPORTED
1317    {
1318       png_textp text_ptr;
1319       int num_text;
1320 
1321       if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
1322       {
1323          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
1324 
1325          pngtest_check_text_support(read_ptr, text_ptr, num_text);
1326 
1327          if (verbose != 0)
1328          {
1329             int i;
1330 
1331             printf("\n");
1332             for (i=0; i<num_text; i++)
1333             {
1334                printf("   Text compression[%d]=%d\n",
1335                      i, text_ptr[i].compression);
1336             }
1337          }
1338 
1339          png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
1340       }
1341    }
1342 #endif
1343 #ifdef PNG_tIME_SUPPORTED
1344    {
1345       png_timep mod_time;
1346 
1347       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time) != 0)
1348       {
1349          png_set_tIME(write_ptr, write_info_ptr, mod_time);
1350 #ifdef PNG_TIME_RFC1123_SUPPORTED
1351          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
1352             tIME_string[(sizeof tIME_string) - 1] = '\0';
1353 
1354          else
1355          {
1356             strncpy(tIME_string, "*** invalid time ***", (sizeof tIME_string));
1357             tIME_string[(sizeof tIME_string) - 1] = '\0';
1358          }
1359 
1360          tIME_chunk_present++;
1361 #endif /* TIME_RFC1123 */
1362       }
1363    }
1364 #endif
1365 #ifdef PNG_tRNS_SUPPORTED
1366    {
1367       png_bytep trans_alpha;
1368       int num_trans;
1369       png_color_16p trans_color;
1370 
1371       if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans,
1372          &trans_color) != 0)
1373       {
1374          int sample_max = (1 << bit_depth);
1375          /* libpng doesn't reject a tRNS chunk with out-of-range samples */
1376          if (!((color_type == PNG_COLOR_TYPE_GRAY &&
1377              (int)trans_color->gray > sample_max) ||
1378              (color_type == PNG_COLOR_TYPE_RGB &&
1379              ((int)trans_color->red > sample_max ||
1380              (int)trans_color->green > sample_max ||
1381              (int)trans_color->blue > sample_max))))
1382             png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans,
1383                trans_color);
1384       }
1385    }
1386 #endif
1387 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1388    {
1389       png_unknown_chunkp unknowns;
1390       int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr,
1391          &unknowns);
1392 
1393       if (num_unknowns != 0)
1394       {
1395          png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
1396            num_unknowns);
1397 #if PNG_LIBPNG_VER < 10600
1398          /* Copy the locations from the read_info_ptr.  The automatically
1399           * generated locations in write_end_info_ptr are wrong prior to 1.6.0
1400           * because they are reset from the write pointer (removed in 1.6.0).
1401           */
1402          {
1403             int i;
1404             for (i = 0; i < num_unknowns; i++)
1405               png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
1406                 unknowns[i].location);
1407          }
1408 #endif
1409       }
1410    }
1411 #endif
1412 
1413 #ifdef PNG_WRITE_SUPPORTED
1414    pngtest_debug("Writing info struct");
1415 
1416    /* Write the info in two steps so that if we write the 'unknown' chunks here
1417     * they go to the correct place.
1418     */
1419    png_write_info_before_PLTE(write_ptr, write_info_ptr);
1420 
1421    write_chunks(write_ptr, before_PLTE); /* before PLTE */
1422 
1423    png_write_info(write_ptr, write_info_ptr);
1424 
1425    write_chunks(write_ptr, before_IDAT); /* after PLTE */
1426 #endif
1427 
1428 #ifdef SINGLE_ROWBUF_ALLOC
1429    pngtest_debug("Allocating row buffer...");
1430    row_buf = (png_bytep)png_malloc(read_ptr,
1431       png_get_rowbytes(read_ptr, read_info_ptr));
1432 
1433    pngtest_debug1("\t0x%08lx", (unsigned long)row_buf);
1434 #endif /* SINGLE_ROWBUF_ALLOC */
1435    pngtest_debug("Writing row data");
1436 
1437 #if defined(PNG_READ_INTERLACING_SUPPORTED) &&\
1438    defined(PNG_WRITE_INTERLACING_SUPPORTED)
1439    /* Both must be defined for libpng to be able to handle the interlace,
1440     * otherwise it gets handled below by simply reading and writing the passes
1441     * directly.
1442     */
1443    if (png_set_interlace_handling(read_ptr) != num_passes)
1444       png_error(write_ptr,
1445             "png_set_interlace_handling(read): wrong pass count ");
1446    if (png_set_interlace_handling(write_ptr) != num_passes)
1447       png_error(write_ptr,
1448             "png_set_interlace_handling(write): wrong pass count ");
1449 #else /* png_set_interlace_handling not called on either read or write */
1450 #  define calc_pass_height
1451 #endif /* not using libpng interlace handling */
1452 
1453 #ifdef PNGTEST_TIMING
1454    t_stop = (float)clock();
1455    t_misc += (t_stop - t_start);
1456    t_start = t_stop;
1457 #endif
1458    for (pass = 0; pass < num_passes; pass++)
1459    {
1460 #     ifdef calc_pass_height
1461          png_uint_32 pass_height;
1462 
1463          if (num_passes == 7) /* interlaced */
1464          {
1465             if (PNG_PASS_COLS(width, pass) > 0)
1466                pass_height = PNG_PASS_ROWS(height, pass);
1467 
1468             else
1469                pass_height = 0;
1470          }
1471 
1472          else /* not interlaced */
1473             pass_height = height;
1474 #     else
1475 #        define pass_height height
1476 #     endif
1477 
1478       pngtest_debug1("Writing row data for pass %d", pass);
1479       for (y = 0; y < pass_height; y++)
1480       {
1481 #ifndef SINGLE_ROWBUF_ALLOC
1482          pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
1483 
1484          row_buf = (png_bytep)png_malloc(read_ptr,
1485             png_get_rowbytes(read_ptr, read_info_ptr));
1486 
1487          pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
1488             (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
1489 
1490 #endif /* !SINGLE_ROWBUF_ALLOC */
1491          png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
1492 
1493 #ifdef PNG_WRITE_SUPPORTED
1494 #ifdef PNGTEST_TIMING
1495          t_stop = (float)clock();
1496          t_decode += (t_stop - t_start);
1497          t_start = t_stop;
1498 #endif
1499          png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
1500 #ifdef PNGTEST_TIMING
1501          t_stop = (float)clock();
1502          t_encode += (t_stop - t_start);
1503          t_start = t_stop;
1504 #endif
1505 #endif /* WRITE */
1506 
1507 #ifndef SINGLE_ROWBUF_ALLOC
1508          pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
1509          png_free(read_ptr, row_buf);
1510          row_buf = NULL;
1511 #endif /* !SINGLE_ROWBUF_ALLOC */
1512       }
1513    }
1514 
1515 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
1516 #  ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
1517       png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
1518 #  endif
1519 #  ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1520       png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
1521 #  endif
1522 #endif
1523 
1524    pngtest_debug("Reading and writing end_info data");
1525 
1526    png_read_end(read_ptr, end_info_ptr);
1527 #ifdef PNG_TEXT_SUPPORTED
1528    {
1529       png_textp text_ptr;
1530       int num_text;
1531 
1532       if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
1533       {
1534          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
1535 
1536          pngtest_check_text_support(read_ptr, text_ptr, num_text);
1537 
1538          if (verbose != 0)
1539          {
1540             int i;
1541 
1542             printf("\n");
1543             for (i=0; i<num_text; i++)
1544             {
1545                printf("   Text compression[%d]=%d\n",
1546                      i, text_ptr[i].compression);
1547             }
1548          }
1549 
1550          png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
1551       }
1552    }
1553 #endif
1554 #ifdef PNG_tIME_SUPPORTED
1555    {
1556       png_timep mod_time;
1557 
1558       if (png_get_tIME(read_ptr, end_info_ptr, &mod_time) != 0)
1559       {
1560          png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
1561 #ifdef PNG_TIME_RFC1123_SUPPORTED
1562          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
1563             tIME_string[(sizeof tIME_string) - 1] = '\0';
1564 
1565          else
1566          {
1567             strncpy(tIME_string, "*** invalid time ***", sizeof tIME_string);
1568             tIME_string[(sizeof tIME_string)-1] = '\0';
1569          }
1570 
1571          tIME_chunk_present++;
1572 #endif /* TIME_RFC1123 */
1573       }
1574    }
1575 #endif
1576 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1577    {
1578       png_unknown_chunkp unknowns;
1579       int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr,
1580          &unknowns);
1581 
1582       if (num_unknowns != 0)
1583       {
1584          png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
1585            num_unknowns);
1586 #if PNG_LIBPNG_VER < 10600
1587          /* Copy the locations from the read_info_ptr.  The automatically
1588           * generated locations in write_end_info_ptr are wrong prior to 1.6.0
1589           * because they are reset from the write pointer (removed in 1.6.0).
1590           */
1591          {
1592             int i;
1593             for (i = 0; i < num_unknowns; i++)
1594               png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
1595                 unknowns[i].location);
1596          }
1597 #endif
1598       }
1599    }
1600 #endif
1601 
1602 #ifdef PNG_WRITE_SUPPORTED
1603 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1604    /* Normally one would use Z_DEFAULT_STRATEGY for text compression.
1605     * This is here just to make pngtest replicate the results from libpng
1606     * versions prior to 1.5.4, and to test this new API.
1607     */
1608    png_set_text_compression_strategy(write_ptr, Z_FILTERED);
1609 #endif
1610 
1611    /* When the unknown vpAg/sTER chunks are written by pngtest the only way to
1612     * do it is to write them *before* calling png_write_end.  When unknown
1613     * chunks are written by libpng, however, they are written just before IEND.
1614     * There seems to be no way round this, however vpAg/sTER are not expected
1615     * after IDAT.
1616     */
1617    write_chunks(write_ptr, after_IDAT);
1618 
1619    png_write_end(write_ptr, write_end_info_ptr);
1620 #endif
1621 
1622 #ifdef PNG_EASY_ACCESS_SUPPORTED
1623    if (verbose != 0)
1624    {
1625       png_uint_32 iwidth, iheight;
1626       iwidth = png_get_image_width(write_ptr, write_info_ptr);
1627       iheight = png_get_image_height(write_ptr, write_info_ptr);
1628       fprintf(STDERR, "\n Image width = %lu, height = %lu\n",
1629          (unsigned long)iwidth, (unsigned long)iheight);
1630    }
1631 #endif
1632 
1633    pngtest_debug("Destroying data structs");
1634 #ifdef SINGLE_ROWBUF_ALLOC
1635    pngtest_debug("destroying row_buf for read_ptr");
1636    png_free(read_ptr, row_buf);
1637    row_buf = NULL;
1638 #endif /* SINGLE_ROWBUF_ALLOC */
1639    pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr");
1640    png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
1641 #ifdef PNG_WRITE_SUPPORTED
1642    pngtest_debug("destroying write_end_info_ptr");
1643    png_destroy_info_struct(write_ptr, &write_end_info_ptr);
1644    pngtest_debug("destroying write_ptr, write_info_ptr");
1645    png_destroy_write_struct(&write_ptr, &write_info_ptr);
1646 #endif
1647    pngtest_debug("Destruction complete.");
1648 
1649    FCLOSE(fpin);
1650    FCLOSE(fpout);
1651 
1652    /* Summarize any warnings or errors and in 'strict' mode fail the test.
1653     * Unsupported chunks can result in warnings, in that case ignore the strict
1654     * setting, otherwise fail the test on warnings as well as errors.
1655     */
1656    if (error_count > 0)
1657    {
1658       /* We don't really expect to get here because of the setjmp handling
1659        * above, but this is safe.
1660        */
1661       fprintf(STDERR, "\n  %s: %d libpng errors found (%d warnings)",
1662          inname, error_count, warning_count);
1663 
1664       if (strict != 0)
1665          return (1);
1666    }
1667 
1668 #  ifdef PNG_WRITE_SUPPORTED
1669       /* If there is no write support nothing was written! */
1670       else if (unsupported_chunks > 0)
1671       {
1672          fprintf(STDERR, "\n  %s: unsupported chunks (%d)%s",
1673             inname, unsupported_chunks, strict ? ": IGNORED --strict!" : "");
1674       }
1675 #  endif
1676 
1677    else if (warning_count > 0)
1678    {
1679       fprintf(STDERR, "\n  %s: %d libpng warnings found",
1680          inname, warning_count);
1681 
1682       if (strict != 0)
1683          return (1);
1684    }
1685 
1686    pngtest_debug("Opening files for comparison");
1687    if ((fpin = fopen(inname, "rb")) == NULL)
1688    {
1689       fprintf(STDERR, "Could not find file %s\n", inname);
1690       return (1);
1691    }
1692 
1693    if ((fpout = fopen(outname, "rb")) == NULL)
1694    {
1695       fprintf(STDERR, "Could not find file %s\n", outname);
1696       FCLOSE(fpin);
1697       return (1);
1698    }
1699 
1700 #if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\
1701     defined (PNG_WRITE_FILTER_SUPPORTED)
1702    if (interlace_preserved != 0) /* else the files will be changed */
1703    {
1704       for (;;)
1705       {
1706          static int wrote_question = 0;
1707          png_size_t num_in, num_out;
1708          char inbuf[256], outbuf[256];
1709 
1710          num_in = fread(inbuf, 1, sizeof inbuf, fpin);
1711          num_out = fread(outbuf, 1, sizeof outbuf, fpout);
1712 
1713          if (num_in != num_out)
1714          {
1715             fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
1716                     inname, outname);
1717 
1718             if (wrote_question == 0 && unsupported_chunks == 0)
1719             {
1720                fprintf(STDERR,
1721          "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
1722                  inname, PNG_ZBUF_SIZE);
1723                fprintf(STDERR,
1724                  "\n   filtering heuristic (libpng default), compression");
1725                fprintf(STDERR,
1726                  " level (zlib default),\n   and zlib version (%s)?\n\n",
1727                  ZLIB_VERSION);
1728                wrote_question = 1;
1729             }
1730 
1731             FCLOSE(fpin);
1732             FCLOSE(fpout);
1733 
1734             if (strict != 0 && unsupported_chunks == 0)
1735               return (1);
1736 
1737             else
1738               return (0);
1739          }
1740 
1741          if (num_in == 0)
1742             break;
1743 
1744          if (memcmp(inbuf, outbuf, num_in))
1745          {
1746             fprintf(STDERR, "\nFiles %s and %s are different\n", inname,
1747                outname);
1748 
1749             if (wrote_question == 0 && unsupported_chunks == 0)
1750             {
1751                fprintf(STDERR,
1752          "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
1753                     inname, PNG_ZBUF_SIZE);
1754                fprintf(STDERR,
1755                  "\n   filtering heuristic (libpng default), compression");
1756                fprintf(STDERR,
1757                  " level (zlib default),\n   and zlib version (%s)?\n\n",
1758                  ZLIB_VERSION);
1759                wrote_question = 1;
1760             }
1761 
1762             FCLOSE(fpin);
1763             FCLOSE(fpout);
1764 
1765             /* NOTE: the unsupported_chunks escape is permitted here because
1766              * unsupported text chunk compression will result in the compression
1767              * mode being changed (to NONE) yet, in the test case, the result
1768              * can be exactly the same size!
1769              */
1770             if (strict != 0 && unsupported_chunks == 0)
1771               return (1);
1772 
1773             else
1774               return (0);
1775          }
1776       }
1777    }
1778 #endif /* WRITE && WRITE_FILTER */
1779 
1780    FCLOSE(fpin);
1781    FCLOSE(fpout);
1782 
1783    return (0);
1784 }
1785 
1786 /* Input and output filenames */
1787 #ifdef RISCOS
1788 static PNG_CONST char *inname = "pngtest/png";
1789 static PNG_CONST char *outname = "pngout/png";
1790 #else
1791 static PNG_CONST char *inname = "pngtest.png";
1792 static PNG_CONST char *outname = "pngout.png";
1793 #endif
1794 
1795 int
1796 main(int argc, char *argv[])
1797 {
1798    int multiple = 0;
1799    int ierror = 0;
1800 
1801    png_structp dummy_ptr;
1802 
1803    fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
1804    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
1805    fprintf(STDERR, "%s", png_get_copyright(NULL));
1806    /* Show the version of libpng used in building the library */
1807    fprintf(STDERR, " library (%lu):%s",
1808       (unsigned long)png_access_version_number(),
1809       png_get_header_version(NULL));
1810 
1811    /* Show the version of libpng used in building the application */
1812    fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
1813       PNG_HEADER_VERSION_STRING);
1814 
1815    /* Do some consistency checking on the memory allocation settings, I'm
1816     * not sure this matters, but it is nice to know, the first of these
1817     * tests should be impossible because of the way the macros are set
1818     * in pngconf.h
1819     */
1820 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
1821       fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
1822 #endif
1823    /* I think the following can happen. */
1824 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
1825       fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
1826 #endif
1827 
1828    if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
1829    {
1830       fprintf(STDERR,
1831          "Warning: versions are different between png.h and png.c\n");
1832       fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
1833       fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
1834       ++ierror;
1835    }
1836 
1837    if (argc > 1)
1838    {
1839       if (strcmp(argv[1], "-m") == 0)
1840       {
1841          multiple = 1;
1842          status_dots_requested = 0;
1843       }
1844 
1845       else if (strcmp(argv[1], "-mv") == 0 ||
1846                strcmp(argv[1], "-vm") == 0 )
1847       {
1848          multiple = 1;
1849          verbose = 1;
1850          status_dots_requested = 1;
1851       }
1852 
1853       else if (strcmp(argv[1], "-v") == 0)
1854       {
1855          verbose = 1;
1856          status_dots_requested = 1;
1857          inname = argv[2];
1858       }
1859 
1860       else if (strcmp(argv[1], "--strict") == 0)
1861       {
1862          status_dots_requested = 0;
1863          verbose = 1;
1864          inname = argv[2];
1865          strict++;
1866          relaxed = 0;
1867       }
1868 
1869       else if (strcmp(argv[1], "--relaxed") == 0)
1870       {
1871          status_dots_requested = 0;
1872          verbose = 1;
1873          inname = argv[2];
1874          strict = 0;
1875          relaxed++;
1876       }
1877 
1878       else
1879       {
1880          inname = argv[1];
1881          status_dots_requested = 0;
1882       }
1883    }
1884 
1885    if (multiple == 0 && argc == 3 + verbose)
1886      outname = argv[2 + verbose];
1887 
1888    if ((multiple == 0 && argc > 3 + verbose) ||
1889        (multiple != 0 && argc < 2))
1890    {
1891      fprintf(STDERR,
1892        "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
1893         argv[0], argv[0]);
1894      fprintf(STDERR,
1895        "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
1896      fprintf(STDERR,
1897        "  with -m %s is used as a temporary file\n", outname);
1898      exit(1);
1899    }
1900 
1901    if (multiple != 0)
1902    {
1903       int i;
1904 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1905       int allocation_now = current_allocation;
1906 #endif
1907       for (i=2; i<argc; ++i)
1908       {
1909          int kerror;
1910          fprintf(STDERR, "\n Testing %s:", argv[i]);
1911 #if PNG_DEBUG > 0
1912          fprintf(STDERR, "\n");
1913 #endif
1914          kerror = test_one_file(argv[i], outname);
1915          if (kerror == 0)
1916          {
1917 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1918             fprintf(STDERR, "\n PASS (%lu zero samples)\n",
1919                (unsigned long)zero_samples);
1920 #else
1921             fprintf(STDERR, " PASS\n");
1922 #endif
1923 #ifdef PNG_TIME_RFC1123_SUPPORTED
1924             if (tIME_chunk_present != 0)
1925                fprintf(STDERR, " tIME = %s\n", tIME_string);
1926 
1927             tIME_chunk_present = 0;
1928 #endif /* TIME_RFC1123 */
1929          }
1930 
1931          else
1932          {
1933             fprintf(STDERR, " FAIL\n");
1934             ierror += kerror;
1935          }
1936 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1937          if (allocation_now != current_allocation)
1938             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
1939                current_allocation - allocation_now);
1940 
1941          if (current_allocation != 0)
1942          {
1943             memory_infop pinfo = pinformation;
1944 
1945             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
1946                current_allocation);
1947 
1948             while (pinfo != NULL)
1949             {
1950                fprintf(STDERR, " %lu bytes at %p\n",
1951                  (unsigned long)pinfo->size,
1952                  pinfo->pointer);
1953                pinfo = pinfo->next;
1954             }
1955          }
1956 #endif
1957       }
1958 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1959          fprintf(STDERR, " Current memory allocation: %10d bytes\n",
1960             current_allocation);
1961          fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
1962             maximum_allocation);
1963          fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
1964             total_allocation);
1965          fprintf(STDERR, "     Number of allocations: %10d\n",
1966             num_allocations);
1967 #endif
1968    }
1969 
1970    else
1971    {
1972       int i;
1973       for (i = 0; i<3; ++i)
1974       {
1975          int kerror;
1976 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1977          int allocation_now = current_allocation;
1978 #endif
1979          if (i == 1)
1980             status_dots_requested = 1;
1981 
1982          else if (verbose == 0)
1983             status_dots_requested = 0;
1984 
1985          if (i == 0 || verbose == 1 || ierror != 0)
1986          {
1987             fprintf(STDERR, "\n Testing %s:", inname);
1988 #if PNG_DEBUG > 0
1989             fprintf(STDERR, "\n");
1990 #endif
1991          }
1992 
1993          kerror = test_one_file(inname, outname);
1994 
1995          if (kerror == 0)
1996          {
1997             if (verbose == 1 || i == 2)
1998             {
1999 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
2000                 fprintf(STDERR, "\n PASS (%lu zero samples)\n",
2001                    (unsigned long)zero_samples);
2002 #else
2003                 fprintf(STDERR, " PASS\n");
2004 #endif
2005 #ifdef PNG_TIME_RFC1123_SUPPORTED
2006              if (tIME_chunk_present != 0)
2007                 fprintf(STDERR, " tIME = %s\n", tIME_string);
2008 #endif /* TIME_RFC1123 */
2009             }
2010          }
2011 
2012          else
2013          {
2014             if (verbose == 0 && i != 2)
2015             {
2016                fprintf(STDERR, "\n Testing %s:", inname);
2017 #if PNG_DEBUG > 0
2018                fprintf(STDERR, "\n");
2019 #endif
2020             }
2021 
2022             fprintf(STDERR, " FAIL\n");
2023             ierror += kerror;
2024          }
2025 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
2026          if (allocation_now != current_allocation)
2027              fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
2028                current_allocation - allocation_now);
2029 
2030          if (current_allocation != 0)
2031          {
2032              memory_infop pinfo = pinformation;
2033 
2034              fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
2035                 current_allocation);
2036 
2037              while (pinfo != NULL)
2038              {
2039                 fprintf(STDERR, " %lu bytes at %p\n",
2040                    (unsigned long)pinfo->size, pinfo->pointer);
2041                 pinfo = pinfo->next;
2042              }
2043           }
2044 #endif
2045        }
2046 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
2047        fprintf(STDERR, " Current memory allocation: %10d bytes\n",
2048           current_allocation);
2049        fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
2050           maximum_allocation);
2051        fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
2052           total_allocation);
2053        fprintf(STDERR, "     Number of allocations: %10d\n",
2054             num_allocations);
2055 #endif
2056    }
2057 
2058 #ifdef PNGTEST_TIMING
2059    t_stop = (float)clock();
2060    t_misc += (t_stop - t_start);
2061    t_start = t_stop;
2062    fprintf(STDERR, " CPU time used = %.3f seconds",
2063       (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
2064    fprintf(STDERR, " (decoding %.3f,\n",
2065       t_decode/(float)CLOCKS_PER_SEC);
2066    fprintf(STDERR, "        encoding %.3f ,",
2067       t_encode/(float)CLOCKS_PER_SEC);
2068    fprintf(STDERR, " other %.3f seconds)\n\n",
2069       t_misc/(float)CLOCKS_PER_SEC);
2070 #endif
2071 
2072    if (ierror == 0)
2073       fprintf(STDERR, " libpng passes test\n");
2074 
2075    else
2076       fprintf(STDERR, " libpng FAILS test\n");
2077 
2078    dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
2079    fprintf(STDERR, " Default limits:\n");
2080    fprintf(STDERR, "  width_max  = %lu\n",
2081       (unsigned long) png_get_user_width_max(dummy_ptr));
2082    fprintf(STDERR, "  height_max = %lu\n",
2083       (unsigned long) png_get_user_height_max(dummy_ptr));
2084    if (png_get_chunk_cache_max(dummy_ptr) == 0)
2085       fprintf(STDERR, "  cache_max  = unlimited\n");
2086    else
2087       fprintf(STDERR, "  cache_max  = %lu\n",
2088          (unsigned long) png_get_chunk_cache_max(dummy_ptr));
2089    if (png_get_chunk_malloc_max(dummy_ptr) == 0)
2090       fprintf(STDERR, "  malloc_max = unlimited\n");
2091    else
2092       fprintf(STDERR, "  malloc_max = %lu\n",
2093          (unsigned long) png_get_chunk_malloc_max(dummy_ptr));
2094    png_destroy_read_struct(&dummy_ptr, NULL, NULL);
2095 
2096    return (int)(ierror != 0);
2097 }
2098 #else
2099 int
2100 main(void)
2101 {
2102    fprintf(STDERR,
2103       " test ignored because libpng was not built with read support\n");
2104    /* And skip this test */
2105    return SKIP;
2106 }
2107 #endif
2108 
2109 /* Generate a compiler error if there is an old png.h in the search path. */
2110 typedef png_libpng_version_1_6_23 Your_png_h_is_not_version_1_6_23;