Skip to content

C func returning Option<extern fn> is not immediate on 32-bit linux #11040

@lilyball

Description

@lilyball

Calls to a C function declared as returning Option<extern fn> are correctly immediate on 64-bit darwin, but are not immediate on 32-bit linux. I'm assuming the bit width is the issue here, not the platform.

Given that functions are non-nullable, and the only way to declare a nullable function is with Option<extern fn>, this seems like a rather serious problem. The only way to declare a C function returning a nullable function in the presence of this bug is to declare it as returning an arbitrary raw pointer and wrap it in another function that casts it.

Incidentally, this is not an issue with the null-pointer optimization. size_of() reports that both extern fn and Option<extern fn> are 4 on 32-bit linux, as expected.

Example

Source

foo_c.c:

#include <stdio.h>

typedef void (*voidfunc)(void);

voidfunc foo(int x) {
    printf("foo: x=%d\n", x);
    return NULL;
}

foo_rust.rs:

use std::libc;

extern {
    pub fn foo(x: libc::c_int) -> Option<extern "C" fn()>;
}

fn main() {
    unsafe { println!("{:?}", foo(3)); }
}

Makefile:

foo: foo_c.o foo_rust.rs
    rustc -o foo --link-args foo_c.o foo_rust.rs

Results

64-bit Darwin:

> ./foo
foo: x=3
None

32-bit Linux:

> ./foo
foo: x=-1220505408
None
Segmentation fault (core dumped)

FWIW, the version of rustc on both platforms is slightly different. The 32-bit Linux platform is using Hans Jørgen Hoel's rust-nightly package, which is almost a day old at 000cda6. 64-bit Darwin is using a newer version of master, at bf30a21. However, I don't see any changes in the newer version that look obviously related.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions