From 6f95ec58215a3b49c839ec8c1ff10974d6e78ed3 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 12 Feb 2023 10:44:32 -0500 Subject: [PATCH] LibGfx: Validate presence of curves for lutAToBType and lutBToAType --- Userland/Libraries/LibGfx/ICC/TagTypes.cpp | 16 ++++++++++++++++ Userland/Libraries/LibGfx/ICC/TagTypes.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/Userland/Libraries/LibGfx/ICC/TagTypes.cpp b/Userland/Libraries/LibGfx/ICC/TagTypes.cpp index 978e41791ad..bb7ac8f4d9f 100644 --- a/Userland/Libraries/LibGfx/ICC/TagTypes.cpp +++ b/Userland/Libraries/LibGfx/ICC/TagTypes.cpp @@ -471,6 +471,10 @@ ErrorOr> LutAToBTagData::from_bytes(ReadonlyBytes return Error::from_string_literal("ICC::Profile: lutAToBType no CLUT despite different number of input and output channels"); } + // Follows from the "Only the following combinations are permitted" list in 10.12.1. + if (a_curves.has_value() != clut_data.has_value()) + return Error::from_string_literal("ICC::Profile: lutAToBType must have 'A' curves exactly if it has a CLUT"); + // 10.12.4 “M” curves // "There are the same number of “M” curves as there are output channels. The curves are stored sequentially, // with 00h bytes used for padding between them if needed. Each “M” curve is stored as an embedded curveType @@ -495,6 +499,10 @@ ErrorOr> LutAToBTagData::from_bytes(ReadonlyBytes e->e[i] = S15Fixed16::create_raw(raw_e[i]); } + // Follows from the "Only the following combinations are permitted" list in 10.12.1. + if (m_curves.has_value() != e.has_value()) + return Error::from_string_literal("ICC::Profile: lutAToBType must have 'M' curves exactly if it has a matrix"); + // 10.12.6 “B” curves // "There are the same number of “B” curves as there are output channels. The curves are stored sequentially, with // 00h bytes used for padding between them if needed. Each “B” curve is stored as an embedded curveType or a @@ -556,6 +564,10 @@ ErrorOr> LutBToATagData::from_bytes(ReadonlyBytes if (header.offset_to_m_curves) m_curves = TRY(read_curves(bytes, header.offset_to_m_curves, header.number_of_input_channels)); + // Follows from the "Only the following combinations are permitted" list in 10.13.1. + if (e.has_value() != m_curves.has_value()) + return Error::from_string_literal("ICC::Profile: lutBToAType must have matrix exactly if it has 'M' curves"); + // 10.13.5 CLUT Optional clut_data; if (header.offset_to_clut) { @@ -575,6 +587,10 @@ ErrorOr> LutBToATagData::from_bytes(ReadonlyBytes if (header.offset_to_a_curves) a_curves = TRY(read_curves(bytes, header.offset_to_a_curves, header.number_of_output_channels)); + // Follows from the "Only the following combinations are permitted" list in 10.13.1. + if (clut_data.has_value() != a_curves.has_value()) + return Error::from_string_literal("ICC::Profile: lutBToAType must have A clut exactly if it has 'A' curves"); + return try_make_ref_counted(offset, size, header.number_of_input_channels, header.number_of_output_channels, move(b_curves), e, move(m_curves), move(clut_data), move(a_curves)); } diff --git a/Userland/Libraries/LibGfx/ICC/TagTypes.h b/Userland/Libraries/LibGfx/ICC/TagTypes.h index 05fcba3dee4..2e4ac26e587 100644 --- a/Userland/Libraries/LibGfx/ICC/TagTypes.h +++ b/Userland/Libraries/LibGfx/ICC/TagTypes.h @@ -327,6 +327,8 @@ public: VERIFY(!m_a_curves.has_value() || m_a_curves->size() == m_number_of_input_channels); VERIFY(!m_m_curves.has_value() || m_m_curves->size() == m_number_of_output_channels); VERIFY(m_b_curves.size() == m_number_of_output_channels); + VERIFY(m_a_curves.has_value() == m_clut.has_value()); + VERIFY(m_m_curves.has_value() == m_e.has_value()); } u8 number_of_input_channels() const { return m_number_of_input_channels; } @@ -377,6 +379,8 @@ public: VERIFY(m_b_curves.size() == m_number_of_input_channels); VERIFY(!m_m_curves.has_value() || m_m_curves->size() == m_number_of_input_channels); VERIFY(!m_a_curves.has_value() || m_a_curves->size() == m_number_of_output_channels); + VERIFY(m_e.has_value() == m_m_curves.has_value()); + VERIFY(m_clut.has_value() == m_a_curves.has_value()); } u8 number_of_input_channels() const { return m_number_of_input_channels; }