Skip to content

Commit 9c32ede

Browse files
committed
comment tweaks, better validation errors, update UI tests
1 parent c12c8a7 commit 9c32ede

File tree

4 files changed

+36
-26
lines changed

4 files changed

+36
-26
lines changed

src/librustc_mir/interpret/memory.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use super::{
2020
Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
2121
InterpResult, Scalar, InterpError, GlobalAlloc, PointerArithmetic,
2222
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg,
23-
InterpError::ValidationFailure,
2423
};
2524

2625
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
@@ -260,13 +259,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
260259
}
261260

262261
/// Check if the given scalar is allowed to do a memory access of given `size`
263-
/// and `align`. On success, returns `None` for zero-sized accesses (where
262+
/// and `align`. On success, returns `None` for zero-sized accesses (where
264263
/// nothing else is left to do) and a `Pointer` to use for the actual access otherwise.
265264
/// Crucially, if the input is a `Pointer`, we will test it for liveness
266265
/// *even of* the size is 0.
267266
///
268267
/// Everyone accessing memory based on a `Scalar` should use this method to get the
269-
/// `Pointer` they need. And even if you already have a `Pointer`, call this method
268+
/// `Pointer` they need. And even if you already have a `Pointer`, call this method
270269
/// to make sure it is sufficiently aligned and not dangling. Not doing that may
271270
/// cause ICEs.
272271
pub fn check_ptr_access(
@@ -292,9 +291,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
292291
return err!(InvalidNullPointerUsage);
293292
}
294293
if bits % align.bytes() != 0 {
295-
let bits_pow1 = 1 << bits.trailing_zeros();
294+
// The biggest power of two through which `bits` is divisible.
295+
let bits_pow2 = 1 << bits.trailing_zeros();
296296
return err!(AlignmentCheckFailed {
297-
has: Align::from_bytes(bits_pow1).unwrap(),
297+
has: Align::from_bytes(bits_pow2).unwrap(),
298298
required: align,
299299
});
300300
}
@@ -308,7 +308,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
308308
// checks for overflow.
309309
let end_ptr = ptr.offset(size, self)?;
310310
end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?;
311-
// Test align. Check this last; if both bounds and alignment are violated
311+
// Test align. Check this last; if both bounds and alignment are violated
312312
// we want the error to be about the bounds.
313313
if alloc_align.bytes() < align.bytes() {
314314
// The allocation itself is not aligned enough.
@@ -323,10 +323,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
323323
}
324324
let offset = ptr.offset.bytes();
325325
if offset % align.bytes() != 0 {
326-
// The offset os not aligned enough.
327-
let has = offset % align.bytes();
326+
// The biggest power of two through which `offset` is divisible.
327+
let bits_pow2 = 1 << offset.trailing_zeros();
328328
return err!(AlignmentCheckFailed {
329-
has: Align::from_bytes(has).unwrap(),
329+
has: Align::from_bytes(bits_pow2).unwrap(),
330330
required: align,
331331
})
332332
}
@@ -520,15 +520,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
520520
}
521521
_ => {
522522
if let Ok(alloc) = self.get(id) {
523-
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
523+
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align))
524524
}
525-
if let AllocCheck::MaybeDead = liveness {
525+
else if let AllocCheck::MaybeDead = liveness {
526526
// Deallocated pointers are allowed, we should be able to find
527527
// them in the map.
528-
self.dead_alloc_map.get(&id).copied().ok_or_else(||
529-
ValidationFailure("allocation missing in dead_alloc_map".to_string())
530-
.into()
531-
)
528+
Ok(*self.dead_alloc_map.get(&id)
529+
.expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
532530
} else {
533531
err!(DanglingPointerDeref)
534532
}

src/librustc_mir/interpret/operand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
228228

229229
let ptr = match self.memory.check_ptr_access(ptr, mplace.layout.size, ptr_align)? {
230230
Some(ptr) => ptr,
231-
None => return Ok(Some(ImmTy {
231+
None => return Ok(Some(ImmTy { // zero-sized type
232232
imm: Immediate::Scalar(Scalar::zst().into()),
233233
layout: mplace.layout,
234-
})), // zero-sized access
234+
})),
235235
};
236236

237237
match mplace.layout.abi {

src/librustc_mir/interpret/validity.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,15 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
366366
match tail.sty {
367367
ty::Dynamic(..) => {
368368
let vtable = meta.unwrap();
369-
try_validation!(self.ecx.memory.check_ptr_access(
370-
vtable,
371-
3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align
372-
self.ecx.tcx.data_layout.pointer_align.abi,
373-
), "dangling or unaligned vtable pointer", self.path);
369+
try_validation!(
370+
self.ecx.memory.check_ptr_access(
371+
vtable,
372+
3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align
373+
self.ecx.tcx.data_layout.pointer_align.abi,
374+
),
375+
"dangling or unaligned vtable pointer or too small vtable",
376+
self.path
377+
);
374378
try_validation!(self.ecx.read_drop_type_from_vtable(vtable),
375379
"invalid drop fn in vtable", self.path);
376380
try_validation!(self.ecx.read_size_and_align_from_vtable(vtable),
@@ -397,14 +401,22 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
397401
let ptr: Option<_> = match self.ecx.memory.check_ptr_access(ptr, size, align) {
398402
Ok(ptr) => ptr,
399403
Err(err) => {
400-
info!("{:?} is not aligned to {:?}", ptr, align);
404+
info!(
405+
"{:?} did not pass access check for size {:?}, align {:?}",
406+
ptr, size, align
407+
);
401408
match err.kind {
402409
InterpError::InvalidNullPointerUsage =>
403410
return validation_failure!("NULL reference", self.path),
404411
InterpError::AlignmentCheckFailed { required, has } =>
405412
return validation_failure!(format!("unaligned reference \
406413
(required {} byte alignment but found {})",
407414
required.bytes(), has.bytes()), self.path),
415+
InterpError::ReadBytesAsPointer =>
416+
return validation_failure!(
417+
"integer pointer in non-ZST reference",
418+
self.path
419+
),
408420
_ =>
409421
return validation_failure!(
410422
"dangling (not entirely in bounds) reference",

src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,23 @@ error[E0080]: it is undefined behavior to use this value
4242
--> $DIR/union-ub-fat-ptr.rs:97:1
4343
|
4444
LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
45-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
45+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable
4646
|
4747
= 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
4848

4949
error[E0080]: it is undefined behavior to use this value
5050
--> $DIR/union-ub-fat-ptr.rs:100:1
5151
|
5252
LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable
5454
|
5555
= 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
5656

5757
error[E0080]: it is undefined behavior to use this value
5858
--> $DIR/union-ub-fat-ptr.rs:103:1
5959
|
6060
LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
61-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
61+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable
6262
|
6363
= 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
6464

0 commit comments

Comments
 (0)