servo: Merge #15469 - layout: Fix integer overflow when computing size of replace elements (from stshine:no-integer-overflow); r=emilio
authorPu Xingyu <pu.stshine@gmail.com>
Thu, 09 Feb 2017 06:21:29 -0800
changeset 481560 ed926f0ed4513a39157047c42fbf1d6533cfc5f3
parent 481559 f0f7d425527e142eb16240a3dc0e1900471a636b
child 481561 020e1536fd678ef5a7eee25b3fada9211c86efc8
push id44840
push userbmo:rchien@mozilla.com
push dateFri, 10 Feb 2017 01:03:57 +0000
reviewersemilio
milestone54.0a1
servo: Merge #15469 - layout: Fix integer overflow when computing size of replace elements (from stshine:no-integer-overflow); r=emilio <!-- Please describe your changes on the following line: --> When calculating size of replaced element that has intrinsic aspect ratio, we need to multiply the ratio if one of the dimensions has definite size. And we can not precompute the ratio and store it as a float, because doing so may result one pixel difference in calculation for certain images, thus make some tests fail. So it may overflow when the dimension lengths are large, and this pull request convert them to `i64` before multiplication. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #15249 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 384391da680de3f73557dc721774326bbbf8ade7
servo/components/layout/fragment.rs
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -1046,44 +1046,47 @@ impl Fragment {
             // dimensions, the missing dimension is taken from the object’s intrinsic
             // dimensions. Otherwise it is taken from the default object size.
             (MaybeAuto::Specified(inline_size), MaybeAuto::Auto) => {
                 let inline_size = inline_constraint.clamp(inline_size);
                 let block_size = if self.has_intrinsic_ratio() {
                     // Note: We can not precompute the ratio and store it as a float, because
                     // doing so may result one pixel difference in calculation for certain
                     // images, thus make some tests fail.
-                    inline_size * intrinsic_block_size.0 / intrinsic_inline_size.0
+                    Au((inline_size.0 as i64 * intrinsic_block_size.0 as i64 /
+                        intrinsic_inline_size.0 as i64) as i32)
                 } else {
                     intrinsic_block_size
                 };
                 (inline_size, block_constraint.clamp(block_size))
             }
             (MaybeAuto::Auto, MaybeAuto::Specified(block_size)) => {
                 let block_size = block_constraint.clamp(block_size);
                 let inline_size = if self.has_intrinsic_ratio() {
-                    block_size * intrinsic_inline_size.0 / intrinsic_block_size.0
+                    Au((block_size.0 as i64 * intrinsic_inline_size.0 as i64 /
+                       intrinsic_block_size.0 as i64) as i32)
                 } else {
                     intrinsic_inline_size
                 };
                 (inline_constraint.clamp(inline_size), block_size)
             }
             // https://drafts.csswg.org/css2/visudet.html#min-max-widths
             (MaybeAuto::Auto, MaybeAuto::Auto) => {
                 if self.has_intrinsic_ratio() {
                     // This approch follows the spirit of cover and contain constraint.
                     // https://drafts.csswg.org/css-images-3/#cover-contain
 
                     // First, create two rectangles that keep aspect ratio while may be clamped
                     // by the contraints;
                     let first_isize = inline_constraint.clamp(intrinsic_inline_size);
-                    let first_bsize = first_isize * intrinsic_block_size.0 / intrinsic_inline_size.0;
+                    let first_bsize = Au((first_isize.0 as i64 * intrinsic_block_size.0 as i64 /
+                                          intrinsic_inline_size.0 as i64) as i32);
                     let second_bsize = block_constraint.clamp(intrinsic_block_size);
-                    let second_isize = second_bsize * intrinsic_inline_size.0 / intrinsic_block_size.0;
-
+                    let second_isize = Au((second_bsize.0 as i64 * intrinsic_inline_size.0 as i64 /
+                                           intrinsic_block_size.0 as i64) as i32);
                     let (inline_size, block_size) = match (first_isize.cmp(&intrinsic_inline_size) ,
                                                            second_isize.cmp(&intrinsic_inline_size)) {
                         (Ordering::Equal, Ordering::Equal) =>
                             (first_isize, first_bsize),
                         // When only one rectangle is clamped, use it;
                         (Ordering::Equal, _) =>
                             (second_isize, second_bsize),
                         (_, Ordering::Equal) =>