[18] [WebCore] Bound grid masonry span and exclude excluded-from-normal-layout from subgrid
Severity: Medium | Component: WebCore rendering (Grid masonry/subgrid) | ca8c809
두 가지 연관된 결함이 함께 수정되어 Medium으로 평가되었습니다. RenderGrid::isSubgrid()는 이제 isExcludedFromNormalLayout()을 확인합니다. 이를 통해 fieldset <legend>가 자신을 배치하지 않은 부모 grid에게 subgrid라고 응답하던 문제가 제거되었습니다. gridAreaForIndefiniteGridAxisItem()은 auto-placement span을 m_gridAxisTracksCount로 clamp합니다. 두 경우 모두 release 빌드에서 unsigned underflow가 발생하며, 그 결과 near-UINT_MAX 값이 layout 인덱싱에 유입됩니다. JS에서 관찰 가능한 read/write primitive는 존재하지 않습니다.
RenderGrid::isSubgrid()는 일반 레이아웃에서 제외된 자식 요소에 대해 false를 반환합니다. gridAreaForIndefiniteGridAxisItem()는 gridAxisLines - itemSpanLength를 계산하기 전에 std::min(itemSpanLength, m_gridAxisTracksCount)로 span 크기를 clamp합니다.
Source/WebCore/rendering/RenderGrid.cpp
Grid masonry/subgrid layout에서 전제 조건 검사 누락으로 인한 unsigned underflow — near-UINT_MAX 값의 track 인덱싱 유입.
Patch Details
isSubgrid()는 일반 레이아웃에서 제외된 자식 요소를 subgrid 판정 대상에서 제거합니다. gridAreaForIndefiniteGridAxisItem()는 gridAxisLines에서 차감하기 전에 span을 clamp합니다.
Background
CSS Grid Level 3는 masonry layout을 도입합니다(display: grid와 함께 grid-template-rows: subgrid 또는 grid-lanes 계열을 사용). fieldset의 <legend>는 fieldset이 특별하게 렌더링하는 요소로, fieldset의 grid-item 집합에서 제외됩니다. 그러나 grid-template-rows: subgrid가 적용된 경우에도 isSubgrid()에 true를 반환하는 문제가 있었습니다. 참고로 gridAxisLines = m_gridAxisTracksCount + 1입니다.
Analysis
(a) 패치 이전 isSubgrid()는 isExcludedFromNormalLayout()을 고려하지 않았습니다. legend가 layout을 요청하면 부모 grid에 자신의 위치를 묻는 흐름이 발생합니다. 그런데 부모의 m_gridItemArea에 legend가 포함되어 있지 않습니다. 이 때문에 debug 빌드에서는 ASSERT(m_gridItemArea.contains(item))가 발동되고, release 빌드에서는 unsigned underflow가 발생했습니다.
(b) 패치 이전 gridAreaForIndefiniteGridAxisItem()는 style에서 auto-placement span을 계산할 때 상한을 두지 않았습니다. grid-row: span 10이 단일 grid-axis track에 적용되면 itemSpanLength가 gridAxisLines를 초과합니다. 이후 gridAxisLines - itemSpanLength 연산에서 unsigned counter의 underflow가 발생했습니다.