From db58986e5f5f6ef67c3e97c5f888b7e6c4369389 Mon Sep 17 00:00:00 2001 From: Jaycadox Date: Sun, 22 Dec 2024 23:27:36 +1000 Subject: [PATCH] LibWeb/CSS: Recalculate calc() numeric type when resolving percentages Previously, `percentage_of` would be called on the previous value, potentially changing its numeric type, yet this potential change was never reflected as the old numeric type was always used. Now, the numeric type will be re-calculated every time after the percentage is resolved. As well, VERIFY checks have been placed to uphold the requirements for the numeric types to match what the actual values are. --- .../CSS/StyleValues/CalculatedStyleValue.cpp | 19 +++++++++++++++---- .../css/singular-percentage-calc-crash.txt | 1 + .../css/singular-percentage-calc-crash.html | 12 ++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/singular-percentage-calc-crash.txt create mode 100644 Tests/LibWeb/Text/input/css/singular-percentage-calc-crash.html diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp index 6fa6b1eb850..36067121644 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp @@ -109,12 +109,12 @@ CalculationNode::CalculationNode(Type type, Optional numeric_typ CalculationNode::~CalculationNode() = default; -NonnullOwnPtr NumericCalculationNode::create(NumericValue value, Optional percentage_resolved_type) +static CSSNumericType numeric_type_from_calculated_style_value(CalculatedStyleValue::CalculationResult::Value const& value, Optional percentage_resolved_type) { // https://drafts.csswg.org/css-values-4/#determine-the-type-of-a-calculation // Anything else is a terminal value, whose type is determined based on its CSS type. // (Unless otherwise specified, the type’s associated percent hint is null.) - auto numeric_type = value.visit( + return value.visit( [](Number const&) { // -> // -> @@ -172,7 +172,11 @@ NonnullOwnPtr NumericCalculationNode::create(NumericValu // result.set_percent_hint(CSSNumericType::BaseType::Percent); return result; }); +} +NonnullOwnPtr NumericCalculationNode::create(NumericValue value, Optional percentage_resolved_type) +{ + auto numeric_type = numeric_type_from_calculated_style_value(value, percentage_resolved_type); return adopt_own(*new (nothrow) NumericCalculationNode(move(value), numeric_type)); } @@ -200,11 +204,13 @@ CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(Optional // NOTE: Depending on whether percentage_basis is set, the caller of resolve() is expecting a raw percentage or // resolved type. return percentage_basis.visit( - [&](Empty const&) -> CalculatedStyleValue::CalculationResult { + [&](Empty const&) { + VERIFY(numeric_type_from_calculated_style_value(m_value, {}) == numeric_type()); return CalculatedStyleValue::CalculationResult::from_value(m_value, resolution_context, numeric_type()); }, [&](auto const& value) { - return CalculatedStyleValue::CalculationResult::from_value(value.percentage_of(m_value.get()), resolution_context, numeric_type()); + auto const calculated_value = value.percentage_of(m_value.get()); + return CalculatedStyleValue::CalculationResult::from_value(calculated_value, resolution_context, numeric_type_from_calculated_style_value(calculated_value, {})); }); } @@ -1730,6 +1736,11 @@ bool RemCalculationNode::equals(CalculationNode const& other) const CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult::from_value(Value const& value, Optional context, Optional numeric_type) { + auto const expected_numeric_type = numeric_type_from_calculated_style_value(value, {}); + if (numeric_type.has_value()) { + VERIFY(numeric_type.value() == expected_numeric_type); + } + auto number = value.visit( [](Number const& number) { return number.value(); }, [](Angle const& angle) { return angle.to_degrees(); }, diff --git a/Tests/LibWeb/Text/expected/css/singular-percentage-calc-crash.txt b/Tests/LibWeb/Text/expected/css/singular-percentage-calc-crash.txt new file mode 100644 index 00000000000..50586a4cbfb --- /dev/null +++ b/Tests/LibWeb/Text/expected/css/singular-percentage-calc-crash.txt @@ -0,0 +1 @@ +PASS! (Didn't crash) diff --git a/Tests/LibWeb/Text/input/css/singular-percentage-calc-crash.html b/Tests/LibWeb/Text/input/css/singular-percentage-calc-crash.html new file mode 100644 index 00000000000..62a88bff93e --- /dev/null +++ b/Tests/LibWeb/Text/input/css/singular-percentage-calc-crash.html @@ -0,0 +1,12 @@ + + +
+ \ No newline at end of file