Skip to content

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

Closed

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

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 29, 2025
  2. 1c3t3a commented on Jul 29, 2025

    @1c3t3a
    MemberAuthor

    @rustbot label -needs-triage, +A-control-flow-integrity, +A-sanitizers, +PG-exploit-mitigations

  3. added
    A-control-flow-integrityArea: Control Flow Integrity (CFI) security mitigation
    A-sanitizersArea: Sanitizers for correctness and code quality
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 29, 2025
  4. rcvalle commented on Jul 29, 2025

    @rcvalle
    Member

    @rustbot claim

  5. added a commit that references this issue on Aug 5, 2025
    8b21653
  6. rcvalle commented on Aug 5, 2025

    @rcvalle
    Member

    There is currently no explicit handling in transform_instance for types that implement Fn, FnMut, or FnOnce (such as Box<dyn Fn()>, Box<dyn FnMut()>, etc.) when they are used as the receiver of a call to their respective call, call_mut, or call_once methods. The only special handling in the code is for closures, coroutines, and coroutine closures, but not for arbitrary types that implement these traits. I submited a PR to fix this at #144936.

  7. added a commit that references this issue on Aug 5, 2025
    bb63853
  8. added a commit that references this issue on Aug 6, 2025
    b08297c
  9. added a commit that references this issue on Aug 6, 2025
    d91fe48
  10. added a commit that references this issue on Oct 15, 2025
    2ddb8aa
  11. added a commit that references this issue on Oct 16, 2025
    8cce703
  12. added a commit that references this issue on Oct 17, 2025
    8f6b94f
  13. added 3 commits that reference this issue on Oct 28, 2025
    7a26eff
    1eaa22e
    68618a8
  14. added a commit that references this issue on Oct 28, 2025
    06a1aa4
  15. added a commit that references this issue on Nov 3, 2025
    c920c5f
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