aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCosmin Truta <ctruta@gmail.com>2023-06-21 16:16:07 +0300
committerCosmin Truta <ctruta@gmail.com>2023-06-21 16:16:07 +0300
commite6c5bf46c4fa3e3738a2ed0896ce33fc270e0cac (patch)
treecafb11c119f217f29d4b6a7a61d401a51dceb163
parent8be5c147d567bf90553088305208e612abb16768 (diff)
downloadlibpng-e6c5bf46c4fa3e3738a2ed0896ce33fc270e0cac.tar.gz
Ensure that only one eXIf chunk is written in the entire datastream
EXIF data can be stored in an eXIf chunk before IDAT, or after IDAT, but the entire PNG datastream may contain one eXIf chunk at most. Introduce the private mode flag PNG_WROTE_eXIf, which is meant to be used like the PNG_WROTE_tIME flag. The eXIf chunk and the tIME chunk have the same ordering rules (i.e. no constraints are imposed), and the same multiplicity rules (i.e. no multiples are allowed), and they should be initialized and checked using the same algorithm. This fixes commit cd03aaf7bf0e0c748b8c6cb34a56b402b40d61d0, previously reverted in 3d57708c9166419b7f5e0bbda2f7a2149112c844. Reported-by: Ben Bullock <benkasminbullock@gmail.com>
-rw-r--r--pngpriv.h4
-rw-r--r--pngset.c31
-rw-r--r--pngwrite.c10
3 files changed, 22 insertions, 23 deletions
diff --git a/pngpriv.h b/pngpriv.h
index 75411d967..7c19373f0 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -1,7 +1,7 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2023 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -626,7 +626,7 @@
#define PNG_BACKGROUND_IS_GRAY 0x800U
#define PNG_HAVE_PNG_SIGNATURE 0x1000U
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
- /* 0x4000U (unused) */
+#define PNG_WROTE_eXIf 0x4000U
#define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */
/* Flags for the transformations the PNG library does on the image data */
diff --git a/pngset.c b/pngset.c
index 8ce01dff7..3fc31feb0 100644
--- a/pngset.c
+++ b/pngset.c
@@ -137,44 +137,39 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
- png_bytep eXIf_buf)
+ png_bytep exif)
{
png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
PNG_UNUSED(info_ptr)
- PNG_UNUSED(eXIf_buf)
+ PNG_UNUSED(exif)
}
void PNGAPI
png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
- png_uint_32 num_exif, png_bytep eXIf_buf)
+ png_uint_32 num_exif, png_bytep exif)
{
- int i;
+ png_bytep new_exif;
png_debug1(1, "in %s storage function", "eXIf");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL ||
+ (png_ptr->mode & PNG_WROTE_eXIf) != 0)
return;
- if (info_ptr->exif)
- {
- png_free(png_ptr, info_ptr->exif);
- info_ptr->exif = NULL;
- }
+ new_exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, num_exif));
- 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)
+ if (new_exif == NULL)
{
png_warning(png_ptr, "Insufficient memory for eXIf chunk data");
return;
}
- for (i = 0; i < (int) info_ptr->num_exif; i++)
- info_ptr->exif[i] = eXIf_buf[i];
+ memcpy(new_exif, exif, (size_t)num_exif);
+ png_free_data(png_ptr, info_ptr, PNG_FREE_EXIF, 0);
+
+ info_ptr->num_exif = num_exif;
+ info_ptr->exif = new_exif;
info_ptr->free_me |= PNG_FREE_EXIF;
info_ptr->valid |= PNG_INFO_eXIf;
}
diff --git a/pngwrite.c b/pngwrite.c
index 4e58d776a..32f4bfbe7 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -1,7 +1,7 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2023 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -239,7 +239,10 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
#ifdef PNG_WRITE_eXIf_SUPPORTED
if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
+ {
png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
+ png_ptr->mode |= PNG_WROTE_eXIf;
+ }
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
@@ -439,8 +442,9 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
#endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
- if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
- png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
+ if ((info_ptr->valid & PNG_INFO_eXIf) != 0 &&
+ (png_ptr->mode & PNG_WROTE_eXIf) == 0)
+ png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED