fix: beef up Exif error detection (#5322)
One small improvement in how decode_exif detects corruption, to ensure that the initial header examination doesn't read past the array bounds -- by starting off with a check that the exif blob's size is at least a big as a TIFFHeader, otherwise parsing it is pointless. Then the rest of the changes are finding places where readers call decode_exif but ignore the results, effectively ignoring corrupt Exif blobs. That is in fact the default intended behavior (if the rest of the image file can be read properly), but we are supposed to be checking the global "imageinput:strict" attribute and considering it a hard error when in strict mode. There were several places where we didn't handle that case, in the JPEG, PNG, WebP, and Heif readers. --------- Signed-off-by: Larry Gritz <lg@larrygritz.com>
This commit is contained in:
@@ -412,12 +412,20 @@ HeifInput::seek_subimage(int subimage, int miplevel)
|
||||
if (Strutil::iequals(m_ihandle.get_metadata_type(m), "Exif")
|
||||
&& metacontents.size() >= 10) {
|
||||
cspan<uint8_t> s(&metacontents[10], metacontents.size() - 10);
|
||||
decode_exif(s, m_spec);
|
||||
bool ok = decode_exif(s, m_spec);
|
||||
if (!ok && OIIO::get_int_attribute("imageinput:strict")) {
|
||||
errorfmt("Could not decode Exif");
|
||||
return false;
|
||||
}
|
||||
} else if (0 // For now, skip this, I haven't seen anything useful
|
||||
&& Strutil::iequals(m_ihandle.get_metadata_type(m), "mime")
|
||||
&& Strutil::iequals(m_ihandle.get_metadata_content_type(m),
|
||||
"application/rdf+xml")) {
|
||||
decode_xmp(metacontents, m_spec);
|
||||
bool ok = decode_xmp(metacontents, m_spec);
|
||||
if (!ok && OIIO::get_int_attribute("imageinput:strict")) {
|
||||
errorfmt("Could not decode XMP");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
print(
|
||||
|
||||
@@ -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");
|
||||
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
|
||||
|
||||
@@ -1233,6 +1233,8 @@ decode_exif(cspan<uint8_t> exif, ImageSpec& spec)
|
||||
// N.B. Just read libtiff's "tiff.h" for info on the structure
|
||||
// layout of TIFF headers and directory entries. The TIFF spec
|
||||
// itself is also helpful in this area.
|
||||
if (exif.size() < sizeof(TIFFHeader))
|
||||
return false;
|
||||
TIFFHeader head = *(const TIFFHeader*)exif.data();
|
||||
if (head.tiff_magic != 0x4949 && head.tiff_magic != 0x4d4d)
|
||||
return false;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -282,7 +282,12 @@ read_info(png_structp& sp, png_infop& ip, int& bit_depth, int& color_type,
|
||||
// Most PNG files seem to encode Exif by cramming it into a text
|
||||
// field, with the key "Raw profile type exif" and then a special
|
||||
// text encoding that we handle with the following function:
|
||||
decode_png_text_exif(text_ptr[i].text, spec);
|
||||
bool ok = decode_png_text_exif(text_ptr[i].text, spec);
|
||||
if (!ok && OIIO::get_int_attribute("imageinput:strict")) {
|
||||
ImageInput* pnginput = (ImageInput*)png_get_io_ptr(sp);
|
||||
pnginput->errorfmt("Could not decode Exif");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
spec.attribute(text_ptr[i].key, text_ptr[i].text);
|
||||
}
|
||||
@@ -345,7 +350,13 @@ 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<uint8_t>(exif_data, span_size_t(num_exif)), spec);
|
||||
bool ok = decode_exif(cspan<uint8_t>(exif_data, span_size_t(num_exif)),
|
||||
spec);
|
||||
if (!ok && OIIO::get_int_attribute("imageinput:strict")) {
|
||||
ImageInput* pnginput = (ImageInput*)png_get_io_ptr(sp);
|
||||
pnginput->errorfmt("Could not decode Exif");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1353,7 +1353,7 @@ PSDInput::load_resource_1058(uint32_t length)
|
||||
|
||||
if (!decode_exif(data, m_composite_attribs)
|
||||
|| !decode_exif(data, m_common_attribs)) {
|
||||
errorfmt("Failed to decode Exif data");
|
||||
errorfmt("Could not decode Exif");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -207,8 +207,13 @@ WebpInput::open(const std::string& name, ImageSpec& spec,
|
||||
if (m_demux_flags & EXIF_FLAG
|
||||
&& WebPDemuxGetChunk(m_demux, "EXIF", 1, &chunk_iter)) {
|
||||
cspan<uint8_t> exif_span(chunk_iter.chunk.bytes, chunk_iter.chunk.size);
|
||||
if (webp_exif_payload_has_tiff_header(exif_span))
|
||||
decode_exif(exif_span, m_spec);
|
||||
if (webp_exif_payload_has_tiff_header(exif_span)) {
|
||||
bool ok = decode_exif(exif_span, m_spec);
|
||||
if (!ok && OIIO::get_int_attribute("imageinput:strict")) {
|
||||
errorfmt("Could not decode Exif");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
}
|
||||
if (m_demux_flags & XMP_FLAG
|
||||
|
||||
@@ -2090,7 +2090,7 @@ src/Layers_32bit_RGB.psd : 48 x 27, 3 channel, float psd
|
||||
stEvt:instanceID: "xmp.iid:68fcb000-4377-c148-974d-bdd193ca024d; xmp.iid:cbd904c5-53b4-0d4e-9ff8-37ac35429f46"
|
||||
stEvt:softwareAgent: "Adobe Photoshop 23.3 (Windows)"
|
||||
stEvt:when: "2024-04-01T19:35:16+02:00"
|
||||
oiiotool ERROR: read : Failed to decode Exif data
|
||||
oiiotool ERROR: read : Could not decode Exif
|
||||
failed to open "src/crash-psd-exif-1632.psd": failed load_resources
|
||||
Full command line was:
|
||||
> oiiotool --info -v -a --hash src/crash-psd-exif-1632.psd
|
||||
|
||||
@@ -2090,7 +2090,7 @@ src/Layers_32bit_RGB.psd : 48 x 27, 3 channel, float psd
|
||||
stEvt:instanceID: "xmp.iid:68fcb000-4377-c148-974d-bdd193ca024d; xmp.iid:cbd904c5-53b4-0d4e-9ff8-37ac35429f46"
|
||||
stEvt:softwareAgent: "Adobe Photoshop 23.3 (Windows)"
|
||||
stEvt:when: "2024-04-01T19:35:16+02:00"
|
||||
oiiotool ERROR: read : Failed to decode Exif data
|
||||
oiiotool ERROR: read : Could not decode Exif
|
||||
failed to open "src/crash-psd-exif-1632.psd": failed load_resources
|
||||
Full command line was:
|
||||
> oiiotool --info -v -a --hash src/crash-psd-exif-1632.psd
|
||||
|
||||
Reference in New Issue
Block a user