From c5937d7a6f7965b492d2f5cc74b80087214d3032 Mon Sep 17 00:00:00 2001 From: rose413 <116857309+rose413@users.noreply.github.com> Date: Wed, 27 May 2026 13:00:32 -0700 Subject: [PATCH 1/2] api: add OIIO_NODISCARD_ERROR to tiffutils.h Add OIIO_NODISCARD_ERROR to the following functions in tiffutils.h to enforce that callers check their bool return values: - decode_exif - decode_iptc_iim - encode_iptc_iim - decode_xmp - decode_icc_profile Fix callers in tiffoutput.cpp, png_pvt.h, and webpinput.cpp that were previously ignoring return values. - Assisted-by: Claude Sonnet 4.6 Signed-off-by: rose413 <116857309+rose413@users.noreply.github.com> --- src/include/OpenImageIO/tiffutils.h | 10 +++++----- src/png.imageio/png_pvt.h | 9 ++++++++- src/tiff.imageio/tiffoutput.cpp | 5 ++++- src/webp.imageio/webpinput.cpp | 7 ++++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/include/OpenImageIO/tiffutils.h b/src/include/OpenImageIO/tiffutils.h index 87ed742fd8..0dccceda96 100644 --- a/src/include/OpenImageIO/tiffutils.h +++ b/src/include/OpenImageIO/tiffutils.h @@ -181,7 +181,7 @@ tiff_dir_data (const TIFFDirEntry &td, cspan data); /// ImageSpec. Return true if all is ok, false if the exif block was /// somehow malformed. The binary data pointed to by 'exif' should /// start with a TIFF directory header. -OIIO_API bool decode_exif (cspan exif, ImageSpec &spec); +OIIO_NODISCARD_ERROR OIIO_API bool decode_exif (cspan exif, ImageSpec &spec); OIIO_API bool decode_exif (string_view exif, ImageSpec &spec); /// Construct an Exif data block from the ImageSpec, appending the Exif @@ -210,7 +210,7 @@ OIIO_API bool gps_tag_lookup (string_view name, int &tag, /// metadata without having to duplicate functionality within each /// plugin. Note that IIM is actually considered obsolete and is /// replaced by an XML scheme called XMP. -OIIO_API bool decode_iptc_iim (string_view iptc, ImageSpec &spec); +OIIO_NODISCARD_ERROR OIIO_API bool decode_iptc_iim (string_view iptc, ImageSpec &spec); // DEPRECATED(3.2) -- unsafe version OIIO_API bool decode_iptc_iim (const void *iptc, int length, ImageSpec &spec); @@ -222,14 +222,14 @@ OIIO_API bool decode_iptc_iim (const void *iptc, int length, ImageSpec &spec); /// that IIM is actually considered obsolete and is replaced by an XML /// scheme called XMP. Return true if it was successful and any items /// were encoded. -OIIO_API bool encode_iptc_iim (const ImageSpec &spec, std::vector &iptc); +OIIO_NODISCARD_ERROR OIIO_API bool encode_iptc_iim (const ImageSpec &spec, std::vector &iptc); /// Add metadata to spec based on XMP data in an XML block. Return true /// if all is ok, false if the xml was somehow malformed. This is a /// utility function to make it easy for multiple format plugins to /// support embedding XMP metadata without having to duplicate /// functionality within each plugin. -OIIO_API bool decode_xmp (cspan xml, ImageSpec &spec); +OIIO_NODISCARD_ERROR OIIO_API bool decode_xmp (cspan xml, ImageSpec &spec); OIIO_API bool decode_xmp (string_view xml, ImageSpec &spec); /// Find all the relevant metadata (IPTC, Exif, etc.) in spec and @@ -246,7 +246,7 @@ OIIO_API std::string encode_xmp (const ImageSpec &spec, bool minimal=false); /// the contents of `error` to something useful). This is a utility function /// to make it easy for multiple format plugins to support embedding ICC /// metadata without having to duplicate functionality within each plugin. -OIIO_API bool decode_icc_profile(cspan iccdata, ImageSpec& spec, +OIIO_NODISCARD_ERROR OIIO_API bool decode_icc_profile(cspan iccdata, ImageSpec& spec, std::string& error); diff --git a/src/png.imageio/png_pvt.h b/src/png.imageio/png_pvt.h index 7b04553a89..ecd20f09c6 100644 --- a/src/png.imageio/png_pvt.h +++ b/src/png.imageio/png_pvt.h @@ -345,7 +345,14 @@ read_info(png_structp& sp, png_infop& ip, int& bit_depth, int& color_type, png_uint_32 num_exif = 0; png_bytep exif_data = nullptr; if (png_get_eXIf_1(sp, ip, &num_exif, &exif_data)) { - decode_exif(cspan(exif_data, span_size_t(num_exif)), spec); + bool ok = decode_exif(cspan(exif_data, span_size_t(num_exif)), + spec); + if (!ok) { + ImageInput* pnginput = (ImageInput*)png_get_io_ptr(sp); + if (pnginput) + pnginput->errorfmt( + "Could not decode Exif metadata from PNG eXIf chunk"); + } } #endif diff --git a/src/tiff.imageio/tiffoutput.cpp b/src/tiff.imageio/tiffoutput.cpp index 8356d312a1..6f00800f45 100644 --- a/src/tiff.imageio/tiffoutput.cpp +++ b/src/tiff.imageio/tiffoutput.cpp @@ -934,7 +934,10 @@ TIFFOutput::open(const std::string& name, const ImageSpec& userspec, // was because of a size mixup on our part that has since been fixed. // Should we re-enable it by default in the future? std::vector iptc; - encode_iptc_iim(m_spec, iptc); + bool iptc_ok = encode_iptc_iim(m_spec, iptc); + if (!iptc_ok) { + errorfmt("Failed to encode IPTC metadata for writing"); + } if (iptc.size()) { TIFFSetField(m_tif, TIFFTAG_RICHTIFFIPTC, iptc.size(), &iptc[0]); } diff --git a/src/webp.imageio/webpinput.cpp b/src/webp.imageio/webpinput.cpp index 86eb80f55c..92170add01 100644 --- a/src/webp.imageio/webpinput.cpp +++ b/src/webp.imageio/webpinput.cpp @@ -195,9 +195,14 @@ WebpInput::open(const std::string& name, ImageSpec& spec, if (m_demux_flags & EXIF_FLAG && WebPDemuxGetChunk(m_demux, "EXIF", 1, &chunk_iter)) { cspan exif_span(chunk_iter.chunk.bytes, chunk_iter.chunk.size); + bool ok = true; if (webp_exif_payload_has_tiff_header(exif_span)) - decode_exif(exif_span, m_spec); + ok = decode_exif(exif_span, m_spec); WebPDemuxReleaseChunkIterator(&chunk_iter); + if (!ok && OIIO::get_int_attribute("imageinput:strict")) { + errorfmt("Possible corrupt file, could not decode EXIF metadata"); + return false; + } } if (m_demux_flags & XMP_FLAG && WebPDemuxGetChunk(m_demux, "XMP ", 1, &chunk_iter)) { From dbd7f486011c7ee0052f0429bb15344e1f678df1 Mon Sep 17 00:00:00 2001 From: rose413 <116857309+rose413@users.noreply.github.com> Date: Wed, 27 May 2026 15:11:49 -0700 Subject: [PATCH 2/2] api: add nodiscard annotations to decode/encode metadata functions in tiffutils.h - Annotate decode_exif, decode_iptc_iim, exif_tag_lookup , and gps_tag_lookup with OIIO_NODISCARD_ERROR. - Fix all call sites in png_pvt.h, tiffinput.cpp, and jpeginput.cpp - Assisted-by: Claude Sonnet 4.6 Signed-off-by: rose413 <116857309+rose413@users.noreply.github.com> --- src/include/OpenImageIO/tiffutils.h | 8 ++++---- src/jpeg.imageio/jpeginput.cpp | 9 +++++++-- src/png.imageio/png_pvt.h | 2 +- src/tiff.imageio/tiffinput.cpp | 5 ++++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/include/OpenImageIO/tiffutils.h b/src/include/OpenImageIO/tiffutils.h index 0dccceda96..31765164ed 100644 --- a/src/include/OpenImageIO/tiffutils.h +++ b/src/include/OpenImageIO/tiffutils.h @@ -182,7 +182,7 @@ tiff_dir_data (const TIFFDirEntry &td, cspan data); /// somehow malformed. The binary data pointed to by 'exif' should /// start with a TIFF directory header. OIIO_NODISCARD_ERROR OIIO_API bool decode_exif (cspan exif, ImageSpec &spec); -OIIO_API bool decode_exif (string_view exif, ImageSpec &spec); +OIIO_NODISCARD_ERROR OIIO_API bool decode_exif (string_view exif, ImageSpec &spec); /// Construct an Exif data block from the ImageSpec, appending the Exif /// data as a big blob to the char vector. Endianness can be specified with @@ -193,13 +193,13 @@ OIIO_API void encode_exif (const ImageSpec &spec, std::vector &blob, /// Helper: For the given OIIO metadata attribute name, look up the Exif tag /// ID, TIFFDataType (expressed as an int), and count. Return true and fill /// in the fields if found, return false if not found. -OIIO_API bool exif_tag_lookup (string_view name, int &tag, +OIIO_NODISCARD_ERROR OIIO_API bool exif_tag_lookup (string_view name, int &tag, int &tifftype, int &count); /// Helper: For the given OIIO metadata attribute name, look up the GPS tag /// ID, TIFFDataType (expressed as an int), and count. Return true and fill /// in the fields if found, return false if not found. -OIIO_API bool gps_tag_lookup (string_view name, int &tag, +OIIO_NODISCARD_ERROR OIIO_API bool gps_tag_lookup (string_view name, int &tag, int &tifftype, int &count); /// Add metadata to spec based on raw IPTC (International Press @@ -213,7 +213,7 @@ OIIO_API bool gps_tag_lookup (string_view name, int &tag, OIIO_NODISCARD_ERROR OIIO_API bool decode_iptc_iim (string_view iptc, ImageSpec &spec); // DEPRECATED(3.2) -- unsafe version -OIIO_API bool decode_iptc_iim (const void *iptc, int length, ImageSpec &spec); +OIIO_NODISCARD_ERROR OIIO_API bool decode_iptc_iim (const void *iptc, int length, ImageSpec &spec); /// Find all the IPTC-amenable metadata in spec and assemble it into an /// IIM data block in iptc. This is a utility function to make it easy diff --git a/src/jpeg.imageio/jpeginput.cpp b/src/jpeg.imageio/jpeginput.cpp index e606ecd872..e0e1d5f6bd 100644 --- a/src/jpeg.imageio/jpeginput.cpp +++ b/src/jpeg.imageio/jpeginput.cpp @@ -296,8 +296,13 @@ JpgInput::open(const std::string& name, ImageSpec& newspec) if (is_exif_marker(m)) { // The block starts with "Exif\0\0", so skip 6 bytes to get // to the start of the actual Exif data TIFF directory - decode_exif(string_view((char*)m->data + 6, m->data_length - 6), - m_spec); + bool ok = decode_exif(string_view((char*)m->data + 6, + m->data_length - 6), + m_spec); + if (!ok && OIIO::get_int_attribute("imageinput:strict")) { + errorfmt("Could not decode Exif data in JPEG file"); + return false; + } } else if (m->marker == (JPEG_APP0 + 1) && m->data_length >= 28 && !strncmp((const char*)m->data, "http://ns.adobe.com/xap/1.0/", 28)) { //NOSONAR diff --git a/src/png.imageio/png_pvt.h b/src/png.imageio/png_pvt.h index ecd20f09c6..34245b2b14 100644 --- a/src/png.imageio/png_pvt.h +++ b/src/png.imageio/png_pvt.h @@ -171,7 +171,7 @@ decode_png_text_exif(string_view raw, ImageSpec& spec) raw.remove_prefix(2); } if (Strutil::istarts_with(decoded, "Exif")) { - decode_exif(decoded, spec); + return decode_exif(decoded, spec); } return false; } diff --git a/src/tiff.imageio/tiffinput.cpp b/src/tiff.imageio/tiffinput.cpp index 2a0ccf5ed2..96bf1e5397 100644 --- a/src/tiff.imageio/tiffinput.cpp +++ b/src/tiff.imageio/tiffinput.cpp @@ -1509,7 +1509,10 @@ TIFFInput::readspec(bool read_meta) } else { iptc.assign(iptcdata, iptcdata + iptcsize); } - decode_iptc_iim(&iptc[0], iptcsize, m_spec); + bool ok = decode_iptc_iim(&iptc[0], iptcsize, m_spec); + if (!ok && OIIO::get_int_attribute("imageinput:strict")) { + errorfmt("Could not decode IPTC metadata in TIFF file"); + } } // Search for an XML packet containing XMP (IPTC, Exif, etc.)