From 58b472aa6c2901b3889fbe570c974f26e41c71bc Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Tue, 19 May 2026 13:54:02 +0100 Subject: [PATCH 1/2] Add slice op soundness tests --- fearless_simd_tests/Cargo.toml | 2 + fearless_simd_tests/tests/mod.rs | 1 + fearless_simd_tests/tests/soundness.rs | 85 ++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 fearless_simd_tests/tests/soundness.rs diff --git a/fearless_simd_tests/Cargo.toml b/fearless_simd_tests/Cargo.toml index 9eddb65d1..16fcf8f8c 100644 --- a/fearless_simd_tests/Cargo.toml +++ b/fearless_simd_tests/Cargo.toml @@ -9,6 +9,8 @@ description = "Safer and easier SIMD" readme = "README.md" rust-version.workspace = true publish = false +# Tests are collected through tests/mod.rs; files beside it are modules, not separate integration crates. +autotests = false [[test]] name = "tests" diff --git a/fearless_simd_tests/tests/mod.rs b/fearless_simd_tests/tests/mod.rs index 24c76c095..4d2f053d8 100644 --- a/fearless_simd_tests/tests/mod.rs +++ b/fearless_simd_tests/tests/mod.rs @@ -10,6 +10,7 @@ use fearless_simd::*; use fearless_simd_dev_macros::simd_test; mod harness; +mod soundness; // Ensure that we can cast between generic native-width vectors #[expect(dead_code, reason = "Compile only test")] diff --git a/fearless_simd_tests/tests/soundness.rs b/fearless_simd_tests/tests/soundness.rs new file mode 100644 index 000000000..680c56081 --- /dev/null +++ b/fearless_simd_tests/tests/soundness.rs @@ -0,0 +1,85 @@ +// Copyright 2026 the Fearless_SIMD Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +use std::panic::{AssertUnwindSafe, catch_unwind}; + +use fearless_simd::*; +use fearless_simd_dev_macros::simd_test; + +#[track_caller] +fn assert_panics(label: &str, f: impl FnOnce()) { + assert!( + catch_unwind(AssertUnwindSafe(f)).is_err(), + "{label} should panic" + ); +} + +macro_rules! for_each_simd_type { + ($test:ident, $simd:expr) => { + $test!($simd, f32x4, 4); + $test!($simd, i8x16, 16); + $test!($simd, u8x16, 16); + $test!($simd, mask8x16, 16); + $test!($simd, i16x8, 8); + $test!($simd, u16x8, 8); + $test!($simd, mask16x8, 8); + $test!($simd, i32x4, 4); + $test!($simd, u32x4, 4); + $test!($simd, mask32x4, 4); + $test!($simd, f64x2, 2); + $test!($simd, mask64x2, 2); + $test!($simd, f32x8, 8); + $test!($simd, i8x32, 32); + $test!($simd, u8x32, 32); + $test!($simd, mask8x32, 32); + $test!($simd, i16x16, 16); + $test!($simd, u16x16, 16); + $test!($simd, mask16x16, 16); + $test!($simd, i32x8, 8); + $test!($simd, u32x8, 8); + $test!($simd, mask32x8, 8); + $test!($simd, f64x4, 4); + $test!($simd, mask64x4, 4); + $test!($simd, f32x16, 16); + $test!($simd, i8x64, 64); + $test!($simd, u8x64, 64); + $test!($simd, mask8x64, 64); + $test!($simd, i16x32, 32); + $test!($simd, u16x32, 32); + $test!($simd, mask16x32, 32); + $test!($simd, i32x16, 16); + $test!($simd, u32x16, 16); + $test!($simd, mask32x16, 16); + $test!($simd, f64x8, 8); + $test!($simd, mask64x8, 8); + }; +} + +macro_rules! check_from_slice_short { + ($simd:expr, $vec:ident, $len:expr) => { + assert_panics(stringify!($vec::from_slice), || { + let _ = $vec::from_slice($simd, &[Default::default(); $len - 1]); + }); + }; +} + +macro_rules! check_store_slice_short { + ($simd:expr, $vec:ident, $len:expr) => {{ + let vec = $vec::from_slice($simd, &[Default::default(); $len]); + let mut short = [Default::default(); $len - 1]; + + assert_panics(stringify!($vec::store_slice), || { + vec.store_slice(&mut short) + }); + }}; +} + +#[simd_test] +fn from_slice_rejects_short_slice(simd: S) { + for_each_simd_type!(check_from_slice_short, simd); +} + +#[simd_test] +fn store_slice_rejects_short_slice(simd: S) { + for_each_simd_type!(check_store_slice_short, simd); +} From 0d9a0203930496c2892df3f83076800ed73931e5 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Tue, 19 May 2026 14:07:55 +0100 Subject: [PATCH 2/2] Only run soundness tests on targets that have unwinding --- fearless_simd_tests/tests/soundness.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fearless_simd_tests/tests/soundness.rs b/fearless_simd_tests/tests/soundness.rs index 680c56081..04cd04c1c 100644 --- a/fearless_simd_tests/tests/soundness.rs +++ b/fearless_simd_tests/tests/soundness.rs @@ -1,12 +1,14 @@ // Copyright 2026 the Fearless_SIMD Authors // SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(panic = "unwind")] use std::panic::{AssertUnwindSafe, catch_unwind}; use fearless_simd::*; use fearless_simd_dev_macros::simd_test; #[track_caller] +#[cfg(panic = "unwind")] fn assert_panics(label: &str, f: impl FnOnce()) { assert!( catch_unwind(AssertUnwindSafe(f)).is_err(), @@ -14,6 +16,12 @@ fn assert_panics(label: &str, f: impl FnOnce()) { ); } +#[cfg(not(panic = "unwind"))] +fn assert_panics(_label: &str, _f: impl FnOnce()) { + // These tests need panic unwinding to observe rejected operations. Some targets, such as + // wasm32-wasip1, abort on panic instead. +} + macro_rules! for_each_simd_type { ($test:ident, $simd:expr) => { $test!($simd, f32x4, 4);