Skip to content

Miscompilation with clashing symbol fn names of different types #69390

Closed

Description

Related to #67946.

Currently, it's possible to perform a read to uninitialised memory by shadowing a function with an extern declaration with the same name. For example:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32
}

#[no_mangle]
fn bar(n: Point) {
    println!("{:?}", n);
}

fn main() {
    extern {
        fn bar();
    }
    unsafe {
        bar();
    }
}

(Playground)

Output:

Point { x: 1014863296, y: 1421860952 }

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.39s
     Running `target/debug/playground`

You can see we're able to happily print garbage this way. This is because on symbol name clash (but with different types), instead of erroring or otherwise doing work to produce distinct symbols, the function is bitcast instead. See #67946 (comment). In our example above, it means we produce a call to bar as if it takes no arguments, meaning we read garbage if we access the function arguments. You can also produce garbage return values, by shadowing a function which has no return value with a declaration that does have a return value.

This issue has been assigned to @jumbatm via this comment.

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

Metadata

Assignees

Labels

A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityT-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