diff options
| author | bors <bors@rust-lang.org> | 2023-12-05 07:12:28 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-12-05 07:12:28 +0000 |
| commit | 73db2e48d78750d96bb54915738d46d365395226 (patch) | |
| tree | 8fe1f2530f94a2fbabf5ba2c69cd2d5a55e78537 | |
| parent | 88d905cb3a09054665b9cee9b7a3ee0c139f8df7 (diff) | |
| parent | 1fa8fd800f7cdd245b8ea73dd0673a1cf434d925 (diff) | |
| download | rust-73db2e48d78750d96bb54915738d46d365395226.tar.gz rust-73db2e48d78750d96bb54915738d46d365395226.zip | |
Auto merge of #3211 - RalfJung:promise, r=RalfJung
fix promising a very large alignment Also make use of https://github.com/rust-lang/rust/pull/118565 to simplify some SIMD intrinsics, while we are at it
6 files changed, 48 insertions, 16 deletions
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 15432c5dd9c..8ddfc05dd30 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -558,14 +558,23 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Promises that a pointer has a given symbolic alignment. "miri_promise_symbolic_alignment" => { + use rustc_target::abi::AlignFromBytesError; + let [ptr, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let align = this.read_target_usize(align)?; - let Ok(align) = Align::from_bytes(align) else { + if !align.is_power_of_two() { throw_unsup_format!( - "`miri_promise_symbolic_alignment`: alignment must be a power of 2" + "`miri_promise_symbolic_alignment`: alignment must be a power of 2, got {align}" ); - }; + } + let align = Align::from_bytes(align).unwrap_or_else(|err| { + match err { + AlignFromBytesError::NotPowerOfTwo(_) => unreachable!(), + // When the alignment is a power of 2 but too big, clamp it to MAX. + AlignFromBytesError::TooLarge(_) => Align::MAX, + } + }); let (_, addr) = ptr.into_parts(); // we know the offset is absolute // Cannot panic since `align` is a power of 2 and hence non-zero. if addr.bytes().checked_rem(align.bytes()).unwrap() != 0 { diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index a514cadcec9..e17c06be9b8 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -115,18 +115,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } Op::Numeric(name) => { - assert!(op.layout.ty.is_integral()); - let size = op.layout.size; - let bits = op.to_scalar().to_bits(size).unwrap(); - let extra = 128u128.checked_sub(u128::from(size.bits())).unwrap(); - let bits_out = match name { - sym::ctlz => u128::from(bits.leading_zeros()).checked_sub(extra).unwrap(), - sym::cttz => u128::from((bits << extra).trailing_zeros()).checked_sub(extra).unwrap(), - sym::bswap => (bits << extra).swap_bytes(), - sym::bitreverse => (bits << extra).reverse_bits(), - _ => unreachable!(), - }; - Scalar::from_uint(bits_out, size) + this.numeric_intrinsic(name, op.to_scalar(), op.layout)? } }; this.write_scalar(val, &dest)?; diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.rs b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.rs new file mode 100644 index 00000000000..5b0638b1fdf --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.rs @@ -0,0 +1,8 @@ +#[path = "../../utils/mod.rs"] +mod utils; + +fn main() { + let buffer = [0u32; 128]; + unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) }; + //~^ERROR: alignment must be a power of 2 +} diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr new file mode 100644 index 00000000000..b3327e04933 --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0 + --> $DIR/promise_alignment_zero.rs:LL:CC + | +LL | unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0 + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/promise_alignment_zero.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.rs b/src/tools/miri/tests/pass/align_offset_symbolic.rs index 292858ebc2e..3e493952d28 100644 --- a/src/tools/miri/tests/pass/align_offset_symbolic.rs +++ b/src/tools/miri/tests/pass/align_offset_symbolic.rs @@ -90,9 +90,21 @@ fn test_cstr() { std::ffi::CStr::from_bytes_with_nul(b"this is a test that is longer than 16 bytes\0").unwrap(); } +fn huge_align() { + #[cfg(target_pointer_width = "64")] + const SIZE: usize = 1 << 47; + #[cfg(target_pointer_width = "32")] + const SIZE: usize = 1 << 30; + #[cfg(target_pointer_width = "16")] + const SIZE: usize = 1 << 13; + struct HugeSize([u8; SIZE - 1]); + let _ = std::ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE); +} + fn main() { test_align_to(); test_from_utf8(); test_u64_array(); test_cstr(); + huge_align(); } diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs index a5cf337da02..a8a7387ecdc 100644 --- a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs @@ -30,7 +30,7 @@ fn main() { unsafe { let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; let p = p.unsize() as *const PackedUnsized; - // Make sure the size computation correctly adds exact 1 byte of padding + // Make sure the size computation correctly adds exactly 1 byte of padding // in front of the `d` field. assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4 * 4); // And likewise for the offset computation. |
