From b024e45c2ce54a908ffc856ae3c0c7b3ab541b48 Mon Sep 17 00:00:00 2001 From: sideshowbarker Date: Mon, 22 Jun 2026 08:30:14 +0900 Subject: [PATCH] LibWeb: Saturate CSSPixels::abs() at the i32 minimum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: CSSPixels::abs() invokes UB for the i32 minimum raw value. Cause: abs() returned from_raw(::abs(m_value)) — and ::abs() of the i32 minimum isn’t representable as an int. Fix: Compute the magnitude with saturating_sub(0, raw_value()) for negative inputs — so the i32 minimum saturates to the maximum. --- Libraries/LibWeb/PixelUnits.h | 2 +- Tests/LibWeb/TestCSSPixels.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Libraries/LibWeb/PixelUnits.h b/Libraries/LibWeb/PixelUnits.h index af1f4f937d..217e84664d 100644 --- a/Libraries/LibWeb/PixelUnits.h +++ b/Libraries/LibWeb/PixelUnits.h @@ -246,7 +246,7 @@ public: return *this; } - constexpr CSSPixels abs() const { return from_raw(::abs(m_value)); } + constexpr CSSPixels abs() const { return raw_value() < 0 ? from_raw(saturating_sub(0, raw_value())) : *this; } CSSPixels& scale_by(float value) { diff --git a/Tests/LibWeb/TestCSSPixels.cpp b/Tests/LibWeb/TestCSSPixels.cpp index c4b5a99309..56388b8b25 100644 --- a/Tests/LibWeb/TestCSSPixels.cpp +++ b/Tests/LibWeb/TestCSSPixels.cpp @@ -124,6 +124,14 @@ TEST_CASE(saturated_subtraction) EXPECT_EQ(value - -1, CSSPixels(INFINITY)); } +TEST_CASE(saturated_abs) +{ + // abs() of the minimum saturates to the maximum instead of overflowing. + EXPECT_EQ(CSSPixels::min().abs(), CSSPixels::max()); + EXPECT_EQ(CSSPixels::from_raw(-5).abs(), CSSPixels::from_raw(5)); + EXPECT_EQ(CSSPixels::from_raw(5).abs(), CSSPixels::from_raw(5)); +} + TEST_CASE(multiplication_uses_i64_for_raw_values) { CSSPixels a(1200);