summaryrefslogtreecommitdiff
path: root/png/pngset.c
diff options
context:
space:
mode:
Diffstat (limited to 'png/pngset.c')
-rw-r--r--png/pngset.c447
1 files changed, 319 insertions, 128 deletions
diff --git a/png/pngset.c b/png/pngset.c
index 2f1f550da..ec75dbe36 100644
--- a/png/pngset.c
+++ b/png/pngset.c
@@ -1,10 +1,10 @@
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 1998-2018 Glenn Randers-Pehrson
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -104,14 +104,14 @@ png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
double green_x, double green_y, double blue_x, double blue_y)
{
png_set_cHRM_fixed(png_ptr, info_ptr,
- png_fixed(png_ptr, white_x, "cHRM White X"),
- png_fixed(png_ptr, white_y, "cHRM White Y"),
- png_fixed(png_ptr, red_x, "cHRM Red X"),
- png_fixed(png_ptr, red_y, "cHRM Red Y"),
- png_fixed(png_ptr, green_x, "cHRM Green X"),
- png_fixed(png_ptr, green_y, "cHRM Green Y"),
- png_fixed(png_ptr, blue_x, "cHRM Blue X"),
- png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
+ png_fixed(png_ptr, white_x, "cHRM White X"),
+ png_fixed(png_ptr, white_y, "cHRM White Y"),
+ png_fixed(png_ptr, red_x, "cHRM Red X"),
+ png_fixed(png_ptr, red_y, "cHRM Red Y"),
+ png_fixed(png_ptr, green_x, "cHRM Green X"),
+ png_fixed(png_ptr, green_y, "cHRM Green Y"),
+ png_fixed(png_ptr, blue_x, "cHRM Blue X"),
+ png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
}
void PNGAPI
@@ -120,20 +120,67 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
double blue_X, double blue_Y, double blue_Z)
{
png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
- png_fixed(png_ptr, red_X, "cHRM Red X"),
- png_fixed(png_ptr, red_Y, "cHRM Red Y"),
- png_fixed(png_ptr, red_Z, "cHRM Red Z"),
- png_fixed(png_ptr, green_X, "cHRM Red X"),
- png_fixed(png_ptr, green_Y, "cHRM Red Y"),
- png_fixed(png_ptr, green_Z, "cHRM Red Z"),
- png_fixed(png_ptr, blue_X, "cHRM Red X"),
- png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
- png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
+ png_fixed(png_ptr, red_X, "cHRM Red X"),
+ png_fixed(png_ptr, red_Y, "cHRM Red Y"),
+ png_fixed(png_ptr, red_Z, "cHRM Red Z"),
+ png_fixed(png_ptr, green_X, "cHRM Green X"),
+ png_fixed(png_ptr, green_Y, "cHRM Green Y"),
+ png_fixed(png_ptr, green_Z, "cHRM Green Z"),
+ png_fixed(png_ptr, blue_X, "cHRM Blue X"),
+ png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
+ png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
}
# endif /* FLOATING_POINT */
#endif /* cHRM */
+#ifdef PNG_eXIf_SUPPORTED
+void PNGAPI
+png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_bytep eXIf_buf)
+{
+ png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
+ PNG_UNUSED(info_ptr)
+ PNG_UNUSED(eXIf_buf)
+}
+
+void PNGAPI
+png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_uint_32 num_exif, png_bytep eXIf_buf)
+{
+ int i;
+
+ png_debug1(1, "in %s storage function", "eXIf");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (info_ptr->exif)
+ {
+ png_free(png_ptr, info_ptr->exif);
+ info_ptr->exif = NULL;
+ }
+
+ info_ptr->num_exif = num_exif;
+
+ info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr,
+ info_ptr->num_exif));
+
+ if (info_ptr->exif == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory for eXIf chunk data");
+ return;
+ }
+
+ info_ptr->free_me |= PNG_FREE_EXIF;
+
+ for (i = 0; i < (int) info_ptr->num_exif; i++)
+ info_ptr->exif[i] = eXIf_buf[i];
+
+ info_ptr->valid |= PNG_INFO_eXIf;
+}
+#endif /* eXIf */
+
#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
@@ -190,6 +237,7 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
if (info_ptr->hist == NULL)
{
png_warning(png_ptr, "Insufficient memory for hIST chunk data");
+
return;
}
@@ -265,13 +313,13 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
int nparams, png_const_charp units, png_charpp params)
{
- png_size_t length;
+ size_t length;
int i;
png_debug1(1, "in %s storage function", "pCAL");
if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
- || (nparams > 0 && params == NULL))
+ || (nparams > 0 && params == NULL))
return;
length = strlen(purpose) + 1;
@@ -282,17 +330,29 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
/* Check that the type matches the specification. */
if (type < 0 || type > 3)
- png_error(png_ptr, "Invalid pCAL equation type");
+ {
+ png_chunk_report(png_ptr, "Invalid pCAL equation type",
+ PNG_CHUNK_WRITE_ERROR);
+ return;
+ }
if (nparams < 0 || nparams > 255)
- png_error(png_ptr, "Invalid pCAL parameter count");
+ {
+ png_chunk_report(png_ptr, "Invalid pCAL parameter count",
+ PNG_CHUNK_WRITE_ERROR);
+ return;
+ }
/* Validate params[nparams] */
for (i=0; i<nparams; ++i)
{
if (params[i] == NULL ||
!png_check_fp_string(params[i], strlen(params[i])))
- png_error(png_ptr, "Invalid format for pCAL parameter");
+ {
+ png_chunk_report(png_ptr, "Invalid format for pCAL parameter",
+ PNG_CHUNK_WRITE_ERROR);
+ return;
+ }
}
info_ptr->pcal_purpose = png_voidcast(png_charp,
@@ -300,7 +360,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
if (info_ptr->pcal_purpose == NULL)
{
- png_warning(png_ptr, "Insufficient memory for pCAL purpose");
+ png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose",
+ PNG_CHUNK_WRITE_ERROR);
return;
}
@@ -314,29 +375,32 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
length = strlen(units) + 1;
png_debug1(3, "allocating units for info (%lu bytes)",
- (unsigned long)length);
+ (unsigned long)length);
info_ptr->pcal_units = png_voidcast(png_charp,
- png_malloc_warn(png_ptr, length));
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_units == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL units");
+
return;
}
memcpy(info_ptr->pcal_units, units, length);
info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
- (png_size_t)((nparams + 1) * (sizeof (png_charp)))));
+ (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp)))));
if (info_ptr->pcal_params == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL params");
+
return;
}
- memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp)));
+ memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) *
+ (sizeof (png_charp)));
for (i = 0; i < nparams; i++)
{
@@ -349,6 +413,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
if (info_ptr->pcal_params[i] == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL parameter");
+
return;
}
@@ -365,7 +430,7 @@ void PNGAPI
png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
int unit, png_const_charp swidth, png_const_charp sheight)
{
- png_size_t lengthw = 0, lengthh = 0;
+ size_t lengthw = 0, lengthh = 0;
png_debug1(1, "in %s storage function", "sCAL");
@@ -393,11 +458,12 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
info_ptr->scal_s_width = png_voidcast(png_charp,
- png_malloc_warn(png_ptr, lengthw));
+ png_malloc_warn(png_ptr, lengthw));
if (info_ptr->scal_s_width == NULL)
{
png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
return;
}
@@ -408,7 +474,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
info_ptr->scal_s_height = png_voidcast(png_charp,
- png_malloc_warn(png_ptr, lengthh));
+ png_malloc_warn(png_ptr, lengthh));
if (info_ptr->scal_s_height == NULL)
{
@@ -416,6 +482,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
info_ptr->scal_s_width = NULL;
png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
return;
}
@@ -446,9 +513,9 @@ png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
char sheight[PNG_sCAL_MAX_DIGITS+1];
png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
- PNG_sCAL_PRECISION);
+ PNG_sCAL_PRECISION);
png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
- PNG_sCAL_PRECISION);
+ PNG_sCAL_PRECISION);
png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
}
@@ -506,12 +573,17 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
png_const_colorp palette, int num_palette)
{
+ png_uint_32 max_palette_length;
+
png_debug1(1, "in %s storage function", "PLTE");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
+ max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+ (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
+ if (num_palette < 0 || num_palette > (int) max_palette_length)
{
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
png_error(png_ptr, "Invalid palette length");
@@ -519,6 +591,7 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
else
{
png_warning(png_ptr, "Invalid palette length");
+
return;
}
}
@@ -531,7 +604,6 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
))
{
png_error(png_ptr, "Invalid palette");
- return;
}
/* It may not actually be necessary to set png_ptr->palette here;
@@ -544,14 +616,15 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
/* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
- * of num_palette entries, in case of an invalid PNG file that has
- * too-large sample values.
+ * of num_palette entries, in case of an invalid PNG file or incorrect
+ * call to png_set_PLTE() with too-large sample values.
*/
png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
if (num_palette > 0)
- memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
+ memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
+ (sizeof (png_color)));
info_ptr->palette = png_ptr->palette;
info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
@@ -618,7 +691,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
{
png_charp new_iccp_name;
png_bytep new_iccp_profile;
- png_size_t length;
+ size_t length;
png_debug1(1, "in %s storage function", "iCCP");
@@ -636,7 +709,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
*/
{
int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
- proflen, profile, info_ptr->color_type);
+ proflen, profile, info_ptr->color_type);
png_colorspace_sync_info(png_ptr, info_ptr);
@@ -655,19 +728,20 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
if (new_iccp_name == NULL)
{
png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
+
return;
}
memcpy(new_iccp_name, name, length);
new_iccp_profile = png_voidcast(png_bytep,
- png_malloc_warn(png_ptr, proflen));
+ png_malloc_warn(png_ptr, proflen));
if (new_iccp_profile == NULL)
{
png_free(png_ptr, new_iccp_name);
- new_iccp_name = NULL;
png_benign_error(png_ptr,
"Insufficient memory to process iCCP profile");
+
return;
}
@@ -701,7 +775,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
{
int i;
- png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
+ png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
(unsigned long)png_ptr->chunk_name);
if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
@@ -735,14 +809,15 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
* the overflow checks.
*/
new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
- info_ptr->text, old_num_text, max_text-old_num_text,
- sizeof *new_text));
+ info_ptr->text, old_num_text, max_text-old_num_text,
+ sizeof *new_text));
}
if (new_text == NULL)
{
png_chunk_report(png_ptr, "too many text chunks",
- PNG_CHUNK_WRITE_ERROR);
+ PNG_CHUNK_WRITE_ERROR);
+
return 1;
}
@@ -769,7 +844,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
{
png_chunk_report(png_ptr, "text compression mode is out of range",
- PNG_CHUNK_WRITE_ERROR);
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
@@ -798,10 +873,10 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
else
lang_key_len = 0;
}
-# else /* PNG_iTXt_SUPPORTED */
+# else /* iTXt */
{
png_chunk_report(png_ptr, "iTXt chunk not supported",
- PNG_CHUNK_WRITE_ERROR);
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
# endif
@@ -830,7 +905,8 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
if (textp->key == NULL)
{
png_chunk_report(png_ptr, "text chunk: out of memory",
- PNG_CHUNK_WRITE_ERROR);
+ PNG_CHUNK_WRITE_ERROR);
+
return 1;
}
@@ -904,6 +980,7 @@ png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
mod_time->second > 60)
{
png_warning(png_ptr, "Ignoring invalid time value");
+
return;
}
@@ -920,6 +997,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_debug1(1, "in %s storage function", "tRNS");
if (png_ptr == NULL || info_ptr == NULL)
+
return;
if (trans_alpha != NULL)
@@ -935,26 +1013,33 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
- /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
- png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
- png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
-
if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
- memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
+ {
+ /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
+ info_ptr->trans_alpha = png_voidcast(png_bytep,
+ png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
+ memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
+ }
+ png_ptr->trans_alpha = info_ptr->trans_alpha;
}
if (trans_color != NULL)
{
- int sample_max = (1 << info_ptr->bit_depth);
-
- if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
- trans_color->gray > sample_max) ||
- (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
- (trans_color->red > sample_max ||
- trans_color->green > sample_max ||
- trans_color->blue > sample_max)))
- png_warning(png_ptr,
- "tRNS chunk has out-of-range samples for bit_depth");
+#ifdef PNG_WARNINGS_SUPPORTED
+ if (info_ptr->bit_depth < 16)
+ {
+ int sample_max = (1 << info_ptr->bit_depth) - 1;
+
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+ trans_color->gray > sample_max) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ (trans_color->red > sample_max ||
+ trans_color->green > sample_max ||
+ trans_color->blue > sample_max)))
+ png_warning(png_ptr,
+ "tRNS chunk has out-of-range samples for bit_depth");
+ }
+#endif
info_ptr->trans_color = *trans_color;
@@ -994,13 +1079,14 @@ png_set_sPLT(png_const_structrp png_ptr,
* overflows. Notice that the parameters are (int) and (size_t)
*/
np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
- info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
- sizeof *np));
+ info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
+ sizeof *np));
if (np == NULL)
{
/* Out of memory or too many chunks */
png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
+
return;
}
@@ -1012,7 +1098,7 @@ png_set_sPLT(png_const_structrp png_ptr,
do
{
- png_size_t length;
+ size_t length;
/* Skip invalid input entries */
if (entries->name == NULL || entries->entries == NULL)
@@ -1055,7 +1141,7 @@ png_set_sPLT(png_const_structrp png_ptr,
* checked it when doing the allocation.
*/
memcpy(np->entries, entries->entries,
- entries->nentries * sizeof (png_sPLT_entry));
+ (unsigned int)entries->nentries * sizeof (png_sPLT_entry));
/* Note that 'continue' skips the advance of the out pointer and out
* count, so an invalid entry is not added.
@@ -1063,8 +1149,9 @@ png_set_sPLT(png_const_structrp png_ptr,
info_ptr->valid |= PNG_INFO_sPLT;
++(info_ptr->splt_palettes_num);
++np;
+ ++entries;
}
- while (++entries, --nentries);
+ while (--nentries);
if (nentries > 0)
png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
@@ -1085,10 +1172,10 @@ check_location(png_const_structrp png_ptr, int location)
{
/* Write struct, so unknown chunks come from the app */
png_app_warning(png_ptr,
- "png_set_unknown_chunks now expects a valid location");
+ "png_set_unknown_chunks now expects a valid location");
/* Use the old behavior */
location = (png_byte)(png_ptr->mode &
- (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
+ (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
}
/* This need not be an internal error - if the app calls
@@ -1111,12 +1198,12 @@ check_location(png_const_structrp png_ptr, int location)
void PNGAPI
png_set_unknown_chunks(png_const_structrp png_ptr,
- png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
+ png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
{
png_unknown_chunkp np;
if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
- unknowns == NULL)
+ unknowns == NULL)
return;
/* Check for the failure cases where support has been disabled at compile
@@ -1130,6 +1217,7 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
{
png_app_error(png_ptr, "no unknown chunk support on read");
+
return;
}
# endif
@@ -1138,6 +1226,7 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
{
png_app_error(png_ptr, "no unknown chunk support on write");
+
return;
}
# endif
@@ -1148,13 +1237,14 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
* appropriate to read or write.
*/
np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
- info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
- sizeof *np));
+ info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
+ sizeof *np));
if (np == NULL)
{
png_chunk_report(png_ptr, "too many unknown chunks",
- PNG_CHUNK_WRITE_ERROR);
+ PNG_CHUNK_WRITE_ERROR);
+
return;
}
@@ -1182,12 +1272,12 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
else
{
np->data = png_voidcast(png_bytep,
- png_malloc_base(png_ptr, unknowns->size));
+ png_malloc_base(png_ptr, unknowns->size));
if (np->data == NULL)
{
png_chunk_report(png_ptr, "unknown chunk: out of memory",
- PNG_CHUNK_WRITE_ERROR);
+ PNG_CHUNK_WRITE_ERROR);
/* But just skip storing the unknown chunk */
continue;
}
@@ -1221,7 +1311,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
{
png_app_error(png_ptr, "invalid unknown chunk location");
/* Fake out the pre 1.6.0 behavior: */
- if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
+ if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */
location = PNG_AFTER_IDAT;
else
@@ -1232,8 +1322,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
check_location(png_ptr, location);
}
}
-#endif
-
+#endif /* STORE_UNKNOWN_CHUNKS */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 PNGAPI
@@ -1264,6 +1353,7 @@ add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
if (memcmp(list, add, 4) == 0)
{
list[4] = (png_byte)keep;
+
return count;
}
}
@@ -1291,6 +1381,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
{
png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
+
return;
}
@@ -1308,9 +1399,10 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
/* Ignore all unknown chunks and all chunks recognized by
* libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
*/
- static PNG_CONST png_byte chunks_to_ignore[] = {
+ static const png_byte chunks_to_ignore[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
+ 101, 88, 73, 102, '\0', /* eXIf */
103, 65, 77, 65, '\0', /* gAMA */
104, 73, 83, 84, '\0', /* hIST */
105, 67, 67, 80, '\0', /* iCCP */
@@ -1340,10 +1432,11 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
* which can be switched off.
*/
png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
+
return;
}
- num_chunks = num_chunks_in;
+ num_chunks = (unsigned int)num_chunks_in;
}
old_num_chunks = png_ptr->num_chunk_list;
@@ -1355,6 +1448,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
if (num_chunks + old_num_chunks > UINT_MAX/5)
{
png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
+
return;
}
@@ -1391,7 +1485,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
for (i=0; i<num_chunks; ++i)
{
old_num_chunks = add_one_chunk(new_list, old_num_chunks,
- chunk_list+5*i, keep);
+ chunk_list+5*i, keep);
}
/* Now remove any spurious 'default' entries. */
@@ -1469,55 +1563,62 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
#endif
void PNGAPI
-png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
+png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
{
- if (png_ptr == NULL)
- return;
+ if (png_ptr == NULL)
+ return;
- if (size == 0 || size > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid compression buffer size");
+ if (size == 0 || size > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid compression buffer size");
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
- if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
+ return;
+ }
+# endif
+
+# ifdef PNG_WRITE_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ if (png_ptr->zowner != 0)
{
- png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
+ png_warning(png_ptr,
+ "Compression buffer size cannot be changed because it is in use");
+
return;
}
-# endif
-# ifdef PNG_WRITE_SUPPORTED
- if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+#ifndef __COVERITY__
+ /* Some compilers complain that this is always false. However, it
+ * can be true when integer overflow happens.
+ */
+ if (size > ZLIB_IO_MAX)
{
- if (png_ptr->zowner != 0)
- {
- png_warning(png_ptr,
- "Compression buffer size cannot be changed because it is in use");
- return;
- }
+ png_warning(png_ptr,
+ "Compression buffer size limited to system maximum");
+ size = ZLIB_IO_MAX; /* must fit */
+ }
+#endif
- if (size > ZLIB_IO_MAX)
- {
- png_warning(png_ptr,
- "Compression buffer size limited to system maximum");
- size = ZLIB_IO_MAX; /* must fit */
- }
+ if (size < 6)
+ {
+ /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
+ * if this is permitted.
+ */
+ png_warning(png_ptr,
+ "Compression buffer size cannot be reduced below 6");
- else if (size < 6)
- {
- /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
- * if this is permitted.
- */
- png_warning(png_ptr,
- "Compression buffer size cannot be reduced below 6");
- return;
- }
+ return;
+ }
- if (png_ptr->zbuffer_size != size)
- {
- png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
- png_ptr->zbuffer_size = (uInt)size;
- }
+ if (png_ptr->zbuffer_size != size)
+ {
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
+ png_ptr->zbuffer_size = (uInt)size;
}
+ }
# endif
}
@@ -1525,7 +1626,7 @@ void PNGAPI
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
{
if (png_ptr != NULL && info_ptr != NULL)
- info_ptr->valid &= ~mask;
+ info_ptr->valid &= (unsigned int)(~mask);
}
@@ -1537,7 +1638,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
{
/* Images with dimensions larger than these limits will be
* rejected by png_set_IHDR(). To accept any PNG datastream
- * regardless of dimensions, set both limits to 0x7ffffffL.
+ * regardless of dimensions, set both limits to 0x7fffffff.
*/
if (png_ptr == NULL)
return;
@@ -1550,8 +1651,8 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
void PNGAPI
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
{
- if (png_ptr != NULL)
- png_ptr->user_chunk_cache_max = user_chunk_cache_max;
+ if (png_ptr != NULL)
+ png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}
/* This function was added to libpng 1.4.1 */
@@ -1608,4 +1709,94 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
png_ptr->num_palette_max = -1;
}
#endif
+
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
+ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+ *
+ * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0'). If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must png_error.
+ */
+png_uint_32 /* PRIVATE */
+png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
+{
+#ifdef PNG_WARNINGS_SUPPORTED
+ png_const_charp orig_key = key;
+#endif
+ png_uint_32 key_len = 0;
+ int bad_character = 0;
+ int space = 1;
+
+ png_debug(1, "in png_check_keyword");
+
+ if (key == NULL)
+ {
+ *new_key = 0;
+ return 0;
+ }
+
+ while (*key && key_len < 79)
+ {
+ png_byte ch = (png_byte)*key++;
+
+ if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+ {
+ *new_key++ = ch; ++key_len; space = 0;
+ }
+
+ else if (space == 0)
+ {
+ /* A space or an invalid character when one wasn't seen immediately
+ * before; output just a space.
+ */
+ *new_key++ = 32; ++key_len; space = 1;
+
+ /* If the character was not a space then it is invalid. */
+ if (ch != 32)
+ bad_character = ch;
+ }
+
+ else if (bad_character == 0)
+ bad_character = ch; /* just skip it, record the first error */
+ }
+
+ if (key_len > 0 && space != 0) /* trailing space */
+ {
+ --key_len; --new_key;
+ if (bad_character == 0)
+ bad_character = 32;
+ }
+
+ /* Terminate the keyword */
+ *new_key = 0;
+
+ if (key_len == 0)
+ return 0;
+
+#ifdef PNG_WARNINGS_SUPPORTED
+ /* Try to only output one warning per keyword: */
+ if (*key != 0) /* keyword too long */
+ png_warning(png_ptr, "keyword truncated");
+
+ else if (bad_character != 0)
+ {
+ PNG_WARNING_PARAMETERS(p)
+
+ png_warning_parameter(p, 1, orig_key);
+ png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+ png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+ }
+#else /* !WARNINGS */
+ PNG_UNUSED(png_ptr)
+#endif /* !WARNINGS */
+
+ return key_len;
+}
+#endif /* TEXT || pCAL || iCCP || sPLT */
#endif /* READ || WRITE */