Skip to content

Commit 0de6873

Browse files
committed
miri: validity checks alignment even when machine otherwise does not
1 parent 30c63aa commit 0de6873

File tree

4 files changed

+33
-9
lines changed

4 files changed

+33
-9
lines changed

Diff for: src/librustc_mir/interpret/memory.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
306306
///
307307
/// Most of the time you should use `check_mplace_access`, but when you just have a pointer,
308308
/// this method is still appropriate.
309+
#[inline(always)]
309310
pub fn check_ptr_access(
310311
&self,
311312
sptr: Scalar<M::PointerTag>,
312313
size: Size,
313314
align: Align,
315+
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
316+
let align = if M::CHECK_ALIGN { Some(align) } else { None };
317+
self.check_ptr_access_align(sptr, size, align)
318+
}
319+
320+
/// Like `check_ptr_access`, but *definitely* checks alignment when `align`
321+
/// is `Some` (overriding `M::CHECK_ALIGN`).
322+
pub(super) fn check_ptr_access_align(
323+
&self,
324+
sptr: Scalar<M::PointerTag>,
325+
size: Size,
326+
align: Option<Align>,
314327
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
315328
fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
316329
if offset % align.bytes() == 0 {
@@ -343,7 +356,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
343356
throw_unsup!(InvalidNullPointerUsage)
344357
}
345358
// Must be aligned.
346-
if M::CHECK_ALIGN {
359+
if let Some(align) = align {
347360
check_offset_align(bits, align)?;
348361
}
349362
None
@@ -358,7 +371,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
358371
end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?;
359372
// Test align. Check this last; if both bounds and alignment are violated
360373
// we want the error to be about the bounds.
361-
if M::CHECK_ALIGN {
374+
if let Some(align) = align {
362375
if alloc_align.bytes() < align.bytes() {
363376
// The allocation itself is not aligned enough.
364377
// FIXME: Alignment check is too strict, depending on the base address that

Diff for: src/librustc_mir/interpret/validity.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,9 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
398398
// alignment and size determined by the layout (size will be 0,
399399
// alignment should take attributes into account).
400400
.unwrap_or_else(|| (layout.size, layout.align.abi));
401-
let ptr: Option<_> = match self.ecx.memory.check_ptr_access(ptr, size, align) {
401+
let ptr: Option<_> = match
402+
self.ecx.memory.check_ptr_access_align(ptr, size, Some(align))
403+
{
402404
Ok(ptr) => ptr,
403405
Err(err) => {
404406
info!(

Diff for: src/test/ui/consts/const-eval/ub-ref.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
use std::mem;
55

6-
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; // Ok (CTFE does not check alignment)
6+
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
7+
//~^ ERROR it is undefined behavior to use this value
78

89
const NULL: &u16 = unsafe { mem::transmute(0usize) };
910
//~^ ERROR it is undefined behavior to use this value

Diff for: src/test/ui/consts/const-eval/ub-ref.stderr

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-ref.rs:8:1
2+
--> $DIR/ub-ref.rs:6:1
3+
|
4+
LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
6+
|
7+
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
8+
9+
error[E0080]: it is undefined behavior to use this value
10+
--> $DIR/ub-ref.rs:9:1
311
|
412
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
513
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
614
|
715
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
816

917
error[E0080]: it is undefined behavior to use this value
10-
--> $DIR/ub-ref.rs:11:1
18+
--> $DIR/ub-ref.rs:12:1
1119
|
1220
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
1321
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
1422
|
1523
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
1624

1725
error[E0080]: it is undefined behavior to use this value
18-
--> $DIR/ub-ref.rs:14:1
26+
--> $DIR/ub-ref.rs:15:1
1927
|
2028
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
2129
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
2230
|
2331
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
2432

2533
error[E0080]: it is undefined behavior to use this value
26-
--> $DIR/ub-ref.rs:17:1
34+
--> $DIR/ub-ref.rs:18:1
2735
|
2836
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
2937
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer)
3038
|
3139
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
3240

33-
error: aborting due to 4 previous errors
41+
error: aborting due to 5 previous errors
3442

3543
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)