diff --git a/src/include/OpenImageIO/tiffutils.h b/src/include/OpenImageIO/tiffutils.h index 87ed742fd8..31765164ed 100644 --- a/src/include/OpenImageIO/tiffutils.h +++ b/src/include/OpenImageIO/tiffutils.h @@ -181,8 +181,8 @@ 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_API bool decode_exif (string_view exif, ImageSpec &spec); +OIIO_NODISCARD_ERROR OIIO_API bool decode_exif (cspan 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 @@ -210,10 +210,10 @@ 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); +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 @@ -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/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 7b04553a89..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; } @@ -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/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.) 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)) {