1
2/* png.c - location for general purpose libpng functions
3 *
4 * Last changed in libpng 1.4.2 [May 6, 2010]
5 * Copyright (c) 1998-2010 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
14#define PNG_NO_EXTERN
15#define PNG_NO_PEDANTIC_WARNINGS
16#include "png.h"
17#include "pngpriv.h"
18
19/* Generate a compiler error if there is an old png.h in the search path. */
20typedef version_1_4_3 Your_png_h_is_not_version_1_4_3;
21
22/* Version information for C files.  This had better match the version
23 * string defined in png.h.
24 */
25
26/* Tells libpng that we have already handled the first "num_bytes" bytes
27 * of the PNG file signature.  If the PNG data is embedded into another
28 * stream we can set num_bytes = 8 so that libpng will not attempt to read
29 * or write any of the magic bytes before it starts on the IHDR.
30 */
31
32#ifdef PNG_READ_SUPPORTED
33void PNGAPI
34png_set_sig_bytes(png_structp png_ptr, int num_bytes)
35{
36   png_debug(1, "in png_set_sig_bytes");
37
38   if (png_ptr == NULL)
39      return;
40
41   if (num_bytes > 8)
42      png_error(png_ptr, "Too many bytes for PNG signature");
43
44   png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
45}
46
47/* Checks whether the supplied bytes match the PNG signature.  We allow
48 * checking less than the full 8-byte signature so that those apps that
49 * already read the first few bytes of a file to determine the file type
50 * can simply check the remaining bytes for extra assurance.  Returns
51 * an integer less than, equal to, or greater than zero if sig is found,
52 * respectively, to be less than, to match, or be greater than the correct
53 * PNG signature (this is the same behaviour as strcmp, memcmp, etc).
54 */
55int PNGAPI
56png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
57{
58   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
59   if (num_to_check > 8)
60      num_to_check = 8;
61   else if (num_to_check < 1)
62      return (-1);
63
64   if (start > 7)
65      return (-1);
66
67   if (start + num_to_check > 8)
68      num_to_check = 8 - start;
69
70   return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
71}
72
73#endif /* PNG_READ_SUPPORTED */
74
75#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
76/* Function to allocate memory for zlib and clear it to 0. */
77voidpf /* PRIVATE */
78png_zalloc(voidpf png_ptr, uInt items, uInt size)
79{
80   png_voidp ptr;
81   png_structp p=(png_structp)png_ptr;
82   png_uint_32 save_flags=p->flags;
83   png_alloc_size_t num_bytes;
84
85   if (png_ptr == NULL)
86      return (NULL);
87   if (items > PNG_UINT_32_MAX/size)
88   {
89     png_warning (p, "Potential overflow in png_zalloc()");
90     return (NULL);
91   }
92   num_bytes = (png_alloc_size_t)items * size;
93
94   p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
95   ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
96   p->flags=save_flags;
97
98   return ((voidpf)ptr);
99}
100
101/* Function to free memory for zlib */
102void /* PRIVATE */
103png_zfree(voidpf png_ptr, voidpf ptr)
104{
105   png_free((png_structp)png_ptr, (png_voidp)ptr);
106}
107
108/* Reset the CRC variable to 32 bits of 1's.  Care must be taken
109 * in case CRC is > 32 bits to leave the top bits 0.
110 */
111void /* PRIVATE */
112png_reset_crc(png_structp png_ptr)
113{
114   png_ptr->crc = crc32(0, Z_NULL, 0);
115}
116
117/* Calculate the CRC over a section of data.  We can only pass as
118 * much data to this routine as the largest single buffer size.  We
119 * also check that this data will actually be used before going to the
120 * trouble of calculating it.
121 */
122void /* PRIVATE */
123png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
124{
125   int need_crc = 1;
126
127   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
128   {
129      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
130          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
131         need_crc = 0;
132   }
133   else                                                    /* critical */
134   {
135      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
136         need_crc = 0;
137   }
138
139   if (need_crc)
140      png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
141}
142
143/* Allocate the memory for an info_struct for the application.  We don't
144 * really need the png_ptr, but it could potentially be useful in the
145 * future.  This should be used in favour of malloc(png_sizeof(png_info))
146 * and png_info_init() so that applications that want to use a shared
147 * libpng don't have to be recompiled if png_info changes size.
148 */
149png_infop PNGAPI
150png_create_info_struct(png_structp png_ptr)
151{
152   png_infop info_ptr;
153
154   png_debug(1, "in png_create_info_struct");
155
156   if (png_ptr == NULL)
157      return (NULL);
158
159#ifdef PNG_USER_MEM_SUPPORTED
160   info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
161      png_ptr->malloc_fn, png_ptr->mem_ptr);
162#else
163   info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
164#endif
165   if (info_ptr != NULL)
166      png_info_init_3(&info_ptr, png_sizeof(png_info));
167
168   return (info_ptr);
169}
170
171/* This function frees the memory associated with a single info struct.
172 * Normally, one would use either png_destroy_read_struct() or
173 * png_destroy_write_struct() to free an info struct, but this may be
174 * useful for some applications.
175 */
176void PNGAPI
177png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
178{
179   png_infop info_ptr = NULL;
180
181   png_debug(1, "in png_destroy_info_struct");
182
183   if (png_ptr == NULL)
184      return;
185
186   if (info_ptr_ptr != NULL)
187      info_ptr = *info_ptr_ptr;
188
189   if (info_ptr != NULL)
190   {
191      png_info_destroy(png_ptr, info_ptr);
192
193#ifdef PNG_USER_MEM_SUPPORTED
194      png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
195          png_ptr->mem_ptr);
196#else
197      png_destroy_struct((png_voidp)info_ptr);
198#endif
199      *info_ptr_ptr = NULL;
200   }
201}
202
203/* Initialize the info structure.  This is now an internal function (0.89)
204 * and applications using it are urged to use png_create_info_struct()
205 * instead.
206 */
207
208void PNGAPI
209png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
210{
211   png_infop info_ptr = *ptr_ptr;
212
213   png_debug(1, "in png_info_init_3");
214
215   if (info_ptr == NULL)
216      return;
217
218   if (png_sizeof(png_info) > png_info_struct_size)
219   {
220      png_destroy_struct(info_ptr);
221      info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
222      *ptr_ptr = info_ptr;
223   }
224
225   /* Set everything to 0 */
226   png_memset(info_ptr, 0, png_sizeof(png_info));
227}
228
229void PNGAPI
230png_data_freer(png_structp png_ptr, png_infop info_ptr,
231   int freer, png_uint_32 mask)
232{
233   png_debug(1, "in png_data_freer");
234
235   if (png_ptr == NULL || info_ptr == NULL)
236      return;
237
238   if (freer == PNG_DESTROY_WILL_FREE_DATA)
239      info_ptr->free_me |= mask;
240   else if (freer == PNG_USER_WILL_FREE_DATA)
241      info_ptr->free_me &= ~mask;
242   else
243      png_warning(png_ptr,
244         "Unknown freer parameter in png_data_freer");
245}
246
247void PNGAPI
248png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
249   int num)
250{
251   png_debug(1, "in png_free_data");
252
253   if (png_ptr == NULL || info_ptr == NULL)
254      return;
255
256#ifdef PNG_TEXT_SUPPORTED
257   /* Free text item num or (if num == -1) all text items */
258   if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
259   {
260      if (num != -1)
261      {
262         if (info_ptr->text && info_ptr->text[num].key)
263         {
264            png_free(png_ptr, info_ptr->text[num].key);
265            info_ptr->text[num].key = NULL;
266         }
267      }
268      else
269      {
270         int i;
271         for (i = 0; i < info_ptr->num_text; i++)
272             png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
273         png_free(png_ptr, info_ptr->text);
274         info_ptr->text = NULL;
275         info_ptr->num_text=0;
276      }
277   }
278#endif
279
280#ifdef PNG_tRNS_SUPPORTED
281   /* Free any tRNS entry */
282   if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
283   {
284      png_free(png_ptr, info_ptr->trans_alpha);
285      info_ptr->trans_alpha = NULL;
286      info_ptr->valid &= ~PNG_INFO_tRNS;
287   }
288#endif
289
290#ifdef PNG_sCAL_SUPPORTED
291   /* Free any sCAL entry */
292   if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
293   {
294#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
295      png_free(png_ptr, info_ptr->scal_s_width);
296      png_free(png_ptr, info_ptr->scal_s_height);
297      info_ptr->scal_s_width = NULL;
298      info_ptr->scal_s_height = NULL;
299#endif
300      info_ptr->valid &= ~PNG_INFO_sCAL;
301   }
302#endif
303
304#ifdef PNG_pCAL_SUPPORTED
305   /* Free any pCAL entry */
306   if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
307   {
308      png_free(png_ptr, info_ptr->pcal_purpose);
309      png_free(png_ptr, info_ptr->pcal_units);
310      info_ptr->pcal_purpose = NULL;
311      info_ptr->pcal_units = NULL;
312      if (info_ptr->pcal_params != NULL)
313         {
314            int i;
315            for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
316            {
317               png_free(png_ptr, info_ptr->pcal_params[i]);
318               info_ptr->pcal_params[i] = NULL;
319            }
320            png_free(png_ptr, info_ptr->pcal_params);
321            info_ptr->pcal_params = NULL;
322         }
323      info_ptr->valid &= ~PNG_INFO_pCAL;
324   }
325#endif
326
327#ifdef PNG_iCCP_SUPPORTED
328   /* Free any iCCP entry */
329   if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
330   {
331      png_free(png_ptr, info_ptr->iccp_name);
332      png_free(png_ptr, info_ptr->iccp_profile);
333      info_ptr->iccp_name = NULL;
334      info_ptr->iccp_profile = NULL;
335      info_ptr->valid &= ~PNG_INFO_iCCP;
336   }
337#endif
338
339#ifdef PNG_sPLT_SUPPORTED
340   /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
341   if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
342   {
343      if (num != -1)
344      {
345         if (info_ptr->splt_palettes)
346         {
347            png_free(png_ptr, info_ptr->splt_palettes[num].name);
348            png_free(png_ptr, info_ptr->splt_palettes[num].entries);
349            info_ptr->splt_palettes[num].name = NULL;
350            info_ptr->splt_palettes[num].entries = NULL;
351         }
352      }
353      else
354      {
355         if (info_ptr->splt_palettes_num)
356         {
357            int i;
358            for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
359               png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
360
361            png_free(png_ptr, info_ptr->splt_palettes);
362            info_ptr->splt_palettes = NULL;
363            info_ptr->splt_palettes_num = 0;
364         }
365         info_ptr->valid &= ~PNG_INFO_sPLT;
366      }
367   }
368#endif
369
370#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
371   if (png_ptr->unknown_chunk.data)
372   {
373      png_free(png_ptr, png_ptr->unknown_chunk.data);
374      png_ptr->unknown_chunk.data = NULL;
375   }
376
377   if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
378   {
379      if (num != -1)
380      {
381          if (info_ptr->unknown_chunks)
382          {
383             png_free(png_ptr, info_ptr->unknown_chunks[num].data);
384             info_ptr->unknown_chunks[num].data = NULL;
385          }
386      }
387      else
388      {
389         int i;
390
391         if (info_ptr->unknown_chunks_num)
392         {
393            for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
394               png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
395
396            png_free(png_ptr, info_ptr->unknown_chunks);
397            info_ptr->unknown_chunks = NULL;
398            info_ptr->unknown_chunks_num = 0;
399         }
400      }
401   }
402#endif
403
404#ifdef PNG_hIST_SUPPORTED
405   /* Free any hIST entry */
406   if ((mask & PNG_FREE_HIST)  & info_ptr->free_me)
407   {
408      png_free(png_ptr, info_ptr->hist);
409      info_ptr->hist = NULL;
410      info_ptr->valid &= ~PNG_INFO_hIST;
411   }
412#endif
413
414   /* Free any PLTE entry that was internally allocated */
415   if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
416   {
417      png_zfree(png_ptr, info_ptr->palette);
418      info_ptr->palette = NULL;
419      info_ptr->valid &= ~PNG_INFO_PLTE;
420      info_ptr->num_palette = 0;
421   }
422
423#ifdef PNG_INFO_IMAGE_SUPPORTED
424   /* Free any image bits attached to the info structure */
425   if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
426   {
427      if (info_ptr->row_pointers)
428      {
429         int row;
430         for (row = 0; row < (int)info_ptr->height; row++)
431         {
432            png_free(png_ptr, info_ptr->row_pointers[row]);
433            info_ptr->row_pointers[row] = NULL;
434         }
435         png_free(png_ptr, info_ptr->row_pointers);
436         info_ptr->row_pointers = NULL;
437      }
438      info_ptr->valid &= ~PNG_INFO_IDAT;
439   }
440#endif
441
442   if (num == -1)
443      info_ptr->free_me &= ~mask;
444   else
445      info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
446}
447
448/* This is an internal routine to free any memory that the info struct is
449 * pointing to before re-using it or freeing the struct itself.  Recall
450 * that png_free() checks for NULL pointers for us.
451 */
452void /* PRIVATE */
453png_info_destroy(png_structp png_ptr, png_infop info_ptr)
454{
455   png_debug(1, "in png_info_destroy");
456
457   png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
458
459#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
460   if (png_ptr->num_chunk_list)
461   {
462      png_free(png_ptr, png_ptr->chunk_list);
463      png_ptr->chunk_list = NULL;
464      png_ptr->num_chunk_list = 0;
465   }
466#endif
467
468   png_info_init_3(&info_ptr, png_sizeof(png_info));
469}
470#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
471
472/* This function returns a pointer to the io_ptr associated with the user
473 * functions.  The application should free any memory associated with this
474 * pointer before png_write_destroy() or png_read_destroy() are called.
475 */
476png_voidp PNGAPI
477png_get_io_ptr(png_structp png_ptr)
478{
479   if (png_ptr == NULL)
480      return (NULL);
481   return (png_ptr->io_ptr);
482}
483
484#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
485#ifdef PNG_STDIO_SUPPORTED
486/* Initialize the default input/output functions for the PNG file.  If you
487 * use your own read or write routines, you can call either png_set_read_fn()
488 * or png_set_write_fn() instead of png_init_io().  If you have defined
489 * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't
490 * necessarily available.
491 */
492void PNGAPI
493png_init_io(png_structp png_ptr, png_FILE_p fp)
494{
495   png_debug(1, "in png_init_io");
496
497   if (png_ptr == NULL)
498      return;
499
500   png_ptr->io_ptr = (png_voidp)fp;
501}
502#endif
503
504#ifdef PNG_TIME_RFC1123_SUPPORTED
505/* Convert the supplied time into an RFC 1123 string suitable for use in
506 * a "Creation Time" or other text-based time string.
507 */
508png_charp PNGAPI
509png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
510{
511   static PNG_CONST char short_months[12][4] =
512        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
513         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
514
515   if (png_ptr == NULL)
516      return (NULL);
517   if (png_ptr->time_buffer == NULL)
518   {
519      png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
520         png_sizeof(char)));
521   }
522
523#ifdef USE_FAR_KEYWORD
524   {
525      char near_time_buf[29];
526      png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000",
527          ptime->day % 32, short_months[(ptime->month - 1) % 12],
528          ptime->year, ptime->hour % 24, ptime->minute % 60,
529          ptime->second % 61);
530      png_memcpy(png_ptr->time_buffer, near_time_buf,
531          29*png_sizeof(char));
532   }
533#else
534   png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000",
535       ptime->day % 32, short_months[(ptime->month - 1) % 12],
536       ptime->year, ptime->hour % 24, ptime->minute % 60,
537       ptime->second % 61);
538#endif
539   return ((png_charp)png_ptr->time_buffer);
540}
541#endif /* PNG_TIME_RFC1123_SUPPORTED */
542
543#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
544
545png_charp PNGAPI
546png_get_copyright(png_structp png_ptr)
547{
548   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
549#ifdef PNG_STRING_COPYRIGHT
550      return PNG_STRING_COPYRIGHT
551#else
552#ifdef __STDC__
553   return ((png_charp) PNG_STRING_NEWLINE \
554     "libpng version 1.4.3 - June 26, 2010" PNG_STRING_NEWLINE \
555     "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
556     "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
557     "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
558     PNG_STRING_NEWLINE);
559#else
560      return ((png_charp) "libpng version 1.4.3 - June 26, 2010\
561      Copyright (c) 1998-2010 Glenn Randers-Pehrson\
562      Copyright (c) 1996-1997 Andreas Dilger\
563      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
564#endif
565#endif
566}
567
568/* The following return the library version as a short string in the
569 * format 1.0.0 through 99.99.99zz.  To get the version of *.h files
570 * used with your application, print out PNG_LIBPNG_VER_STRING, which
571 * is defined in png.h.
572 * Note: now there is no difference between png_get_libpng_ver() and
573 * png_get_header_ver().  Due to the version_nn_nn_nn typedef guard,
574 * it is guaranteed that png.c uses the correct version of png.h.
575 */
576png_charp PNGAPI
577png_get_libpng_ver(png_structp png_ptr)
578{
579   /* Version of *.c files used when building libpng */
580   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
581   return ((png_charp) PNG_LIBPNG_VER_STRING);
582}
583
584png_charp PNGAPI
585png_get_header_ver(png_structp png_ptr)
586{
587   /* Version of *.h files used when building libpng */
588   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
589   return ((png_charp) PNG_LIBPNG_VER_STRING);
590}
591
592png_charp PNGAPI
593png_get_header_version(png_structp png_ptr)
594{
595   /* Returns longer string containing both version and date */
596   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
597#ifdef __STDC__
598   return ((png_charp) PNG_HEADER_VERSION_STRING
599#ifndef PNG_READ_SUPPORTED
600   "     (NO READ SUPPORT)"
601#endif
602   PNG_STRING_NEWLINE);
603#else
604   return ((png_charp) PNG_HEADER_VERSION_STRING);
605#endif
606}
607
608#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
609#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
610int PNGAPI
611png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
612{
613   /* Check chunk_name and return "keep" value if it's on the list, else 0 */
614   int i;
615   png_bytep p;
616   if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0)
617      return 0;
618   p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5;
619   for (i = png_ptr->num_chunk_list; i; i--, p -= 5)
620      if (!png_memcmp(chunk_name, p, 4))
621        return ((int)*(p + 4));
622   return 0;
623}
624#endif
625#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
626
627#ifdef PNG_READ_SUPPORTED
628/* This function, added to libpng-1.0.6g, is untested. */
629int PNGAPI
630png_reset_zstream(png_structp png_ptr)
631{
632   if (png_ptr == NULL)
633      return Z_STREAM_ERROR;
634   return (inflateReset(&png_ptr->zstream));
635}
636#endif /* PNG_READ_SUPPORTED */
637
638/* This function was added to libpng-1.0.7 */
639png_uint_32 PNGAPI
640png_access_version_number(void)
641{
642   /* Version of *.c files used when building libpng */
643   return((png_uint_32) PNG_LIBPNG_VER);
644}
645
646
647
648#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
649#ifdef PNG_SIZE_T
650/* Added at libpng version 1.2.6 */
651   PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size));
652png_size_t PNGAPI
653png_convert_size(size_t size)
654{
655   if (size > (png_size_t)-1)
656      PNG_ABORT();  /* We haven't got access to png_ptr, so no png_error() */
657   return ((png_size_t)size);
658}
659#endif /* PNG_SIZE_T */
660
661/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
662#ifdef PNG_cHRM_SUPPORTED
663#ifdef PNG_CHECK_cHRM_SUPPORTED
664
665/*
666 *    Multiply two 32-bit numbers, V1 and V2, using 32-bit
667 *    arithmetic, to produce a 64 bit result in the HI/LO words.
668 *
669 *                  A B
670 *                x C D
671 *               ------
672 *              AD || BD
673 *        AC || CB || 0
674 *
675 *    where A and B are the high and low 16-bit words of V1,
676 *    C and D are the 16-bit words of V2, AD is the product of
677 *    A and D, and X || Y is (X << 16) + Y.
678*/
679
680void /* PRIVATE */
681png_64bit_product (long v1, long v2, unsigned long *hi_product,
682   unsigned long *lo_product)
683{
684   int a, b, c, d;
685   long lo, hi, x, y;
686
687   a = (v1 >> 16) & 0xffff;
688   b = v1 & 0xffff;
689   c = (v2 >> 16) & 0xffff;
690   d = v2 & 0xffff;
691
692   lo = b * d;                   /* BD */
693   x = a * d + c * b;            /* AD + CB */
694   y = ((lo >> 16) & 0xffff) + x;
695
696   lo = (lo & 0xffff) | ((y & 0xffff) << 16);
697   hi = (y >> 16) & 0xffff;
698
699   hi += a * c;                  /* AC */
700
701   *hi_product = (unsigned long)hi;
702   *lo_product = (unsigned long)lo;
703}
704
705int /* PRIVATE */
706png_check_cHRM_fixed(png_structp png_ptr,
707   png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
708   png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
709   png_fixed_point blue_x, png_fixed_point blue_y)
710{
711   int ret = 1;
712   unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
713
714   png_debug(1, "in function png_check_cHRM_fixed");
715
716   if (png_ptr == NULL)
717      return 0;
718
719   if (white_x < 0 || white_y <= 0 ||
720         red_x < 0 ||   red_y <  0 ||
721       green_x < 0 || green_y <  0 ||
722        blue_x < 0 ||  blue_y <  0)
723   {
724      png_warning(png_ptr,
725        "Ignoring attempt to set negative chromaticity value");
726      ret = 0;
727   }
728   if (white_x > (png_fixed_point) PNG_UINT_31_MAX ||
729       white_y > (png_fixed_point) PNG_UINT_31_MAX ||
730         red_x > (png_fixed_point) PNG_UINT_31_MAX ||
731         red_y > (png_fixed_point) PNG_UINT_31_MAX ||
732       green_x > (png_fixed_point) PNG_UINT_31_MAX ||
733       green_y > (png_fixed_point) PNG_UINT_31_MAX ||
734        blue_x > (png_fixed_point) PNG_UINT_31_MAX ||
735        blue_y > (png_fixed_point) PNG_UINT_31_MAX )
736   {
737      png_warning(png_ptr,
738        "Ignoring attempt to set chromaticity value exceeding 21474.83");
739      ret = 0;
740   }
741   if (white_x > 100000L - white_y)
742   {
743      png_warning(png_ptr, "Invalid cHRM white point");
744      ret = 0;
745   }
746   if (red_x > 100000L - red_y)
747   {
748      png_warning(png_ptr, "Invalid cHRM red point");
749      ret = 0;
750   }
751   if (green_x > 100000L - green_y)
752   {
753      png_warning(png_ptr, "Invalid cHRM green point");
754      ret = 0;
755   }
756   if (blue_x > 100000L - blue_y)
757   {
758      png_warning(png_ptr, "Invalid cHRM blue point");
759      ret = 0;
760   }
761
762   png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
763   png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
764
765   if (xy_hi == yx_hi && xy_lo == yx_lo)
766   {
767      png_warning(png_ptr,
768         "Ignoring attempt to set cHRM RGB triangle with zero area");
769      ret = 0;
770   }
771
772   return ret;
773}
774#endif /* PNG_CHECK_cHRM_SUPPORTED */
775#endif /* PNG_cHRM_SUPPORTED */
776
777void /* PRIVATE */
778png_check_IHDR(png_structp png_ptr,
779   png_uint_32 width, png_uint_32 height, int bit_depth,
780   int color_type, int interlace_type, int compression_type,
781   int filter_type)
782{
783   int error = 0;
784
785   /* Check for width and height valid values */
786   if (width == 0)
787   {
788      png_warning(png_ptr, "Image width is zero in IHDR");
789      error = 1;
790   }
791
792   if (height == 0)
793   {
794      png_warning(png_ptr, "Image height is zero in IHDR");
795      error = 1;
796   }
797
798#ifdef PNG_SET_USER_LIMITS_SUPPORTED
799   if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX)
800#else
801   if (width > PNG_USER_WIDTH_MAX)
802#endif
803   {
804      png_warning(png_ptr, "Image width exceeds user limit in IHDR");
805      error = 1;
806   }
807
808#ifdef PNG_SET_USER_LIMITS_SUPPORTED
809   if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX)
810#else
811   if (height > PNG_USER_HEIGHT_MAX)
812#endif
813   {
814      png_warning(png_ptr, "Image height exceeds user limit in IHDR");
815      error = 1;
816   }
817
818   if (width > PNG_UINT_31_MAX)
819   {
820      png_warning(png_ptr, "Invalid image width in IHDR");
821      error = 1;
822   }
823
824   if ( height > PNG_UINT_31_MAX)
825   {
826      png_warning(png_ptr, "Invalid image height in IHDR");
827      error = 1;
828   }
829
830   if ( width > (PNG_UINT_32_MAX
831                 >> 3)      /* 8-byte RGBA pixels */
832                 - 64       /* bigrowbuf hack */
833                 - 1        /* filter byte */
834                 - 7*8      /* rounding of width to multiple of 8 pixels */
835                 - 8)       /* extra max_pixel_depth pad */
836      png_warning(png_ptr, "Width is too large for libpng to process pixels");
837
838   /* Check other values */
839   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
840       bit_depth != 8 && bit_depth != 16)
841   {
842      png_warning(png_ptr, "Invalid bit depth in IHDR");
843      error = 1;
844   }
845
846   if (color_type < 0 || color_type == 1 ||
847       color_type == 5 || color_type > 6)
848   {
849      png_warning(png_ptr, "Invalid color type in IHDR");
850      error = 1;
851   }
852
853   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
854       ((color_type == PNG_COLOR_TYPE_RGB ||
855         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
856         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
857   {
858      png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
859      error = 1;
860   }
861
862   if (interlace_type >= PNG_INTERLACE_LAST)
863   {
864      png_warning(png_ptr, "Unknown interlace method in IHDR");
865      error = 1;
866   }
867
868   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
869   {
870      png_warning(png_ptr, "Unknown compression method in IHDR");
871      error = 1;
872   }
873
874#ifdef PNG_MNG_FEATURES_SUPPORTED
875   /* Accept filter_method 64 (intrapixel differencing) only if
876    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
877    * 2. Libpng did not read a PNG signature (this filter_method is only
878    *    used in PNG datastreams that are embedded in MNG datastreams) and
879    * 3. The application called png_permit_mng_features with a mask that
880    *    included PNG_FLAG_MNG_FILTER_64 and
881    * 4. The filter_method is 64 and
882    * 5. The color_type is RGB or RGBA
883    */
884   if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
885       png_ptr->mng_features_permitted)
886      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
887
888   if (filter_type != PNG_FILTER_TYPE_BASE)
889   {
890      if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
891         (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
892         ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
893         (color_type == PNG_COLOR_TYPE_RGB ||
894         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
895      {
896         png_warning(png_ptr, "Unknown filter method in IHDR");
897         error = 1;
898      }
899
900      if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
901      {
902         png_warning(png_ptr, "Invalid filter method in IHDR");
903         error = 1;
904      }
905   }
906
907#else
908   if (filter_type != PNG_FILTER_TYPE_BASE)
909   {
910      png_warning(png_ptr, "Unknown filter method in IHDR");
911      error = 1;
912   }
913#endif
914
915   if (error == 1)
916      png_error(png_ptr, "Invalid IHDR data");
917}
918#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
919