Skip to content

Potential unsoundness in deinterleaving_load macro? #2036

Description

@okaneco

I was enabling Miri tests in my SIMD wrapper crate and ran into UB for the vld3 intrinsics.

The error below is for vld3q_f32 which returns a float32x4x3_t.

test aarch64::tests::test_vld3q_f32 ... error: Undefined Behavior: memory access failed: attempting to access 64 bytes, but got alloc751281 which is only 48 bytes from the end of the allocation

 -->\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\..\..\stdarch\crates\core_arch\src\macros.rs:250:20
|
250 |let w: W = ptr::read_unaligned($ptr as *const W);| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
::: \.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\..\..\stdarch\crates\core_arch\src\arm_shared\neon\generated.rs:22080:5
|
22080 | crate::core_arch::macros::deinterleaving_load!(f32, 4, 3, a)
| ------------------------------------------------------------ in this macro invocation
|

This comment on a std::simd private load function warns about the interaction of repr(simd) and read_unaligned.

/// This function is necessary since `repr(simd)` has padding for non-power-of-2 vectors (at the time of writing)./// With padding, `read_unaligned` will read past the end of an array of N elements.

core_arch's Simd is repr(simd) which pads to the nearest power-of-two from 48 to 64 bytes for Simd<f32, 12>.

#[repr(simd)]
#[derive(Copy)]
pub(crate)structSimd<T:SimdElement,constN:usize>([T;N]);

Thus, type W here of Simd<f32, 12> is actually 64 bytes which triggers UB in Miri when a pointer to [f32; 12] is passed.

($elem:ty, $lanes:literal,3, $ptr:expr) => {{
use $crate::core_arch::macros::deinterleave_mask;
use $crate::core_arch::simd::Simd;
use $crate::{mem::transmute, ptr};
typeV = Simd<$elem, $lanes>;
typeW = Simd<$elem,{ $lanes *3}>;
let w:W = ptr::read_unaligned($ptr as*constW);
let v0:V = simd_shuffle!(w, w, deinterleave_mask::<$lanes,3,0>());
let v1:V = simd_shuffle!(w, w, deinterleave_mask::<$lanes,3,1>());
let v2:V = simd_shuffle!(w, w, deinterleave_mask::<$lanes,3,2>());
transmute((v0, v1, v2))
}};

Activity

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

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