← All issues

[18] [WebCore] Bound grid masonry span and exclude excluded-from-normal-layout from subgrid

Severity: Medium | Component: WebCore rendering (Grid masonry/subgrid) | ca8c809

Rated Medium because the diff fixes two related defects: RenderGrid::isSubgrid() now considers isExcludedFromNormalLayout() (fieldset <legend> no longer reports subgrid into a parent that never placed it) and gridAreaForIndefiniteGridAxisItem() clamps the auto-placement span to m_gridAxisTracksCount; both produce an unsigned underflow in release whose downstream effect is layout indexing on near-UINT_MAX values, with no observable JS-visible read/write primitive.

RenderGrid::isSubgrid() returns false when the child is excluded from normal layout; gridAreaForIndefiniteGridAxisItem() clamps the span size with std::min(itemSpanLength, m_gridAxisTracksCount) before computing gridAxisLines - itemSpanLength.

Source/WebCore/rendering/RenderGrid.cpp

- return style().gridRows().subgrid();
+ return style().gridRows().subgrid() && !isExcludedFromNormalLayout();

Unsigned underflow from missing precondition checks in grid masonry/subgrid layout — values fed back into track indexing as near-UINT_MAX.

isSubgrid() excludes excluded-from-normal-layout children. gridAreaForIndefiniteGridAxisItem() clamps the span before subtracting from gridAxisLines.

CSS Grid Level 3 introduces masonry layout (display: grid with grid-template-rows: subgrid or grid-lanes family). A fieldset <legend> is rendered specially by the fieldset and is excluded from the fieldset's grid-item set; with grid-template-rows: subgrid it still incorrectly answered true to isSubgrid(). gridAxisLines = m_gridAxisTracksCount + 1.

(a) Pre-fix isSubgrid() did not consider isExcludedFromNormalLayout(). The legend's layout asked the parent grid where it sits; the parent's m_gridItemArea did not contain the legend, tripping ASSERT(m_gridItemArea.contains(item)) in debug and producing an unsigned underflow in release.

(b) Pre-fix gridAreaForIndefiniteGridAxisItem() computed the auto-placement span from style without bounding it. With grid-row: span 10 against a single grid-axis track, itemSpanLength exceeded gridAxisLines; the later gridAxisLines - itemSpanLength underflowed the unsigned counter.

🔒

Examines whether the unsigned underflow stays a renderer crash or develops into something with attacker-controlled reach into per-track layout state.

Subscribe to read more

🔒

Four reusable audit patterns identified across the CSS Grid masonry, subgrid, and special-child rendering paths, each with concrete starting points.

Subscribe to read more