Skip to content

Invalid CFI failure for and indirect call through a Box<dyn Fn()> #144641

Description

@1c3t3a

I tried this code and compiled it with CFI enabled (-Clinker-plugin-lto -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi):

fn foo(a: u32) {}

struct Foo {
    a: Option<Box<dyn Fn(u32) + Sync + Send>>,
}

impl Foo {
    fn doit(&mut self) {
        let function = {
            if self.a.is_none() {
                self.a = Some(Box::new(foo));
            }
            Box::new(self.a.as_deref().unwrap())
        };
        function(0_u32);
    }
}

fn main() {
    let mut foo = Foo { a: None };
    foo.doit();
}

I expected to see this happen: the program executes successfully

Instead, this happened: I see a CFI failure.

Meta

rustc --version --verbose:

rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: x86_64-unknown-linux-gnu
release: 1.87.0
LLVM version: 20.1.1

This was initially found when compiling the png crate's example code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-control-flow-integrityArea: Control Flow Integrity (CFI) security mitigationA-sanitizersArea: Sanitizers for correctness and code qualityC-bugCategory: This is a bug.PG-exploit-mitigationsProject group: Exploit mitigations

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions