Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: b5f2f7a39314cb9ae2cbf20df1476db3171e09fb
      
https://github.com/WebKit/WebKit/commit/b5f2f7a39314cb9ae2cbf20df1476db3171e09fb
  Author: Ahmad Saleem <[email protected]>
  Date:   2026-10-13 (Tue, 13 Oct 2026)

  Changed paths:
    A 
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-path-huge-coordinates-expected.txt
    A 
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-path-huge-coordinates.html
    M Source/WebCore/rendering/shapes/PathLayoutShape.cpp

  Log Message:
  -----------
  shape-outside: path() with huge coordinates hangs the web process
https://bugs.webkit.org/show_bug.cgi?id=326185
rdar://189068646

Reviewed by Simon Fraser.

PathLayoutShape::getExcludedInterval() is called once per line box while
laying out inline content around a shaped float. For a non-zero shape-margin
it approximated each edge's contribution by sampling one point per unit of
edge length:

    auto steps = static_cast<unsigned>(std::ceil(span.diagonalLength()));
    for (unsigned step = 1; step < steps; ++step)
        includePoint(start + span.scaled(float(step) / steps));

This had two problems. The work was O(perimeter) per line regardless of
where the line sat, and a path with huge coordinates (e.g.
path("M 0 0 L 1e30 0 L 0 50 Z")) made diagonalLength() overflow float to
inf. Casting an out-of-range float to unsigned is undefined behavior; on
arm64 it saturates to UINT_MAX, so the loop ran ~4 billion times per line
and hung the web process. Other browsers lay the same content out fine.

Replace the sampling with an exact O(1)-per-edge computation. Along a single
edge the horizontal extent x +/- reach is piecewise concave/convex, so its
extremes only occur at the endpoints, the band edges (y1, y2), the
margin-extended boundaries (y1 - margin, y2 + margin), and the tangent points
where the margin disk touches a band edge (offset along the edge by
margin * (unit direction).x, computed with hypot() to avoid overflow).
Evaluating just those points through the existing includePoint() reach logic
is independent of coordinate magnitude, and is also slightly more accurate
than the old sampler (it no longer misses thin tangents between samples).

Test: fast/shapes/shape-outside-floats/shape-outside-path-huge-coordinates.html

* 
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-path-huge-coordinates-expected.txt:
 Added.
* 
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-path-huge-coordinates.html:
 Added.
* Source/WebCore/rendering/shapes/PathLayoutShape.cpp:
(WebCore::PathLayoutShape::getExcludedInterval const):

Canonical link: https://commits.webkit.org/323694@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to