LibGfx/TIFF: Don't stop decoding when failing to decode a tag

TIFF files are made in a way that make them easily extendable and over
the years people have made sure to exploit that. In other words, it's
easy to find images with non-standard tags. Instead of returning an
error for that, let's skip them.

Note that we need to make sure to realign the reading head in the file.

The test case was originally a 10x10 checkerboard image with required
tags, and also the `DocumentName` tag. Then, I modified this tag in a
hexadecimal editor and replaced its id with 30 000 (0x3075 as a LE u16)
and the type with the same value as well. This is AFAIK, never used as
a custom TIFF tag, so this should remain an invalid tag id and type.
This commit is contained in:
Lucas CHOLLET 2023-12-29 23:54:47 -05:00 committed by Andreas Kling
parent 6d1c10ed10
commit b8cbc282f3
Notes: sideshowbarker 2024-07-16 21:45:42 +09:00
3 changed files with 23 additions and 2 deletions

View file

@ -546,6 +546,18 @@ TEST_CASE(test_tiff_16_bits)
EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red); EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red);
} }
TEST_CASE(test_tiff_invalid_tag)
{
auto file = MUST(Core::MappedFile::map(TEST_INPUT("tiff/invalid_tag.tiff"sv)));
EXPECT(Gfx::TIFFImageDecoderPlugin::sniff(file->bytes()));
auto plugin_decoder = TRY_OR_FAIL(Gfx::TIFFImageDecoderPlugin::create(file->bytes()));
auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 10, 10 }));
EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color::NamedColor::Black);
EXPECT_EQ(frame.image->get_pixel(0, 9), Gfx::Color::NamedColor::White);
}
TEST_CASE(test_webp_simple_lossy) TEST_CASE(test_webp_simple_lossy)
{ {
auto file = MUST(Core::MappedFile::map(TEST_INPUT("webp/simple-vp8.webp"sv))); auto file = MUST(Core::MappedFile::map(TEST_INPUT("webp/simple-vp8.webp"sv)));

Binary file not shown.

View file

@ -387,9 +387,18 @@ private:
TRY(m_stream->seek(m_next_ifd.value())); TRY(m_stream->seek(m_next_ifd.value()));
auto const number_of_field = TRY(read_value<u16>()); auto const number_of_field = TRY(read_value<u16>());
auto next_tag_offset = TRY(m_stream->tell());
for (u16 i = 0; i < number_of_field; ++i) for (u16 i = 0; i < number_of_field; ++i) {
TRY(read_tag()); TRY(m_stream->seek(next_tag_offset));
if (auto maybe_error = read_tag(); maybe_error.is_error() && TIFF_DEBUG)
dbgln("Unable to decode tag {}/{}", i + 1, number_of_field);
// Section 2: TIFF Structure
// IFD Entry
// Size of tag(u16) + type(u16) + count(u32) + value_or_offset(u32) = 12
next_tag_offset += 12;
}
TRY(read_next_idf_offset()); TRY(read_next_idf_offset());
return {}; return {};