mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Avoid crash with large table column widths (#33424)
Fixes #33423 Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
b048bf80a4
commit
52e495c1a6
2 changed files with 15 additions and 14 deletions
|
@ -882,33 +882,36 @@ impl<'a> TableLayout<'a> {
|
||||||
(self.assignable_width - sum_b).to_f32_px() / (sum_a - sum_b).to_f32_px();
|
(self.assignable_width - sum_b).to_f32_px() / (sum_a - sum_b).to_f32_px();
|
||||||
let weight_b = 1.0 - weight_a;
|
let weight_b = 1.0 - weight_a;
|
||||||
|
|
||||||
let mut sum_accounting_for_floating_point_inaccuracy = Au::new(0);
|
let mut remaining_assignable_width = self.assignable_width;
|
||||||
let mut widths: Vec<Au> = a
|
let mut widths: Vec<Au> = a
|
||||||
.iter()
|
.iter()
|
||||||
.zip(b.iter())
|
.zip(b.iter())
|
||||||
.map(|(guess_a, guess_b)| {
|
.map(|(guess_a, guess_b)| {
|
||||||
(guess_a.scale_by(weight_a)) + (guess_b.scale_by(weight_b))
|
let column_width = guess_a.scale_by(weight_a) + guess_b.scale_by(weight_b);
|
||||||
})
|
// Clamp to avoid exceeding the assignable width. This could otherwise
|
||||||
.inspect(|&column_width| {
|
// happen when dealing with huge values whose sum is clamped to MAX_AU.
|
||||||
sum_accounting_for_floating_point_inaccuracy += column_width;
|
let column_width = column_width.min(remaining_assignable_width);
|
||||||
|
remaining_assignable_width -= column_width;
|
||||||
|
column_width
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if sum_accounting_for_floating_point_inaccuracy != self.assignable_width {
|
if !remaining_assignable_width.is_zero() {
|
||||||
// The computations above can introduce floating-point imprecisions.
|
// The computations above can introduce floating-point imprecisions.
|
||||||
// Since these errors are very small (+-1Au), it's fine to simply adjust
|
// Since these errors are very small (1Au), it's fine to simply adjust
|
||||||
// the first column such that the total width matches the assignable width
|
// the first column such that the total width matches the assignable width
|
||||||
let difference =
|
|
||||||
self.assignable_width - sum_accounting_for_floating_point_inaccuracy;
|
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
difference.abs() <= Au::new(widths.len() as i32),
|
remaining_assignable_width >= Au::zero(),
|
||||||
|
"Sum of columns shouldn't exceed the assignable table width"
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
remaining_assignable_width <= Au::new(widths.len() as i32),
|
||||||
"A deviation of more than one Au per column is unlikely to be caused by float imprecision"
|
"A deviation of more than one Au per column is unlikely to be caused by float imprecision"
|
||||||
);
|
);
|
||||||
|
|
||||||
// We checked if the table was empty at the top of the function, so there
|
// We checked if the table was empty at the top of the function, so there
|
||||||
// always is a first column
|
// always is a first column
|
||||||
widths[0] += difference;
|
widths[0] += remaining_assignable_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(widths.iter().sum::<Au>() == self.assignable_width);
|
debug_assert!(widths.iter().sum::<Au>() == self.assignable_width);
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[large-col-widths.html]
|
|
||||||
expected: CRASH
|
|
Loading…
Add table
Add a link
Reference in a new issue