Skip to content

Commit d5b49f1

Browse files
committed
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
1 parent 071ce6f commit d5b49f1

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

components/style/values/computed/length_percentage.rs

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ use style_traits::{CssWriter, ToCss};
4242
#[derive(Clone, Copy)]
4343
#[repr(C)]
4444
pub struct LengthVariant {
45-
tag: u32,
45+
tag: u8,
4646
length: Length,
4747
}
4848

4949
#[doc(hidden)]
5050
#[derive(Clone, Copy)]
5151
#[repr(C)]
5252
pub struct PercentageVariant {
53-
tag: u32,
53+
tag: u8,
5454
percentage: Percentage,
5555
}
5656

@@ -61,7 +61,7 @@ pub struct PercentageVariant {
6161
#[repr(C)]
6262
#[cfg(target_pointer_width = "32")]
6363
pub struct CalcVariant {
64-
tag: u32,
64+
tag: u8,
6565
ptr: *mut CalcLengthPercentage,
6666
}
6767

@@ -70,7 +70,7 @@ pub struct CalcVariant {
7070
#[repr(C)]
7171
#[cfg(target_pointer_width = "64")]
7272
pub struct CalcVariant {
73-
ptr: *mut CalcLengthPercentage,
73+
ptr: usize, // In little-endian byte order
7474
}
7575

7676
// `CalcLengthPercentage` is `Send + Sync` as asserted below.
@@ -81,7 +81,7 @@ unsafe impl Sync for CalcVariant {}
8181
#[derive(Clone, Copy)]
8282
#[repr(C)]
8383
pub struct TagVariant {
84-
tag: u32,
84+
tag: u8,
8585
}
8686

8787
/// A `<length-percentage>` value. This can be either a `<length>`, a
@@ -114,17 +114,17 @@ pub union LengthPercentageUnion {
114114

115115
impl LengthPercentageUnion {
116116
#[doc(hidden)] // Need to be public so that cbindgen generates it.
117-
pub const TAG_CALC: u32 = 0;
117+
pub const TAG_CALC: u8 = 0;
118118
#[doc(hidden)]
119-
pub const TAG_LENGTH: u32 = 1;
119+
pub const TAG_LENGTH: u8 = 1;
120120
#[doc(hidden)]
121-
pub const TAG_PERCENTAGE: u32 = 2;
121+
pub const TAG_PERCENTAGE: u8 = 2;
122122
#[doc(hidden)]
123-
pub const TAG_MASK: u32 = 0b11;
123+
pub const TAG_MASK: u8 = 0b11;
124124
}
125125

126126
#[derive(Clone, Copy, Debug, PartialEq)]
127-
#[repr(u32)]
127+
#[repr(u8)]
128128
enum Tag {
129129
Calc = LengthPercentageUnion::TAG_CALC,
130130
Length = LengthPercentageUnion::TAG_LENGTH,
@@ -147,7 +147,7 @@ unsafe fn static_assert() {
147147
impl Drop for LengthPercentage {
148148
fn drop(&mut self) {
149149
if self.tag() == Tag::Calc {
150-
let _ = unsafe { Box::from_raw(self.0.calc.ptr) };
150+
let _ = unsafe { Box::from_raw(self.calc_ptr()) };
151151
}
152152
}
153153
}
@@ -236,13 +236,22 @@ impl LengthPercentage {
236236
/// checking.
237237
fn new_calc_unchecked(calc: Box<CalcLengthPercentage>) -> Self {
238238
let ptr = Box::into_raw(calc);
239-
let calc = Self(LengthPercentageUnion {
240-
calc: CalcVariant {
241-
#[cfg(target_pointer_width = "32")]
242-
tag: LengthPercentageUnion::TAG_CALC,
243-
ptr,
244-
},
245-
});
239+
240+
#[cfg(target_pointer_width = "32")]
241+
let calc = CalcVariant {
242+
tag: LengthPercentageUnion::TAG_CALC,
243+
ptr,
244+
};
245+
246+
#[cfg(target_pointer_width = "64")]
247+
let calc = CalcVariant {
248+
#[cfg(target_endian = "little")]
249+
ptr: ptr as usize,
250+
#[cfg(target_endian = "big")]
251+
ptr: (ptr as usize).swap_bytes(),
252+
};
253+
254+
let calc = Self(LengthPercentageUnion { calc });
246255
debug_assert_eq!(calc.tag(), Tag::Calc);
247256
calc
248257
}
@@ -261,13 +270,25 @@ impl LengthPercentage {
261270
fn unpack<'a>(&'a self) -> Unpacked<'a> {
262271
unsafe {
263272
match self.tag() {
264-
Tag::Calc => Unpacked::Calc(&*self.0.calc.ptr),
273+
Tag::Calc => Unpacked::Calc(&*self.calc_ptr()),
265274
Tag::Length => Unpacked::Length(self.0.length.length),
266275
Tag::Percentage => Unpacked::Percentage(self.0.percentage.percentage),
267276
}
268277
}
269278
}
270279

280+
#[inline]
281+
unsafe fn calc_ptr(&self) -> *mut CalcLengthPercentage {
282+
#[cfg(not(all(target_endian = "big", target_pointer_width = "64")))]
283+
{
284+
self.0.calc.ptr as *mut _
285+
}
286+
#[cfg(all(target_endian = "big", target_pointer_width = "64"))]
287+
{
288+
self.0.calc.ptr.swap_bytes() as *mut _
289+
}
290+
}
291+
271292
#[inline]
272293
fn to_serializable(&self) -> Serializable {
273294
match self.unpack() {

0 commit comments

Comments
 (0)