aarch64: fix UB in non-power-of-two reads and writes

(cherry picked from commit 2fa37e7b34)
This commit is contained in:
Folkert de Vries
2026-02-26 13:00:21 +01:00
committed by Josh Stone
parent 8ebd005178
commit e427d29e3c
+14 -6
View File
@@ -226,12 +226,12 @@ macro_rules! deinterleaving_load {
($elem:ty, $lanes:literal, 2, $ptr:expr) => {{
use $crate::core_arch::macros::deinterleave_mask;
use $crate::core_arch::simd::Simd;
use $crate::{mem::transmute, ptr};
use $crate::mem::transmute;
type V = Simd<$elem, $lanes>;
type W = Simd<$elem, { $lanes * 2 }>;
let w: W = ptr::read_unaligned($ptr as *const W);
let w: W = $crate::ptr::read_unaligned($ptr as *const W);
let v0: V = simd_shuffle!(w, w, deinterleave_mask::<$lanes, 2, 0>());
let v1: V = simd_shuffle!(w, w, deinterleave_mask::<$lanes, 2, 1>());
@@ -242,12 +242,20 @@ macro_rules! deinterleaving_load {
($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};
use $crate::mem::{MaybeUninit, transmute};
type V = Simd<$elem, $lanes>;
type W = Simd<$elem, { $lanes * 3 }>;
let w: W = ptr::read_unaligned($ptr as *const W);
// NOTE: repr(simd) adds padding to make the total size a power of two.
// Hence reading W from ptr might read out of bounds.
let mut mem = MaybeUninit::<W>::uninit();
$crate::ptr::copy_nonoverlapping(
$ptr.cast::<$elem>(),
mem.as_mut_ptr().cast::<$elem>(),
$lanes * 3,
);
let w = mem.assume_init();
let v0: V = simd_shuffle!(w, w, deinterleave_mask::<$lanes, 3, 0>());
let v1: V = simd_shuffle!(w, w, deinterleave_mask::<$lanes, 3, 1>());
@@ -259,12 +267,12 @@ macro_rules! deinterleaving_load {
($elem:ty, $lanes:literal, 4, $ptr:expr) => {{
use $crate::core_arch::macros::deinterleave_mask;
use $crate::core_arch::simd::Simd;
use $crate::{mem::transmute, ptr};
use $crate::mem::transmute;
type V = Simd<$elem, $lanes>;
type W = Simd<$elem, { $lanes * 4 }>;
let w: W = ptr::read_unaligned($ptr as *const W);
let w: W = $crate::ptr::read_unaligned($ptr as *const W);
let v0: V = simd_shuffle!(w, w, deinterleave_mask::<$lanes, 4, 0>());
let v1: V = simd_shuffle!(w, w, deinterleave_mask::<$lanes, 4, 1>());