Skip to content

CFI breaks when dropping trait object #118761

@maurer

Description

@maurer

I tried this code:

use std::sync::Arc;
use std::borrow::Borrow;

trait Fooable {
    fn foo(&self) -> i32;
}

struct Bar;

impl Fooable for Bar {
    fn foo(&self) -> i32 {
        3
    }
}

fn do_foo(x: Arc<dyn Fooable>) -> i32 {
    x.foo()
}

fn ref_foo(x: &dyn Fooable) -> i32 {
    x.foo()
}

fn main() {
    let arc: Arc<dyn Fooable> = Arc::new(Bar);
    println!("base: {}",Bar.foo());
    println!("ref: {}", ref_foo(&Bar));
    println!("xlat: {}", ref_foo(arc.borrow()));
    // This one will crash on illegal instruction
    println!("{}", do_foo(arc))
}

built with rustc -Z sanitizer=cfi -Clto -Ccodegen-units=1 cfi_tester.rs

I expected to see this happen: All print statements should run, the program should exit cleanly

Instead, this happened:

mmaurer@anyblade:~$ rustc -Z sanitizer=cfi -Clto -Ccodegen-units=1 cfi_tester.rs
mmaurer@anyblade:~$ ./cfi_tester 
base: 3
ref: 3
xlat: 3
Illegal instruction
mmaurer@anyblade:~$ echo $?
132
mmaurer@anyblade:~$ 

Meta

rustc --version --verbose:

rustc 1.76.0-nightly (9fad68599 2023-12-03)

I don't believe this has ever worked, and it is at least broken back to 1.73.0 if it did.

cc @rcvalle

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-sanitizersArea: Sanitizers for correctness and code qualityC-bugCategory: This is a bug.PG-exploit-mitigationsProject group: Exploit mitigationsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions