Skip to content

Commit 51f90a1

Browse files
authored
Rollup merge of rust-lang#56985 - oli-obk:const_check_bounds, r=RalfJung
Allow testing pointers for inboundedness while forbidding dangling pointers r? @RalfJung
2 parents 05f3b3c + c8bcac5 commit 51f90a1

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

src/librustc_mir/interpret/memory.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
262262
Scalar::Ptr(ptr) => {
263263
// check this is not NULL -- which we can ensure only if this is in-bounds
264264
// of some (potentially dead) allocation.
265-
let align = self.check_bounds_ptr_maybe_dead(ptr)?;
265+
let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead)?;
266266
(ptr.offset.bytes(), align)
267267
}
268268
Scalar::Bits { bits, size } => {
@@ -297,17 +297,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
297297
/// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
298298
/// of an allocation (i.e., at the first *inaccessible* location) *is* considered
299299
/// in-bounds! This follows C's/LLVM's rules.
300-
/// This function also works for deallocated allocations.
301-
/// Use `.get(ptr.alloc_id)?.check_bounds_ptr(ptr)` if you want to force the allocation
302-
/// to still be live.
303300
/// If you want to check bounds before doing a memory access, better first obtain
304301
/// an `Allocation` and call `check_bounds`.
305-
pub fn check_bounds_ptr_maybe_dead(
302+
pub fn check_bounds_ptr(
306303
&self,
307304
ptr: Pointer<M::PointerTag>,
305+
liveness: InboundsCheck,
308306
) -> EvalResult<'tcx, Align> {
309-
let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id);
310-
ptr.check_in_alloc(allocation_size, InboundsCheck::MaybeDead)?;
307+
let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, liveness)?;
308+
ptr.check_in_alloc(allocation_size, liveness)?;
311309
Ok(align)
312310
}
313311
}
@@ -429,27 +427,37 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
429427
}
430428
}
431429

432-
pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) {
430+
/// Obtain the size and alignment of an allocation, even if that allocation has been deallocated
431+
///
432+
/// If `liveness` is `InboundsCheck::Dead`, this function always returns `Ok`
433+
pub fn get_size_and_align(
434+
&self,
435+
id: AllocId,
436+
liveness: InboundsCheck,
437+
) -> EvalResult<'static, (Size, Align)> {
433438
if let Ok(alloc) = self.get(id) {
434-
return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align);
439+
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
435440
}
436441
// Could also be a fn ptr or extern static
437442
match self.tcx.alloc_map.lock().get(id) {
438-
Some(AllocKind::Function(..)) => (Size::ZERO, Align::from_bytes(1).unwrap()),
443+
Some(AllocKind::Function(..)) => Ok((Size::ZERO, Align::from_bytes(1).unwrap())),
439444
Some(AllocKind::Static(did)) => {
440445
// The only way `get` couldn't have worked here is if this is an extern static
441446
assert!(self.tcx.is_foreign_item(did));
442447
// Use size and align of the type
443448
let ty = self.tcx.type_of(did);
444449
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
445-
(layout.size, layout.align.abi)
446-
}
447-
_ => {
448-
// Must be a deallocated pointer
449-
*self.dead_alloc_map.get(&id).expect(
450-
"allocation missing in dead_alloc_map"
451-
)
450+
Ok((layout.size, layout.align.abi))
452451
}
452+
_ => match liveness {
453+
InboundsCheck::MaybeDead => {
454+
// Must be a deallocated pointer
455+
Ok(*self.dead_alloc_map.get(&id).expect(
456+
"allocation missing in dead_alloc_map"
457+
))
458+
},
459+
InboundsCheck::Live => err!(DanglingPointerDeref),
460+
},
453461
}
454462
}
455463

src/librustc_mir/interpret/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::mir;
1717
use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx};
1818

1919
use rustc::mir::interpret::{
20-
GlobalId, AllocId,
20+
GlobalId, AllocId, InboundsCheck,
2121
ConstValue, Pointer, Scalar,
2222
EvalResult, EvalErrorKind,
2323
};
@@ -647,7 +647,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
647647
ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => {
648648
// The niche must be just 0 (which an inbounds pointer value never is)
649649
let ptr_valid = niche_start == 0 && variants_start == variants_end &&
650-
self.memory.check_bounds_ptr_maybe_dead(ptr).is_ok();
650+
self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok();
651651
if !ptr_valid {
652652
return err!(InvalidDiscriminant(raw_discr.erase_tag()));
653653
}

0 commit comments

Comments
 (0)