Skip to content

Commit 73db2e4

Browse files
committed
Auto merge of #3211 - RalfJung:promise, r=RalfJung
fix promising a very large alignment Also make use of #118565 to simplify some SIMD intrinsics, while we are at it
2 parents 88d905c + 1fa8fd8 commit 73db2e4

File tree

6 files changed

+48
-16
lines changed

6 files changed

+48
-16
lines changed

src/tools/miri/src/shims/foreign_items.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -558,14 +558,23 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
558558

559559
// Promises that a pointer has a given symbolic alignment.
560560
"miri_promise_symbolic_alignment" => {
561+
use rustc_target::abi::AlignFromBytesError;
562+
561563
let [ptr, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
562564
let ptr = this.read_pointer(ptr)?;
563565
let align = this.read_target_usize(align)?;
564-
let Ok(align) = Align::from_bytes(align) else {
566+
if !align.is_power_of_two() {
565567
throw_unsup_format!(
566-
"`miri_promise_symbolic_alignment`: alignment must be a power of 2"
568+
"`miri_promise_symbolic_alignment`: alignment must be a power of 2, got {align}"
567569
);
568-
};
570+
}
571+
let align = Align::from_bytes(align).unwrap_or_else(|err| {
572+
match err {
573+
AlignFromBytesError::NotPowerOfTwo(_) => unreachable!(),
574+
// When the alignment is a power of 2 but too big, clamp it to MAX.
575+
AlignFromBytesError::TooLarge(_) => Align::MAX,
576+
}
577+
});
569578
let (_, addr) = ptr.into_parts(); // we know the offset is absolute
570579
// Cannot panic since `align` is a power of 2 and hence non-zero.
571580
if addr.bytes().checked_rem(align.bytes()).unwrap() != 0 {

src/tools/miri/src/shims/intrinsics/simd.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
115115
}
116116
}
117117
Op::Numeric(name) => {
118-
assert!(op.layout.ty.is_integral());
119-
let size = op.layout.size;
120-
let bits = op.to_scalar().to_bits(size).unwrap();
121-
let extra = 128u128.checked_sub(u128::from(size.bits())).unwrap();
122-
let bits_out = match name {
123-
sym::ctlz => u128::from(bits.leading_zeros()).checked_sub(extra).unwrap(),
124-
sym::cttz => u128::from((bits << extra).trailing_zeros()).checked_sub(extra).unwrap(),
125-
sym::bswap => (bits << extra).swap_bytes(),
126-
sym::bitreverse => (bits << extra).reverse_bits(),
127-
_ => unreachable!(),
128-
};
129-
Scalar::from_uint(bits_out, size)
118+
this.numeric_intrinsic(name, op.to_scalar(), op.layout)?
130119
}
131120
};
132121
this.write_scalar(val, &dest)?;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[path = "../../utils/mod.rs"]
2+
mod utils;
3+
4+
fn main() {
5+
let buffer = [0u32; 128];
6+
unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) };
7+
//~^ERROR: alignment must be a power of 2
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: unsupported operation: `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0
2+
--> $DIR/promise_alignment_zero.rs:LL:CC
3+
|
4+
LL | unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0
6+
|
7+
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
8+
= note: BACKTRACE:
9+
= note: inside `main` at $DIR/promise_alignment_zero.rs:LL:CC
10+
11+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
12+
13+
error: aborting due to 1 previous error
14+

src/tools/miri/tests/pass/align_offset_symbolic.rs

+12
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,21 @@ fn test_cstr() {
9090
std::ffi::CStr::from_bytes_with_nul(b"this is a test that is longer than 16 bytes\0").unwrap();
9191
}
9292

93+
fn huge_align() {
94+
#[cfg(target_pointer_width = "64")]
95+
const SIZE: usize = 1 << 47;
96+
#[cfg(target_pointer_width = "32")]
97+
const SIZE: usize = 1 << 30;
98+
#[cfg(target_pointer_width = "16")]
99+
const SIZE: usize = 1 << 13;
100+
struct HugeSize([u8; SIZE - 1]);
101+
let _ = std::ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE);
102+
}
103+
93104
fn main() {
94105
test_align_to();
95106
test_from_utf8();
96107
test_u64_array();
97108
test_cstr();
109+
huge_align();
98110
}

src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn main() {
3030
unsafe {
3131
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
3232
let p = p.unsize() as *const PackedUnsized;
33-
// Make sure the size computation correctly adds exact 1 byte of padding
33+
// Make sure the size computation correctly adds exactly 1 byte of padding
3434
// in front of the `d` field.
3535
assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4 * 4);
3636
// And likewise for the offset computation.

0 commit comments

Comments
 (0)