From d5b49f14da9da7982bf1568f215cbca64df2613d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 1 Feb 2020 00:32:51 +0100 Subject: [PATCH] style: Fix LengthPercentage on big-endian machines. Always store the pointer in little-endian order so that the tag trick works. Differential Revision: https://phabricator.services.mozilla.com/D61386 --- .../values/computed/length_percentage.rs | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/components/style/values/computed/length_percentage.rs b/components/style/values/computed/length_percentage.rs index 14b894e1da40..96bf76c98d48 100644 --- a/components/style/values/computed/length_percentage.rs +++ b/components/style/values/computed/length_percentage.rs @@ -42,7 +42,7 @@ use style_traits::{CssWriter, ToCss}; #[derive(Clone, Copy)] #[repr(C)] pub struct LengthVariant { - tag: u32, + tag: u8, length: Length, } @@ -50,7 +50,7 @@ pub struct LengthVariant { #[derive(Clone, Copy)] #[repr(C)] pub struct PercentageVariant { - tag: u32, + tag: u8, percentage: Percentage, } @@ -61,7 +61,7 @@ pub struct PercentageVariant { #[repr(C)] #[cfg(target_pointer_width = "32")] pub struct CalcVariant { - tag: u32, + tag: u8, ptr: *mut CalcLengthPercentage, } @@ -70,7 +70,7 @@ pub struct CalcVariant { #[repr(C)] #[cfg(target_pointer_width = "64")] pub struct CalcVariant { - ptr: *mut CalcLengthPercentage, + ptr: usize, // In little-endian byte order } // `CalcLengthPercentage` is `Send + Sync` as asserted below. @@ -81,7 +81,7 @@ unsafe impl Sync for CalcVariant {} #[derive(Clone, Copy)] #[repr(C)] pub struct TagVariant { - tag: u32, + tag: u8, } /// A `` value. This can be either a ``, a @@ -114,17 +114,17 @@ pub union LengthPercentageUnion { impl LengthPercentageUnion { #[doc(hidden)] // Need to be public so that cbindgen generates it. - pub const TAG_CALC: u32 = 0; + pub const TAG_CALC: u8 = 0; #[doc(hidden)] - pub const TAG_LENGTH: u32 = 1; + pub const TAG_LENGTH: u8 = 1; #[doc(hidden)] - pub const TAG_PERCENTAGE: u32 = 2; + pub const TAG_PERCENTAGE: u8 = 2; #[doc(hidden)] - pub const TAG_MASK: u32 = 0b11; + pub const TAG_MASK: u8 = 0b11; } #[derive(Clone, Copy, Debug, PartialEq)] -#[repr(u32)] +#[repr(u8)] enum Tag { Calc = LengthPercentageUnion::TAG_CALC, Length = LengthPercentageUnion::TAG_LENGTH, @@ -147,7 +147,7 @@ unsafe fn static_assert() { impl Drop for LengthPercentage { fn drop(&mut self) { if self.tag() == Tag::Calc { - let _ = unsafe { Box::from_raw(self.0.calc.ptr) }; + let _ = unsafe { Box::from_raw(self.calc_ptr()) }; } } } @@ -236,13 +236,22 @@ impl LengthPercentage { /// checking. fn new_calc_unchecked(calc: Box) -> Self { let ptr = Box::into_raw(calc); - let calc = Self(LengthPercentageUnion { - calc: CalcVariant { - #[cfg(target_pointer_width = "32")] - tag: LengthPercentageUnion::TAG_CALC, - ptr, - }, - }); + + #[cfg(target_pointer_width = "32")] + let calc = CalcVariant { + tag: LengthPercentageUnion::TAG_CALC, + ptr, + }; + + #[cfg(target_pointer_width = "64")] + let calc = CalcVariant { + #[cfg(target_endian = "little")] + ptr: ptr as usize, + #[cfg(target_endian = "big")] + ptr: (ptr as usize).swap_bytes(), + }; + + let calc = Self(LengthPercentageUnion { calc }); debug_assert_eq!(calc.tag(), Tag::Calc); calc } @@ -261,13 +270,25 @@ impl LengthPercentage { fn unpack<'a>(&'a self) -> Unpacked<'a> { unsafe { match self.tag() { - Tag::Calc => Unpacked::Calc(&*self.0.calc.ptr), + Tag::Calc => Unpacked::Calc(&*self.calc_ptr()), Tag::Length => Unpacked::Length(self.0.length.length), Tag::Percentage => Unpacked::Percentage(self.0.percentage.percentage), } } } + #[inline] + unsafe fn calc_ptr(&self) -> *mut CalcLengthPercentage { + #[cfg(not(all(target_endian = "big", target_pointer_width = "64")))] + { + self.0.calc.ptr as *mut _ + } + #[cfg(all(target_endian = "big", target_pointer_width = "64"))] + { + self.0.calc.ptr.swap_bytes() as *mut _ + } + } + #[inline] fn to_serializable(&self) -> Serializable { match self.unpack() {