Skip to content

repr(simd) is unsound in C FFI #53346

Closed
Closed
@gnzlbg

Description

@gnzlbg

This supersedes #44367 - after #47743 the unsoundness has been restricted to C FFI. The Rust ABI for vector types currently passes all types by memory.

There are sadly many C libraries that use vector types in their ABIs, some of which are pretty much "fundamental" like some of the short-vector math libraries: libmvec, SVML, etc.

As a summary of the previous issue, currently, the behavior of calling bar, `the following snippet of Rust code is sometimes undefined:

#![feature(repr_simd, simd_ffi)]

#[repr(simd)]
struct F32x8(f32, f32, f32, f32, f32, f32, f32, f32);
impl F32x8 { fn splat(x: f32) -> Self { F32x8(x, x, x, x, x, x, x, x) } }

#[allow(improper_ctypes)]
extern "C" {
    fn foo(x: F32x8) -> F32x8;
}

fn main() {
    unsafe { 
        foo(F32x8::splat(0.));  // UB ?
    }
}

When both the Rust program and the C library exposing foo are compiled with the same set of target-features such that their ABIs match, then the program above will work as expected.

When the C library is compiled with say AVX2, but the Rust program is compiled with SSE4.2, then Rust will try to pass the F32x8 in two 128-bit wide vector registers to C, while the C code only expects a single 256-bit wide vector. A similar problem occurs in the opposite case.

cc @rkruppe @parched @alexcrichton @eddyb - did I correctly represent the problem ?


A potential solution discussed in #44367 would be to completely forbid vector types in FFI functions that do not specify their vector ABI:

extern "C" {
    extern "vector-256" fn foo(x: F32x8) -> F32x8;
    extern "vector-128" fn bar(x: F32x8) -> F32x8;
    // fn baz(x: F32x8) -> F32x8; // ERROR: repr(simd) in C-FFI with unspecified vector ABI
}

let x = F32x8::splat(0.);
foo(x); // x is passed in a single 256-bit wide register
bar(x); // x is passed in two 128-bit wide registers

If the C library linked does not expose the specified ABIs for foo and bar, the program would fail to link, preventing undefined behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-SIMDArea: SIMD (Single Instruction Multiple Data)A-reprArea: the `#[repr(stuff)]` attributeC-bugCategory: This is a bug.F-simd_ffi`#![feature(simd_ffi)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions