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