From 957c20b6769bc1f64da268c09b62079dfb6c850c Mon Sep 17 00:00:00 2001 From: MacDue Date: Sat, 17 Feb 2024 18:53:32 +0000 Subject: [PATCH] LibWeb: Avoid infinite recursion when hit testing SVGs Previously, step 5 of the stacking context hit testing would just call `hit_test()` on the stacking context's paintable box. Which (at least for SVGs) is just indirect infinite recursion (it'll end up right back where it started after going through a few functions). This now explicitly hit tests the descendants, which seems more correct, and avoids the crash for SVGs, but nothing really seems to depend on this step. Another solution (which I've done for a while working on SVGs) is just to delete step 5 entirely, and nothing seems to break. Fixes #22305 --- Userland/Libraries/LibWeb/Painting/StackingContext.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index beafa5b2dd..4a63d1a3c3 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -425,8 +425,12 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks. if (paintable().layout_node().children_are_inline() && is(paintable().layout_node())) { - if (paintable_box().hit_test(transformed_position, type, callback) == TraversalDecision::Break) - return TraversalDecision::Break; + for (auto const* child = paintable().last_child(); child; child = child->previous_sibling()) { + if (child->is_inline() && !child->is_absolutely_positioned() && !child->stacking_context()) { + if (child->hit_test(transformed_position, type, callback) == TraversalDecision::Break) + return TraversalDecision::Break; + } + } } // 4. the non-positioned floats.