Prevent overflow in intersection observer area evaluation (#36955)

Prevent overflowing by not calculating the area and reordering
arithmetic operations.

Testing: No regression in wpt tests:
https://github.com/webbeef/servo/actions/runs/14951055450
Fixes: https://github.com/servo/servo/issues/36940

Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
webbeef 2025-05-10 20:05:47 -07:00 committed by GitHub
parent 6cd44061d7
commit 9c3069366e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -524,11 +524,10 @@ impl IntersectionObserver {
// Step 9 // Step 9
// > Let targetArea be targetRects area. // > Let targetArea be targetRects area.
let target_area = target_rect.size.width.0 * target_rect.size.height.0;
// Step 10 // Step 10
// > Let intersectionArea be intersectionRects area. // > Let intersectionArea be intersectionRects area.
let intersection_area = intersection_rect.size.width.0 * intersection_rect.size.height.0; // These steps are folded in Step 12, rewriting (w1 * h1) / (w2 * h2) as (w1 / w2) * (h1 / h2)
// to avoid multiplication overflows.
// Step 11 // Step 11
// > Let isIntersecting be true if targetRect and rootBounds intersect or are edge-adjacent, // > Let isIntersecting be true if targetRect and rootBounds intersect or are edge-adjacent,
@ -545,9 +544,12 @@ impl IntersectionObserver {
// Step 12 // Step 12
// > If targetArea is non-zero, let intersectionRatio be intersectionArea divided by targetArea. // > If targetArea is non-zero, let intersectionRatio be intersectionArea divided by targetArea.
// > Otherwise, let intersectionRatio be 1 if isIntersecting is true, or 0 if isIntersecting is false. // > Otherwise, let intersectionRatio be 1 if isIntersecting is true, or 0 if isIntersecting is false.
let intersection_ratio = match target_area { let intersection_ratio = if target_rect.size.width.0 == 0 || target_rect.size.height.0 == 0
0 => is_intersecting.into(), {
_ => (intersection_area as f64) / (target_area as f64), is_intersecting.into()
} else {
(intersection_rect.size.width.0 as f64 / target_rect.size.width.0 as f64) *
(intersection_rect.size.height.0 as f64 / target_rect.size.height.0 as f64)
}; };
// Step 13 // Step 13