Rust: Static ends up in rodata despite PhantomData<UnsafeCell> field

Created on 17 Jan 2017  路  4Comments  路  Source: rust-lang/rust

Normally, a static is not placed in .rodata if it contains an UnsafeCell. However, this doesn't work for PhantomData<UnsafeCell> fields:

struct Test(i32, PhantomData<UnsafeCell<i32>>);
static TEST: Test = Test(0, PhantomData);

The TEST static is placed in .rodata, which is surprising to me.

Example where this misconception leads to undefined behavior: https://is.gd/M3ozkx

A-typesystem I-nominated I-unsound 馃挜 T-lang

Most helpful comment

TEST.0 is shared data that's not in an UnsafeCell. AFAIK mutating such data causes undefined behavior.

It's good that PhantomData placed the static in .rodata -- this makes the UB easy to detect.

All 4 comments

cc @oli-obk

TEST.0 is shared data that's not in an UnsafeCell. AFAIK mutating such data causes undefined behavior.

It's good that PhantomData placed the static in .rodata -- this makes the UB easy to detect.

Nominating due to my desire for all soundness bugs to have assigned priority tags.

I don't consider this a soundness bug. In fact, I think that the existing behavior is probably correct, although it is to some extent an unsafe code guidelines issue (but this is not an area where there has ever been disagreement, to my knowledge). I believe that mutating field .0 would be illegal even if we treated the PhantomData<UnsafeCell<T>> as preventing the field from going into rodata -- in other words, the compiler might be validly able to assume that the .0 field is not changed (along with any other fields not actually contained within an UnsafeCell).

The right way to encode this is struct Foo(UnsafeCell<i32>).

Closing therefore, feel free to follow-up! :)

Was this page helpful?
0 / 5 - 0 ratings