Is using array pointers with FFI UB?

#1

Hi,
I want to know if it is UB to pass a C function that receives uint8_t arr[20]
an array pointer(*mut [u8; 20]) instead of a regular pointer(*mut u8)?
are pointers and length equivalent to arrays? or is this UB?

#2

*mut [T; N] and *mut T have the same runtime representation (an address), the *.. [_; N] part is just a compile-time / type-level property that is anyways lost when doing FFI.

If you want the length of the array to be available at runtime, you need slices: [T], for instance, *mut [u8], which is not equivalent to *mut u8.

  • You can go from a slice to a ptr (pointing to the first element) with the .as_mut_ptr() method (losing the length information),

  • and the other way around with the
    ::core::slice::from_raw_parts_mut(ptr: *mut T, len: usize)
    function.

But since the layout of a fat pointer (address, length tuple) may not be FFI-safe, the best thing you can do is to explicitely pass around a *mut u8 with a size_t.

#3

Thanks, I mostly want that the rust bindings will represent the C code, and if the C code accepts a arr[20] the rust bindings should show that, and I think the best way is with a [T; 20]

1 Like
#4

One thing you need to be careful of is the lifetime of the array — if you pass address of a local variable, C must not be allowed to keep the pointer.

1 Like