Skip to content

Compiler segfaults when boxing a ZST from an external crate #28766

Closed
@kylewlacy

Description

@kylewlacy

Demonstration

I uploaded a repo with the simplest possible case I could come up with that demonstrates this issue here. Here's how it works:

$ rustc --version --verbose
    rustc 1.4.0-dev (d2e13e822 2015-09-15)
    binary: rustc
    commit-hash: d2e13e822a73e0ea46ae9e21afdd3155fc997f6d
    commit-date: 2015-09-15
    host: x86_64-apple-darwin
    release: 1.4.0-dev
$ git clone https://github.com/kylewlacy/rust-segfault.git
$ cd rust-segfault
$ cargo build --release --verbose
   Compiling my_crate v0.1.0 (file:///Users/kyle/Desktop/rust-segfault)
     Running `rustc my_crate/src/lib.rs --crate-name my_crate --crate-type lib -C opt-level=3 -C metadata=ab97f46dd8433ebe -C extra-filename=-ab97f46dd8433ebe --out-dir /Users/kyle/Desktop/rust-segfault/target/release/deps --emit=dep-info,link -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps`
   Compiling segfault v0.1.0 (file:///Users/kyle/Desktop/rust-segfault)
     Running `rustc src/lib.rs --crate-name segfault --crate-type lib -C opt-level=3 --out-dir /Users/kyle/Desktop/rust-segfault/target/release --emit=dep-info,link -L dependency=/Users/kyle/Desktop/rust-segfault/target/release -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps --extern my_crate=/Users/kyle/Desktop/rust-segfault/target/release/deps/libmy_crate-ab97f46dd8433ebe.rlib`
Could not compile `segfault`.

Caused by:
  Process didn't exit successfully: `rustc src/lib.rs --crate-name segfault --crate-type lib -C opt-level=3 --out-dir /Users/kyle/Desktop/rust-segfault/target/release --emit=dep-info,link -L dependency=/Users/kyle/Desktop/rust-segfault/target/release -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps --extern my_crate=/Users/kyle/Desktop/rust-segfault/target/release/deps/libmy_crate-ab97f46dd8433ebe.rlib` (signal: 11)

Explanation

So I have a crate in my project, brilliantly named my_crate. my_crate is pretty simple, it contains a struct, called Foo, made up of zero-sized types. Foo also has a constructor function called Foo::new():

// my_crate/lib.rs
pub struct Foo(());

impl Foo {
    fn new() -> Self {
        Foo(())
    }
}

Now, in my library, segfault, I have a single function, called box_foo(), that just returns a Box<Foo>. It constructs a Foo, then boxes it:

// segfault/lib.rs
extern crate my_crate;
use my_crate::Foo;

pub fn box_foo() -> Box<Foo> {
    Box::new(Foo::new())
}

Well, that's about it. Building segfault and my_crate with cargo build works perfectly fine. However, cargo build --release crashes with a signal 11, a segfault.

Some observations

  • Foo must be a zero-sized type, but cannot be a unit struct
  • Foo must be constructed with a function (e.g Box::new(Foo(()) would not segfault)
  • Foo must be from another crate
  • The segfault only occurs if box_foo() is public (otherwise it's dead code, and I guess rustc doesn't even attempt to compile it?)
  • The segfault only occurs when optimizing the outer library
  • The optimization level doesn't matter, it just has to be >0
  • The constructor fn doesn't have to be in impl Foo, but it does have to come from my_crate
  • The fn that creates the box has to be in the outer library (e.g. let boxed: Box<Foo> = Foo::new_box(); would not segfault)
  • Using a newtype in place of Foo has the same issue
  • The crash is not caused by returning a Box<Foo>, but by constructing one with Box::new. That is, the following also causes a segfault:
pub fn foo_ptr_mut() -> *mut Foo {
    let boxed = Box::new(Foo::new());
    Box::into_raw(boxed)
}

Metadata

Metadata

Assignees

Labels

I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions