• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* pngtest.c - a simple test program to test libpng
3  *
4  * Last changed in libpng 1.6.25 [September 1, 2016]
5  * Copyright (c) 1998-2002,2004,2006-2016 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 png_alloc_size_t current_allocation = 0;
518 static png_alloc_size_t maximum_allocation = 0;
519 static png_alloc_size_t total_allocation = 0;
520 static png_alloc_size_t 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             if (current_allocation < pinfo->size)
608                fprintf(STDERR, "Duplicate free of memory\n");
609             else
610                current_allocation -= pinfo->size;
611             /* We must free the list element too, but first kill
612                the memory that is to be freed. */
613             memset(ptr, 0x55, pinfo->size);
614             free(pinfo);
615             pinfo = NULL;
616             break;
617          }
618 
619          if (pinfo->next == NULL)
620          {
621             fprintf(STDERR, "Pointer %p not found\n", ptr);
622             break;
623          }
624 
625          ppinfo = &pinfo->next;
626       }
627    }
628 
629    /* Finally free the data. */
630    if (verbose != 0)
631       printf("Freeing %p\n", ptr);
632 
633    if (ptr != NULL)
634       free(ptr);
635    ptr = NULL;
636 }
637 #endif /* USER_MEM && DEBUG */
638 /* END of code to test memory allocation/deallocation */
639 
640 
641 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
642 /* Demonstration of user chunk support of the sTER and vpAg chunks */
643 
644 /* (sTER is a public chunk not yet known by libpng.  vpAg is a private
645 chunk used in ImageMagick to store "virtual page" size).  */
646 
647 static struct user_chunk_data
648 {
649    png_const_infop info_ptr;
650    png_uint_32     vpAg_width, vpAg_height;
651    png_byte        vpAg_units;
652    png_byte        sTER_mode;
653    int             location[2];
654 }
655 user_chunk_data;
656 
657 /* Used for location and order; zero means nothing. */
658 #define have_sTER   0x01
659 #define have_vpAg   0x02
660 #define before_PLTE 0x10
661 #define before_IDAT 0x20
662 #define after_IDAT  0x40
663 
664 static void
init_callback_info(png_const_infop info_ptr)665 init_callback_info(png_const_infop info_ptr)
666 {
667    MEMZERO(user_chunk_data);
668    user_chunk_data.info_ptr = info_ptr;
669 }
670 
671 static int
set_location(png_structp png_ptr,struct user_chunk_data * data,int what)672 set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
673 {
674    int location;
675 
676    if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
677       return 0; /* already have one of these */
678 
679    /* Find where we are (the code below zeroes info_ptr to indicate that the
680     * chunks before the first IDAT have been read.)
681     */
682    if (data->info_ptr == NULL) /* after IDAT */
683       location = what | after_IDAT;
684 
685    else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
686       location = what | before_IDAT;
687 
688    else
689       location = what | before_PLTE;
690 
691    if (data->location[0] == 0)
692       data->location[0] = location;
693 
694    else
695       data->location[1] = location;
696 
697    return 1; /* handled */
698 }
699 
700 static int PNGCBAPI
read_user_chunk_callback(png_struct * png_ptr,png_unknown_chunkp chunk)701 read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
702 {
703    struct user_chunk_data *my_user_chunk_data =
704       (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
705 
706    if (my_user_chunk_data == NULL)
707       png_error(png_ptr, "lost user chunk pointer");
708 
709    /* Return one of the following:
710     *    return (-n);  chunk had an error
711     *    return (0);  did not recognize
712     *    return (n);  success
713     *
714     * The unknown chunk structure contains the chunk data:
715     * png_byte name[5];
716     * png_byte *data;
717     * png_size_t size;
718     *
719     * Note that libpng has already taken care of the CRC handling.
720     */
721 
722    if (chunk->name[0] == 115 && chunk->name[1] ==  84 &&     /* s  T */
723        chunk->name[2] ==  69 && chunk->name[3] ==  82)       /* E  R */
724       {
725          /* Found sTER chunk */
726          if (chunk->size != 1)
727             return (-1); /* Error return */
728 
729          if (chunk->data[0] != 0 && chunk->data[0] != 1)
730             return (-1);  /* Invalid mode */
731 
732          if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
733          {
734             my_user_chunk_data->sTER_mode=chunk->data[0];
735             return (1);
736          }
737 
738          else
739             return (0); /* duplicate sTER - give it to libpng */
740       }
741 
742    if (chunk->name[0] != 118 || chunk->name[1] != 112 ||    /* v  p */
743        chunk->name[2] !=  65 || chunk->name[3] != 103)      /* A  g */
744       return (0); /* Did not recognize */
745 
746    /* Found ImageMagick vpAg chunk */
747 
748    if (chunk->size != 9)
749       return (-1); /* Error return */
750 
751    if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
752       return (0);  /* duplicate vpAg */
753 
754    my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
755    my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);
756    my_user_chunk_data->vpAg_units = chunk->data[8];
757 
758    return (1);
759 }
760 
761 #ifdef PNG_WRITE_SUPPORTED
762 static void
write_sTER_chunk(png_structp write_ptr)763 write_sTER_chunk(png_structp write_ptr)
764 {
765    png_byte sTER[5] = {115,  84,  69,  82, '\0'};
766 
767    if (verbose != 0)
768       fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
769 
770    png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
771 }
772 
773 static void
write_vpAg_chunk(png_structp write_ptr)774 write_vpAg_chunk(png_structp write_ptr)
775 {
776    png_byte vpAg[5] = {118, 112,  65, 103, '\0'};
777 
778    png_byte vpag_chunk_data[9];
779 
780    if (verbose != 0)
781       fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
782           (unsigned long)user_chunk_data.vpAg_width,
783           (unsigned long)user_chunk_data.vpAg_height,
784           user_chunk_data.vpAg_units);
785 
786    png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
787    png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
788    vpag_chunk_data[8] = user_chunk_data.vpAg_units;
789    png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
790 }
791 
792 static void
write_chunks(png_structp write_ptr,int location)793 write_chunks(png_structp write_ptr, int location)
794 {
795    int i;
796 
797    /* Notice that this preserves the original chunk order, however chunks
798     * intercepted by the callback will be written *after* chunks passed to
799     * libpng.  This will actually reverse a pair of sTER chunks or a pair of
800     * vpAg chunks, resulting in an error later.  This is not worth worrying
801     * about - the chunks should not be duplicated!
802     */
803    for (i=0; i<2; ++i)
804    {
805       if (user_chunk_data.location[i] == (location | have_sTER))
806          write_sTER_chunk(write_ptr);
807 
808       else if (user_chunk_data.location[i] == (location | have_vpAg))
809          write_vpAg_chunk(write_ptr);
810    }
811 }
812 #endif /* WRITE */
813 #else /* !READ_USER_CHUNKS */
814 #  define write_chunks(pp,loc) ((void)0)
815 #endif
816 /* END of code to demonstrate user chunk support */
817 
818 /* START of code to check that libpng has the required text support; this only
819  * checks for the write support because if read support is missing the chunk
820  * will simply not be reported back to pngtest.
821  */
822 #ifdef PNG_TEXT_SUPPORTED
823 static void
pngtest_check_text_support(png_structp png_ptr,png_textp text_ptr,int num_text)824 pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr,
825     int num_text)
826 {
827    while (num_text > 0)
828    {
829       switch (text_ptr[--num_text].compression)
830       {
831          case PNG_TEXT_COMPRESSION_NONE:
832             break;
833 
834          case PNG_TEXT_COMPRESSION_zTXt:
835 #           ifndef PNG_WRITE_zTXt_SUPPORTED
836                ++unsupported_chunks;
837                /* In libpng 1.7 this now does an app-error, so stop it: */
838                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
839 #           endif
840             break;
841 
842          case PNG_ITXT_COMPRESSION_NONE:
843          case PNG_ITXT_COMPRESSION_zTXt:
844 #           ifndef PNG_WRITE_iTXt_SUPPORTED
845                ++unsupported_chunks;
846                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
847 #           endif
848             break;
849 
850          default:
851             /* This is an error */
852             png_error(png_ptr, "invalid text chunk compression field");
853             break;
854       }
855    }
856 }
857 #endif
858 /* END of code to check that libpng has the required text support */
859 
860 /* Test one file */
861 static int
test_one_file(PNG_CONST char * inname,PNG_CONST char * outname)862 test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
863 {
864    static png_FILE_p fpin;
865    static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
866    pngtest_error_parameters error_parameters;
867    png_structp read_ptr;
868    png_infop read_info_ptr, end_info_ptr;
869 #ifdef PNG_WRITE_SUPPORTED
870    png_structp write_ptr;
871    png_infop write_info_ptr;
872    png_infop write_end_info_ptr;
873 #ifdef PNG_WRITE_FILTER_SUPPORTED
874    int interlace_preserved = 1;
875 #endif /* WRITE_FILTER */
876 #else /* !WRITE */
877    png_structp write_ptr = NULL;
878    png_infop write_info_ptr = NULL;
879    png_infop write_end_info_ptr = NULL;
880 #endif /* !WRITE */
881    png_bytep row_buf;
882    png_uint_32 y;
883    png_uint_32 width, height;
884    volatile int num_passes;
885    int pass;
886    int bit_depth, color_type;
887 
888    row_buf = NULL;
889    error_parameters.file_name = inname;
890 
891    if ((fpin = fopen(inname, "rb")) == NULL)
892    {
893       fprintf(STDERR, "Could not find input file %s\n", inname);
894       return (1);
895    }
896 
897    if ((fpout = fopen(outname, "wb")) == NULL)
898    {
899       fprintf(STDERR, "Could not open output file %s\n", outname);
900       FCLOSE(fpin);
901       return (1);
902    }
903 
904    pngtest_debug("Allocating read and write structures");
905 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
906    read_ptr =
907        png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL,
908        NULL, NULL, NULL, png_debug_malloc, png_debug_free);
909 #else
910    read_ptr =
911        png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
912 #endif
913    png_set_error_fn(read_ptr, &error_parameters, pngtest_error,
914        pngtest_warning);
915 
916 #ifdef PNG_WRITE_SUPPORTED
917 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
918    write_ptr =
919        png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL,
920        NULL, NULL, NULL, png_debug_malloc, png_debug_free);
921 #else
922    write_ptr =
923        png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
924 #endif
925    png_set_error_fn(write_ptr, &error_parameters, pngtest_error,
926        pngtest_warning);
927 #endif
928    pngtest_debug("Allocating read_info, write_info and end_info structures");
929    read_info_ptr = png_create_info_struct(read_ptr);
930    end_info_ptr = png_create_info_struct(read_ptr);
931 #ifdef PNG_WRITE_SUPPORTED
932    write_info_ptr = png_create_info_struct(write_ptr);
933    write_end_info_ptr = png_create_info_struct(write_ptr);
934 #endif
935 
936 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
937    init_callback_info(read_info_ptr);
938    png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
939        read_user_chunk_callback);
940 #endif
941 
942 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
943 #  ifdef CHUNK_LIMIT /* from the build, for testing */
944       png_set_chunk_malloc_max(read_ptr, CHUNK_LIMIT);
945 #  endif /* CHUNK_LIMIT */
946 #endif
947 
948 #ifdef PNG_SETJMP_SUPPORTED
949    pngtest_debug("Setting jmpbuf for read struct");
950    if (setjmp(png_jmpbuf(read_ptr)))
951    {
952       fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
953       png_free(read_ptr, row_buf);
954       row_buf = NULL;
955       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
956 #ifdef PNG_WRITE_SUPPORTED
957       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
958       png_destroy_write_struct(&write_ptr, &write_info_ptr);
959 #endif
960       FCLOSE(fpin);
961       FCLOSE(fpout);
962       return (1);
963    }
964 
965 #ifdef PNG_WRITE_SUPPORTED
966    pngtest_debug("Setting jmpbuf for write struct");
967 
968    if (setjmp(png_jmpbuf(write_ptr)))
969    {
970       fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
971       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
972       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
973 #ifdef PNG_WRITE_SUPPORTED
974       png_destroy_write_struct(&write_ptr, &write_info_ptr);
975 #endif
976       FCLOSE(fpin);
977       FCLOSE(fpout);
978       return (1);
979    }
980 #endif
981 #endif
982 
983    if (strict != 0)
984    {
985       /* Treat png_benign_error() as errors on read */
986       png_set_benign_errors(read_ptr, 0);
987 
988 #ifdef PNG_WRITE_SUPPORTED
989       /* Treat them as errors on write */
990       png_set_benign_errors(write_ptr, 0);
991 #endif
992 
993       /* if strict is not set, then app warnings and errors are treated as
994        * warnings in release builds, but not in unstable builds; this can be
995        * changed with '--relaxed'.
996        */
997    }
998 
999    else if (relaxed != 0)
1000    {
1001       /* Allow application (pngtest) errors and warnings to pass */
1002       png_set_benign_errors(read_ptr, 1);
1003 
1004 #ifdef PNG_WRITE_SUPPORTED
1005       png_set_benign_errors(write_ptr, 1);
1006 #endif
1007    }
1008 
1009    pngtest_debug("Initializing input and output streams");
1010 #ifdef PNG_STDIO_SUPPORTED
1011    png_init_io(read_ptr, fpin);
1012 #  ifdef PNG_WRITE_SUPPORTED
1013    png_init_io(write_ptr, fpout);
1014 #  endif
1015 #else
1016    png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
1017 #  ifdef PNG_WRITE_SUPPORTED
1018    png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
1019 #    ifdef PNG_WRITE_FLUSH_SUPPORTED
1020        pngtest_flush);
1021 #    else
1022        NULL);
1023 #    endif
1024 #  endif
1025 #endif
1026 
1027    if (status_dots_requested == 1)
1028    {
1029 #ifdef PNG_WRITE_SUPPORTED
1030       png_set_write_status_fn(write_ptr, write_row_callback);
1031 #endif
1032       png_set_read_status_fn(read_ptr, read_row_callback);
1033    }
1034 
1035    else
1036    {
1037 #ifdef PNG_WRITE_SUPPORTED
1038       png_set_write_status_fn(write_ptr, NULL);
1039 #endif
1040       png_set_read_status_fn(read_ptr, NULL);
1041    }
1042 
1043 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1044    png_set_read_user_transform_fn(read_ptr, read_user_callback);
1045 #endif
1046 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1047    zero_samples = 0;
1048    png_set_write_user_transform_fn(write_ptr, count_zero_samples);
1049 #endif
1050 
1051 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
1052    /* Preserve all the unknown chunks, if possible.  If this is disabled then,
1053     * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
1054     * libpng to *save* the unknown chunks on read (because we can't switch the
1055     * save option on!)
1056     *
1057     * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
1058     * unknown chunks and write will write them all.
1059     */
1060 #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
1061    png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
1062        NULL, 0);
1063 #endif
1064 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1065    png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
1066        NULL, 0);
1067 #endif
1068 #endif
1069 
1070    pngtest_debug("Reading info struct");
1071    png_read_info(read_ptr, read_info_ptr);
1072 
1073 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1074    /* This is a bit of a hack; there is no obvious way in the callback function
1075     * to determine that the chunks before the first IDAT have been read, so
1076     * remove the info_ptr (which is only used to determine position relative to
1077     * PLTE) here to indicate that we are after the IDAT.
1078     */
1079    user_chunk_data.info_ptr = NULL;
1080 #endif
1081 
1082    pngtest_debug("Transferring info struct");
1083    {
1084       int interlace_type, compression_type, filter_type;
1085 
1086       if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
1087           &color_type, &interlace_type, &compression_type, &filter_type) != 0)
1088       {
1089          png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
1090              color_type, interlace_type, compression_type, filter_type);
1091          /* num_passes may not be available below if interlace support is not
1092           * provided by libpng for both read and write.
1093           */
1094          switch (interlace_type)
1095          {
1096             case PNG_INTERLACE_NONE:
1097                num_passes = 1;
1098                break;
1099 
1100             case PNG_INTERLACE_ADAM7:
1101                num_passes = 7;
1102                break;
1103 
1104             default:
1105                png_error(read_ptr, "invalid interlace type");
1106                /*NOT REACHED*/
1107          }
1108       }
1109 
1110       else
1111          png_error(read_ptr, "png_get_IHDR failed");
1112    }
1113 #ifdef PNG_FIXED_POINT_SUPPORTED
1114 #ifdef PNG_cHRM_SUPPORTED
1115    {
1116       png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
1117           blue_y;
1118 
1119       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y,
1120           &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
1121       {
1122          png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
1123              red_y, green_x, green_y, blue_x, blue_y);
1124       }
1125    }
1126 #endif
1127 #ifdef PNG_gAMA_SUPPORTED
1128    {
1129       png_fixed_point gamma;
1130 
1131       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0)
1132          png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
1133    }
1134 #endif
1135 #else /* Use floating point versions */
1136 #ifdef PNG_FLOATING_POINT_SUPPORTED
1137 #ifdef PNG_cHRM_SUPPORTED
1138    {
1139       double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
1140           blue_y;
1141 
1142       if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
1143           &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
1144       {
1145          png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
1146              red_y, green_x, green_y, blue_x, blue_y);
1147       }
1148    }
1149 #endif
1150 #ifdef PNG_gAMA_SUPPORTED
1151    {
1152       double gamma;
1153 
1154       if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0)
1155          png_set_gAMA(write_ptr, write_info_ptr, gamma);
1156    }
1157 #endif
1158 #endif /* Floating point */
1159 #endif /* Fixed point */
1160 #ifdef PNG_iCCP_SUPPORTED
1161    {
1162       png_charp name;
1163       png_bytep profile;
1164       png_uint_32 proflen;
1165       int compression_type;
1166 
1167       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
1168           &profile, &proflen) != 0)
1169       {
1170          png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
1171              profile, proflen);
1172       }
1173    }
1174 #endif
1175 #ifdef PNG_sRGB_SUPPORTED
1176    {
1177       int intent;
1178 
1179       if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0)
1180          png_set_sRGB(write_ptr, write_info_ptr, intent);
1181    }
1182 #endif
1183    {
1184       png_colorp palette;
1185       int num_palette;
1186 
1187       if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)
1188          png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
1189    }
1190 #ifdef PNG_bKGD_SUPPORTED
1191    {
1192       png_color_16p background;
1193 
1194       if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
1195       {
1196          png_set_bKGD(write_ptr, write_info_ptr, background);
1197       }
1198    }
1199 #endif
1200 #ifdef PNG_hIST_SUPPORTED
1201    {
1202       png_uint_16p hist;
1203 
1204       if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0)
1205          png_set_hIST(write_ptr, write_info_ptr, hist);
1206    }
1207 #endif
1208 #ifdef PNG_oFFs_SUPPORTED
1209    {
1210       png_int_32 offset_x, offset_y;
1211       int unit_type;
1212 
1213       if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
1214           &unit_type) != 0)
1215       {
1216          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
1217       }
1218    }
1219 #endif
1220 #ifdef PNG_pCAL_SUPPORTED
1221    {
1222       png_charp purpose, units;
1223       png_charpp params;
1224       png_int_32 X0, X1;
1225       int type, nparams;
1226 
1227       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
1228           &nparams, &units, &params) != 0)
1229       {
1230          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
1231              nparams, units, params);
1232       }
1233    }
1234 #endif
1235 #ifdef PNG_pHYs_SUPPORTED
1236    {
1237       png_uint_32 res_x, res_y;
1238       int unit_type;
1239 
1240       if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y,
1241           &unit_type) != 0)
1242          png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
1243    }
1244 #endif
1245 #ifdef PNG_sBIT_SUPPORTED
1246    {
1247       png_color_8p sig_bit;
1248 
1249       if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0)
1250          png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
1251    }
1252 #endif
1253 #ifdef PNG_sCAL_SUPPORTED
1254 #if defined(PNG_FLOATING_POINT_SUPPORTED) && \
1255    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
1256    {
1257       int unit;
1258       double scal_width, scal_height;
1259 
1260       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
1261           &scal_height) != 0)
1262       {
1263          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
1264       }
1265    }
1266 #else
1267 #ifdef PNG_FIXED_POINT_SUPPORTED
1268    {
1269       int unit;
1270       png_charp scal_width, scal_height;
1271 
1272       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
1273            &scal_height) != 0)
1274       {
1275          png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,
1276              scal_height);
1277       }
1278    }
1279 #endif
1280 #endif
1281 #endif
1282 
1283 #ifdef PNG_sPLT_SUPPORTED
1284    {
1285        png_sPLT_tp entries;
1286 
1287        int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);
1288        if (num_entries)
1289        {
1290            png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
1291        }
1292    }
1293 #endif
1294 
1295 #ifdef PNG_TEXT_SUPPORTED
1296    {
1297       png_textp text_ptr;
1298       int num_text;
1299 
1300       if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
1301       {
1302          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
1303 
1304          pngtest_check_text_support(read_ptr, text_ptr, num_text);
1305 
1306          if (verbose != 0)
1307          {
1308             int i;
1309 
1310             printf("\n");
1311             for (i=0; i<num_text; i++)
1312             {
1313                printf("   Text compression[%d]=%d\n",
1314                    i, text_ptr[i].compression);
1315             }
1316          }
1317 
1318          png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
1319       }
1320    }
1321 #endif
1322 #ifdef PNG_tIME_SUPPORTED
1323    {
1324       png_timep mod_time;
1325 
1326       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time) != 0)
1327       {
1328          png_set_tIME(write_ptr, write_info_ptr, mod_time);
1329 #ifdef PNG_TIME_RFC1123_SUPPORTED
1330          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
1331             tIME_string[(sizeof tIME_string) - 1] = '\0';
1332 
1333          else
1334          {
1335             strncpy(tIME_string, "*** invalid time ***", (sizeof tIME_string));
1336             tIME_string[(sizeof tIME_string) - 1] = '\0';
1337          }
1338 
1339          tIME_chunk_present++;
1340 #endif /* TIME_RFC1123 */
1341       }
1342    }
1343 #endif
1344 #ifdef PNG_tRNS_SUPPORTED
1345    {
1346       png_bytep trans_alpha;
1347       int num_trans;
1348       png_color_16p trans_color;
1349 
1350       if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans,
1351           &trans_color) != 0)
1352       {
1353          int sample_max = (1 << bit_depth);
1354          /* libpng doesn't reject a tRNS chunk with out-of-range samples */
1355          if (!((color_type == PNG_COLOR_TYPE_GRAY &&
1356              (int)trans_color->gray > sample_max) ||
1357              (color_type == PNG_COLOR_TYPE_RGB &&
1358              ((int)trans_color->red > sample_max ||
1359              (int)trans_color->green > sample_max ||
1360              (int)trans_color->blue > sample_max))))
1361             png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans,
1362                trans_color);
1363       }
1364    }
1365 #endif
1366 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1367    {
1368       png_unknown_chunkp unknowns;
1369       int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr,
1370           &unknowns);
1371 
1372       if (num_unknowns != 0)
1373       {
1374          png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
1375              num_unknowns);
1376 #if PNG_LIBPNG_VER < 10600
1377          /* Copy the locations from the read_info_ptr.  The automatically
1378           * generated locations in write_end_info_ptr are wrong prior to 1.6.0
1379           * because they are reset from the write pointer (removed in 1.6.0).
1380           */
1381          {
1382             int i;
1383             for (i = 0; i < num_unknowns; i++)
1384               png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
1385                   unknowns[i].location);
1386          }
1387 #endif
1388       }
1389    }
1390 #endif
1391 
1392 #ifdef PNG_WRITE_SUPPORTED
1393    pngtest_debug("Writing info struct");
1394 
1395    /* Write the info in two steps so that if we write the 'unknown' chunks here
1396     * they go to the correct place.
1397     */
1398    png_write_info_before_PLTE(write_ptr, write_info_ptr);
1399 
1400    write_chunks(write_ptr, before_PLTE); /* before PLTE */
1401 
1402    png_write_info(write_ptr, write_info_ptr);
1403 
1404    write_chunks(write_ptr, before_IDAT); /* after PLTE */
1405 #endif
1406 
1407 #ifdef SINGLE_ROWBUF_ALLOC
1408    pngtest_debug("Allocating row buffer...");
1409    row_buf = (png_bytep)png_malloc(read_ptr,
1410        png_get_rowbytes(read_ptr, read_info_ptr));
1411 
1412    pngtest_debug1("\t0x%08lx", (unsigned long)row_buf);
1413 #endif /* SINGLE_ROWBUF_ALLOC */
1414    pngtest_debug("Writing row data");
1415 
1416 #if defined(PNG_READ_INTERLACING_SUPPORTED) &&\
1417    defined(PNG_WRITE_INTERLACING_SUPPORTED)
1418    /* Both must be defined for libpng to be able to handle the interlace,
1419     * otherwise it gets handled below by simply reading and writing the passes
1420     * directly.
1421     */
1422    if (png_set_interlace_handling(read_ptr) != num_passes)
1423       png_error(write_ptr,
1424           "png_set_interlace_handling(read): wrong pass count ");
1425    if (png_set_interlace_handling(write_ptr) != num_passes)
1426       png_error(write_ptr,
1427           "png_set_interlace_handling(write): wrong pass count ");
1428 #else /* png_set_interlace_handling not called on either read or write */
1429 #  define calc_pass_height
1430 #endif /* not using libpng interlace handling */
1431 
1432 #ifdef PNGTEST_TIMING
1433    t_stop = (float)clock();
1434    t_misc += (t_stop - t_start);
1435    t_start = t_stop;
1436 #endif
1437    for (pass = 0; pass < num_passes; pass++)
1438    {
1439 #     ifdef calc_pass_height
1440          png_uint_32 pass_height;
1441 
1442          if (num_passes == 7) /* interlaced */
1443          {
1444             if (PNG_PASS_COLS(width, pass) > 0)
1445                pass_height = PNG_PASS_ROWS(height, pass);
1446 
1447             else
1448                pass_height = 0;
1449          }
1450 
1451          else /* not interlaced */
1452             pass_height = height;
1453 #     else
1454 #        define pass_height height
1455 #     endif
1456 
1457       pngtest_debug1("Writing row data for pass %d", pass);
1458       for (y = 0; y < pass_height; y++)
1459       {
1460 #ifndef SINGLE_ROWBUF_ALLOC
1461          pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
1462 
1463          row_buf = (png_bytep)png_malloc(read_ptr,
1464              png_get_rowbytes(read_ptr, read_info_ptr));
1465 
1466          pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
1467              (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
1468 
1469 #endif /* !SINGLE_ROWBUF_ALLOC */
1470          png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
1471 
1472 #ifdef PNG_WRITE_SUPPORTED
1473 #ifdef PNGTEST_TIMING
1474          t_stop = (float)clock();
1475          t_decode += (t_stop - t_start);
1476          t_start = t_stop;
1477 #endif
1478          png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
1479 #ifdef PNGTEST_TIMING
1480          t_stop = (float)clock();
1481          t_encode += (t_stop - t_start);
1482          t_start = t_stop;
1483 #endif
1484 #endif /* WRITE */
1485 
1486 #ifndef SINGLE_ROWBUF_ALLOC
1487          pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
1488          png_free(read_ptr, row_buf);
1489          row_buf = NULL;
1490 #endif /* !SINGLE_ROWBUF_ALLOC */
1491       }
1492    }
1493 
1494 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
1495 #  ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
1496       png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
1497 #  endif
1498 #  ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1499       png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
1500 #  endif
1501 #endif
1502 
1503    pngtest_debug("Reading and writing end_info data");
1504 
1505    png_read_end(read_ptr, end_info_ptr);
1506 #ifdef PNG_TEXT_SUPPORTED
1507    {
1508       png_textp text_ptr;
1509       int num_text;
1510 
1511       if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
1512       {
1513          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
1514 
1515          pngtest_check_text_support(read_ptr, text_ptr, num_text);
1516 
1517          if (verbose != 0)
1518          {
1519             int i;
1520 
1521             printf("\n");
1522             for (i=0; i<num_text; i++)
1523             {
1524                printf("   Text compression[%d]=%d\n",
1525                    i, text_ptr[i].compression);
1526             }
1527          }
1528 
1529          png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
1530       }
1531    }
1532 #endif
1533 #ifdef PNG_tIME_SUPPORTED
1534    {
1535       png_timep mod_time;
1536 
1537       if (png_get_tIME(read_ptr, end_info_ptr, &mod_time) != 0)
1538       {
1539          png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
1540 #ifdef PNG_TIME_RFC1123_SUPPORTED
1541          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
1542             tIME_string[(sizeof tIME_string) - 1] = '\0';
1543 
1544          else
1545          {
1546             strncpy(tIME_string, "*** invalid time ***", sizeof tIME_string);
1547             tIME_string[(sizeof tIME_string)-1] = '\0';
1548          }
1549 
1550          tIME_chunk_present++;
1551 #endif /* TIME_RFC1123 */
1552       }
1553    }
1554 #endif
1555 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
1556    {
1557       png_unknown_chunkp unknowns;
1558       int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr,
1559           &unknowns);
1560 
1561       if (num_unknowns != 0)
1562       {
1563          png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
1564              num_unknowns);
1565 #if PNG_LIBPNG_VER < 10600
1566          /* Copy the locations from the read_info_ptr.  The automatically
1567           * generated locations in write_end_info_ptr are wrong prior to 1.6.0
1568           * because they are reset from the write pointer (removed in 1.6.0).
1569           */
1570          {
1571             int i;
1572             for (i = 0; i < num_unknowns; i++)
1573               png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
1574                   unknowns[i].location);
1575          }
1576 #endif
1577       }
1578    }
1579 #endif
1580 
1581 #ifdef PNG_WRITE_SUPPORTED
1582 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1583    /* Normally one would use Z_DEFAULT_STRATEGY for text compression.
1584     * This is here just to make pngtest replicate the results from libpng
1585     * versions prior to 1.5.4, and to test this new API.
1586     */
1587    png_set_text_compression_strategy(write_ptr, Z_FILTERED);
1588 #endif
1589 
1590    /* When the unknown vpAg/sTER chunks are written by pngtest the only way to
1591     * do it is to write them *before* calling png_write_end.  When unknown
1592     * chunks are written by libpng, however, they are written just before IEND.
1593     * There seems to be no way round this, however vpAg/sTER are not expected
1594     * after IDAT.
1595     */
1596    write_chunks(write_ptr, after_IDAT);
1597 
1598    png_write_end(write_ptr, write_end_info_ptr);
1599 #endif
1600 
1601 #ifdef PNG_EASY_ACCESS_SUPPORTED
1602    if (verbose != 0)
1603    {
1604       png_uint_32 iwidth, iheight;
1605       iwidth = png_get_image_width(write_ptr, write_info_ptr);
1606       iheight = png_get_image_height(write_ptr, write_info_ptr);
1607       fprintf(STDERR, "\n Image width = %lu, height = %lu\n",
1608           (unsigned long)iwidth, (unsigned long)iheight);
1609    }
1610 #endif
1611 
1612    pngtest_debug("Destroying data structs");
1613 #ifdef SINGLE_ROWBUF_ALLOC
1614    pngtest_debug("destroying row_buf for read_ptr");
1615    png_free(read_ptr, row_buf);
1616    row_buf = NULL;
1617 #endif /* SINGLE_ROWBUF_ALLOC */
1618    pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr");
1619    png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
1620 #ifdef PNG_WRITE_SUPPORTED
1621    pngtest_debug("destroying write_end_info_ptr");
1622    png_destroy_info_struct(write_ptr, &write_end_info_ptr);
1623    pngtest_debug("destroying write_ptr, write_info_ptr");
1624    png_destroy_write_struct(&write_ptr, &write_info_ptr);
1625 #endif
1626    pngtest_debug("Destruction complete.");
1627 
1628    FCLOSE(fpin);
1629    FCLOSE(fpout);
1630 
1631    /* Summarize any warnings or errors and in 'strict' mode fail the test.
1632     * Unsupported chunks can result in warnings, in that case ignore the strict
1633     * setting, otherwise fail the test on warnings as well as errors.
1634     */
1635    if (error_count > 0)
1636    {
1637       /* We don't really expect to get here because of the setjmp handling
1638        * above, but this is safe.
1639        */
1640       fprintf(STDERR, "\n  %s: %d libpng errors found (%d warnings)",
1641           inname, error_count, warning_count);
1642 
1643       if (strict != 0)
1644          return (1);
1645    }
1646 
1647 #  ifdef PNG_WRITE_SUPPORTED
1648       /* If there is no write support nothing was written! */
1649       else if (unsupported_chunks > 0)
1650       {
1651          fprintf(STDERR, "\n  %s: unsupported chunks (%d)%s",
1652              inname, unsupported_chunks, strict ? ": IGNORED --strict!" : "");
1653       }
1654 #  endif
1655 
1656    else if (warning_count > 0)
1657    {
1658       fprintf(STDERR, "\n  %s: %d libpng warnings found",
1659           inname, warning_count);
1660 
1661       if (strict != 0)
1662          return (1);
1663    }
1664 
1665    pngtest_debug("Opening files for comparison");
1666    if ((fpin = fopen(inname, "rb")) == NULL)
1667    {
1668       fprintf(STDERR, "Could not find file %s\n", inname);
1669       return (1);
1670    }
1671 
1672    if ((fpout = fopen(outname, "rb")) == NULL)
1673    {
1674       fprintf(STDERR, "Could not find file %s\n", outname);
1675       FCLOSE(fpin);
1676       return (1);
1677    }
1678 
1679 #if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\
1680     defined (PNG_WRITE_FILTER_SUPPORTED)
1681    if (interlace_preserved != 0) /* else the files will be changed */
1682    {
1683       for (;;)
1684       {
1685          static int wrote_question = 0;
1686          png_size_t num_in, num_out;
1687          char inbuf[256], outbuf[256];
1688 
1689          num_in = fread(inbuf, 1, sizeof inbuf, fpin);
1690          num_out = fread(outbuf, 1, sizeof outbuf, fpout);
1691 
1692          if (num_in != num_out)
1693          {
1694             fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
1695                 inname, outname);
1696 
1697             if (wrote_question == 0 && unsupported_chunks == 0)
1698             {
1699                fprintf(STDERR,
1700                    "   Was %s written with the same maximum IDAT"
1701                    " chunk size (%d bytes),",
1702                    inname, PNG_ZBUF_SIZE);
1703                fprintf(STDERR,
1704                    "\n   filtering heuristic (libpng default), compression");
1705                fprintf(STDERR,
1706                    " level (zlib default),\n   and zlib version (%s)?\n\n",
1707                    ZLIB_VERSION);
1708                wrote_question = 1;
1709             }
1710 
1711             FCLOSE(fpin);
1712             FCLOSE(fpout);
1713 
1714             if (strict != 0 && unsupported_chunks == 0)
1715               return (1);
1716 
1717             else
1718               return (0);
1719          }
1720 
1721          if (num_in == 0)
1722             break;
1723 
1724          if (memcmp(inbuf, outbuf, num_in))
1725          {
1726             fprintf(STDERR, "\nFiles %s and %s are different\n", inname,
1727                 outname);
1728 
1729             if (wrote_question == 0 && unsupported_chunks == 0)
1730             {
1731                fprintf(STDERR,
1732                    "   Was %s written with the same maximum"
1733                    " IDAT chunk size (%d bytes),",
1734                     inname, PNG_ZBUF_SIZE);
1735                fprintf(STDERR,
1736                    "\n   filtering heuristic (libpng default), compression");
1737                fprintf(STDERR,
1738                    " level (zlib default),\n   and zlib version (%s)?\n\n",
1739                  ZLIB_VERSION);
1740                wrote_question = 1;
1741             }
1742 
1743             FCLOSE(fpin);
1744             FCLOSE(fpout);
1745 
1746             /* NOTE: the unsupported_chunks escape is permitted here because
1747              * unsupported text chunk compression will result in the compression
1748              * mode being changed (to NONE) yet, in the test case, the result
1749              * can be exactly the same size!
1750              */
1751             if (strict != 0 && unsupported_chunks == 0)
1752               return (1);
1753 
1754             else
1755               return (0);
1756          }
1757       }
1758    }
1759 #endif /* WRITE && WRITE_FILTER */
1760 
1761    FCLOSE(fpin);
1762    FCLOSE(fpout);
1763 
1764    return (0);
1765 }
1766 
1767 /* Input and output filenames */
1768 #ifdef RISCOS
1769 static PNG_CONST char *inname = "pngtest/png";
1770 static PNG_CONST char *outname = "pngout/png";
1771 #else
1772 static PNG_CONST char *inname = "pngtest.png";
1773 static PNG_CONST char *outname = "pngout.png";
1774 #endif
1775 
1776 int
main(int argc,char * argv[])1777 main(int argc, char *argv[])
1778 {
1779    int multiple = 0;
1780    int ierror = 0;
1781 
1782    png_structp dummy_ptr;
1783 
1784    fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
1785    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
1786    fprintf(STDERR, "%s", png_get_copyright(NULL));
1787    /* Show the version of libpng used in building the library */
1788    fprintf(STDERR, " library (%lu):%s",
1789        (unsigned long)png_access_version_number(),
1790        png_get_header_version(NULL));
1791 
1792    /* Show the version of libpng used in building the application */
1793    fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
1794        PNG_HEADER_VERSION_STRING);
1795 
1796    /* Do some consistency checking on the memory allocation settings, I'm
1797     * not sure this matters, but it is nice to know, the first of these
1798     * tests should be impossible because of the way the macros are set
1799     * in pngconf.h
1800     */
1801 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
1802       fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
1803 #endif
1804    /* I think the following can happen. */
1805 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
1806       fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
1807 #endif
1808 
1809    if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
1810    {
1811       fprintf(STDERR,
1812           "Warning: versions are different between png.h and png.c\n");
1813       fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
1814       fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
1815       ++ierror;
1816    }
1817 
1818    if (argc > 1)
1819    {
1820       if (strcmp(argv[1], "-m") == 0)
1821       {
1822          multiple = 1;
1823          status_dots_requested = 0;
1824       }
1825 
1826       else if (strcmp(argv[1], "-mv") == 0 ||
1827                strcmp(argv[1], "-vm") == 0 )
1828       {
1829          multiple = 1;
1830          verbose = 1;
1831          status_dots_requested = 1;
1832       }
1833 
1834       else if (strcmp(argv[1], "-v") == 0)
1835       {
1836          verbose = 1;
1837          status_dots_requested = 1;
1838          inname = argv[2];
1839       }
1840 
1841       else if (strcmp(argv[1], "--strict") == 0)
1842       {
1843          status_dots_requested = 0;
1844          verbose = 1;
1845          inname = argv[2];
1846          strict++;
1847          relaxed = 0;
1848       }
1849 
1850       else if (strcmp(argv[1], "--relaxed") == 0)
1851       {
1852          status_dots_requested = 0;
1853          verbose = 1;
1854          inname = argv[2];
1855          strict = 0;
1856          relaxed++;
1857       }
1858 
1859       else
1860       {
1861          inname = argv[1];
1862          status_dots_requested = 0;
1863       }
1864    }
1865 
1866    if (multiple == 0 && argc == 3 + verbose)
1867       outname = argv[2 + verbose];
1868 
1869    if ((multiple == 0 && argc > 3 + verbose) ||
1870        (multiple != 0 && argc < 2))
1871    {
1872       fprintf(STDERR,
1873           "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
1874           argv[0], argv[0]);
1875       fprintf(STDERR,
1876           "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
1877       fprintf(STDERR,
1878           "  with -m %s is used as a temporary file\n", outname);
1879       exit(1);
1880    }
1881 
1882    if (multiple != 0)
1883    {
1884       int i;
1885 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1886       png_alloc_size_t allocation_now = current_allocation;
1887 #endif
1888       for (i=2; i<argc; ++i)
1889       {
1890          int kerror;
1891          fprintf(STDERR, "\n Testing %s:", argv[i]);
1892 #if PNG_DEBUG > 0
1893          fprintf(STDERR, "\n");
1894 #endif
1895          kerror = test_one_file(argv[i], outname);
1896          if (kerror == 0)
1897          {
1898 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1899             fprintf(STDERR, "\n PASS (%lu zero samples)\n",
1900                 (unsigned long)zero_samples);
1901 #else
1902             fprintf(STDERR, " PASS\n");
1903 #endif
1904 #ifdef PNG_TIME_RFC1123_SUPPORTED
1905             if (tIME_chunk_present != 0)
1906                fprintf(STDERR, " tIME = %s\n", tIME_string);
1907 
1908             tIME_chunk_present = 0;
1909 #endif /* TIME_RFC1123 */
1910          }
1911 
1912          else
1913          {
1914             fprintf(STDERR, " FAIL\n");
1915             ierror += kerror;
1916          }
1917 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1918          if (allocation_now != current_allocation)
1919             fprintf(STDERR, "MEMORY ERROR: %lu bytes lost\n",
1920                 (unsigned long)(current_allocation - allocation_now));
1921 
1922          if (current_allocation != 0)
1923          {
1924             memory_infop pinfo = pinformation;
1925 
1926             fprintf(STDERR, "MEMORY ERROR: %lu bytes still allocated\n",
1927                 (unsigned long)current_allocation);
1928 
1929             while (pinfo != NULL)
1930             {
1931                fprintf(STDERR, " %lu bytes at %p\n",
1932                    (unsigned long)pinfo->size,
1933                    pinfo->pointer);
1934                pinfo = pinfo->next;
1935             }
1936          }
1937 #endif
1938       }
1939 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1940          fprintf(STDERR, " Current memory allocation: %20lu bytes\n",
1941              (unsigned long)current_allocation);
1942          fprintf(STDERR, " Maximum memory allocation: %20lu bytes\n",
1943              (unsigned long) maximum_allocation);
1944          fprintf(STDERR, " Total   memory allocation: %20lu bytes\n",
1945              (unsigned long)total_allocation);
1946          fprintf(STDERR, "     Number of allocations: %20lu\n",
1947              (unsigned long)num_allocations);
1948 #endif
1949    }
1950 
1951    else
1952    {
1953       int i;
1954       for (i = 0; i<3; ++i)
1955       {
1956          int kerror;
1957 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1958          png_alloc_size_t allocation_now = current_allocation;
1959 #endif
1960          if (i == 1)
1961             status_dots_requested = 1;
1962 
1963          else if (verbose == 0)
1964             status_dots_requested = 0;
1965 
1966          if (i == 0 || verbose == 1 || ierror != 0)
1967          {
1968             fprintf(STDERR, "\n Testing %s:", inname);
1969 #if PNG_DEBUG > 0
1970             fprintf(STDERR, "\n");
1971 #endif
1972          }
1973 
1974          kerror = test_one_file(inname, outname);
1975 
1976          if (kerror == 0)
1977          {
1978             if (verbose == 1 || i == 2)
1979             {
1980 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1981                 fprintf(STDERR, "\n PASS (%lu zero samples)\n",
1982                     (unsigned long)zero_samples);
1983 #else
1984                 fprintf(STDERR, " PASS\n");
1985 #endif
1986 #ifdef PNG_TIME_RFC1123_SUPPORTED
1987              if (tIME_chunk_present != 0)
1988                 fprintf(STDERR, " tIME = %s\n", tIME_string);
1989 #endif /* TIME_RFC1123 */
1990             }
1991          }
1992 
1993          else
1994          {
1995             if (verbose == 0 && i != 2)
1996             {
1997                fprintf(STDERR, "\n Testing %s:", inname);
1998 #if PNG_DEBUG > 0
1999                fprintf(STDERR, "\n");
2000 #endif
2001             }
2002 
2003             fprintf(STDERR, " FAIL\n");
2004             ierror += kerror;
2005          }
2006 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
2007          if (allocation_now != current_allocation)
2008              fprintf(STDERR, "MEMORY ERROR: %lu bytes lost\n",
2009                  (unsigned long)(current_allocation - allocation_now));
2010 
2011          if (current_allocation != 0)
2012          {
2013              memory_infop pinfo = pinformation;
2014 
2015              fprintf(STDERR, "MEMORY ERROR: %lu bytes still allocated\n",
2016                  (unsigned long)current_allocation);
2017 
2018              while (pinfo != NULL)
2019              {
2020                 fprintf(STDERR, " %lu bytes at %p\n",
2021                     (unsigned long)pinfo->size, pinfo->pointer);
2022                 pinfo = pinfo->next;
2023              }
2024           }
2025 #endif
2026        }
2027 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
2028        fprintf(STDERR, " Current memory allocation: %20lu bytes\n",
2029            (unsigned long)current_allocation);
2030        fprintf(STDERR, " Maximum memory allocation: %20lu bytes\n",
2031            (unsigned long)maximum_allocation);
2032        fprintf(STDERR, " Total   memory allocation: %20lu bytes\n",
2033            (unsigned long)total_allocation);
2034        fprintf(STDERR, "     Number of allocations: %20lu\n",
2035            (unsigned long)num_allocations);
2036 #endif
2037    }
2038 
2039 #ifdef PNGTEST_TIMING
2040    t_stop = (float)clock();
2041    t_misc += (t_stop - t_start);
2042    t_start = t_stop;
2043    fprintf(STDERR, " CPU time used = %.3f seconds",
2044        (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
2045    fprintf(STDERR, " (decoding %.3f,\n",
2046        t_decode/(float)CLOCKS_PER_SEC);
2047    fprintf(STDERR, "        encoding %.3f ,",
2048        t_encode/(float)CLOCKS_PER_SEC);
2049    fprintf(STDERR, " other %.3f seconds)\n\n",
2050        t_misc/(float)CLOCKS_PER_SEC);
2051 #endif
2052 
2053    if (ierror == 0)
2054       fprintf(STDERR, " libpng passes test\n");
2055 
2056    else
2057       fprintf(STDERR, " libpng FAILS test\n");
2058 
2059    dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
2060    fprintf(STDERR, " Default limits:\n");
2061    fprintf(STDERR, "  width_max  = %lu\n",
2062        (unsigned long) png_get_user_width_max(dummy_ptr));
2063    fprintf(STDERR, "  height_max = %lu\n",
2064        (unsigned long) png_get_user_height_max(dummy_ptr));
2065    if (png_get_chunk_cache_max(dummy_ptr) == 0)
2066       fprintf(STDERR, "  cache_max  = unlimited\n");
2067    else
2068       fprintf(STDERR, "  cache_max  = %lu\n",
2069           (unsigned long) png_get_chunk_cache_max(dummy_ptr));
2070    if (png_get_chunk_malloc_max(dummy_ptr) == 0)
2071       fprintf(STDERR, "  malloc_max = unlimited\n");
2072    else
2073       fprintf(STDERR, "  malloc_max = %lu\n",
2074           (unsigned long) png_get_chunk_malloc_max(dummy_ptr));
2075    png_destroy_read_struct(&dummy_ptr, NULL, NULL);
2076 
2077    return (int)(ierror != 0);
2078 }
2079 #else
2080 int
main(void)2081 main(void)
2082 {
2083    fprintf(STDERR,
2084        " test ignored because libpng was not built with read support\n");
2085    /* And skip this test */
2086    return SKIP;
2087 }
2088 #endif
2089 
2090 /* Generate a compiler error if there is an old png.h in the search path. */
2091 typedef png_libpng_version_1_6_25 Your_png_h_is_not_version_1_6_25;
2092