-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
non-c-like repr(u8) enum miscompilation? #50098
Comments
In this specific case, the expression |
Which nightly is servo on? i can't reproduce on playpen: https://play.rust-lang.org/?gist=c18f53f98345751eb4afe3ac59ffc73e&version=stable |
This occurred locally on my machine, which is using:
I was also unable to reproduce it in a small test case. There appears to be other factors that cause it. My guess is that it's related to how that enum is laid out when it is a field within a structure, but that's just a guess. |
Does such an enum require being nested in another enum to exhibit the problem? |
I'm actually unable to reproduce glenn's results; all tests appear to pass running |
Was able to reproduce a similar issue when doing C++ FFI with this feature. Now have a reproduction: |
https://play.rust-lang.org/?gist=5ac04c96bd654b01567d4eed362ddb6a&version=stable&mode=release // Should Print:
// local!! 1
// local!! 2
//
// Does Print:
// local!! 1
//
#![allow(dead_code)]
#[repr(C, u8)] enum Space { Local(f32), Screen }
#[repr(C)]
struct SpaceRepr {
tag: Tag,
padding: [u8; 3],
payload: Payloads,
}
#[repr(C)]
union Payloads {
local: f32,
}
#[repr(u8)]
enum Tag {
Local,
Screen,
}
fn handle_space(space: &Space) {
if let Space::Local(val) = *space {
println!("local!! {}", val);
}
}
fn main() {
// We should be allowed to store any garbage in padding, right?
let local1 = SpaceRepr { tag: Tag::Local, padding: [0, 0, 0], payload: Payloads { local: 1.0 }};
let local2 = SpaceRepr { tag: Tag::Local, padding: [1, 2, 3], payload: Payloads { local: 2.0 }};
let local1_ref: &Space = unsafe {::std::mem::transmute(&local1)};
let local2_ref: &Space = unsafe {::std::mem::transmute(&local2)};
handle_space(local1_ref);
handle_space(local2_ref);
} |
The issue is that the code for accessing the tag thinks the tag is a full u32, but any raw repr code thinks that the tag is only a byte. As such it tosses garbage in the padding, and the code freaks out. We were seeing this in pure rust because it was passing through my Magic Serde Code that uses raw reprs to deserialize enums in place. We can patch around this in WR by making the tag the "right" size, but this should clearly be fixed in rustc. |
cc @eddyb |
@gankro Ah, oops, |
Solution: make this be rust/src/librustc/ty/layout.rs Lines 950 to 951 in 4745092
|
rustc tries to expand enum tags to fill padding even if the requested size is smaller. This causes any code manipulating the enum's raw repr to produce buggy results, as it will write garbage into the padding, corrupting what rustc thinks is the tag. This is being fixed upstream, but for now just work around it by making the tags the same size rustc expects. See rust-lang/rust#50098
work around a rustc bug rustc tries to expand enum tags to fill padding even if the requested size is smaller. This causes any code manipulating the enum's raw repr to produce buggy results, as it will write garbage into the padding, corrupting what rustc thinks is the tag. This is being fixed upstream, but for now just work around it by making the tags the same size rustc expects. See rust-lang/rust#50098 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2708) <!-- Reviewable:end -->
Correct initial field alignment for repr(C)/repr(int) Fixes #50098 following #50098 (comment). (I wasn't sure which kind of test was best suited here — I picked run-pass simply because that was convenient, but if codegen is more appropriate, let me know and I'll change it.) r? @eddyb
Kinda vague since we just ran into it and it's late for me, but we're seeing a behaviour change marking
as
#[repr(u8)]
and otherwise not changing the program:servo/webrender#2673 (comment)
Making it
#[repr(C, u8)]
works correctly.All 3 layouts of the enum should be identical, so this is especially surprising that literally anything is changing. We're only seeing the issue in release builds. I can help reduce/bisect/debug this further tomorrow.
The text was updated successfully, but these errors were encountered: