Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,25 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
None
}
} else {
// We are not checking dereferenceability, but we still want to ensure that the pointer
// *could* be dereferenceable in *some* memory: we have to be able to compute the
// address at the end of this range without overflowing..
let scalar = Scalar::from_maybe_pointer(place.ptr(), self.ecx);
// Skip this if we don't know the absolute address (during CTFE).
if let Ok(addr) = scalar.try_to_scalar_int() {
// Try to compute the end address.
let addr = Size::from_bytes(addr.to_target_usize(*self.ecx.tcx));
if addr.checked_add(size, self.ecx).is_none() {
throw_validation_failure!(
self.path,
format!(
"encountered a {ptr_kind} that is too close to the end of the address space for a pointee of {} bytes",
size.bytes(),
)
)
}
}

// Pointer remains unchanged.
None
};
Expand All @@ -658,20 +677,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
self.reset_pointer_provenance(value, &ptr)?;
}

// Check alignment after dereferenceable (if both are violated, trigger the error above).
try_validation!(
self.ecx.check_ptr_align(
place.ptr(),
align,
),
self.path,
Ub(AlignmentCheckFailed(Misalignment { required, has }, _msg)) => format!(
"encountered an unaligned {ptr_kind} (required {required_bytes} byte alignment but found {found_bytes})",
required_bytes = required.bytes(),
found_bytes = has.bytes()
),
);

// Make sure this is non-null. This is obviously needed when `may_dangle` is set,
// but even if we did check dereferenceability above that would still allow null
// pointers if `size` is zero.
Expand All @@ -686,6 +691,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
)
)
}

// Do not allow references to uninhabited types.
if !place.layout.ty.is_opsem_inhabited(*self.ecx.tcx, self.ecx.typing_env) {
let ty = place.layout.ty;
Expand All @@ -695,6 +701,20 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
)
}

// Check alignment after dereferenceable (if both are violated, trigger the error above).
try_validation!(
self.ecx.check_ptr_align(
place.ptr(),
align,
),
self.path,
Ub(AlignmentCheckFailed(Misalignment { required, has }, _msg)) => format!(
"encountered an unaligned {ptr_kind} (required {required_bytes} byte alignment but found {found_bytes})",
required_bytes = required.bytes(),
found_bytes = has.bytes()
),
);

// Recursive checking (but not inside `MaybeDangling` of course).
if let Some(ref_tracking) = self.ref_tracking.as_deref_mut()
&& !self.may_dangle
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#![feature(maybe_dangling)]
use std::mem::{transmute, MaybeDangling};

fn main() {
let _x: MaybeDangling<&i8> = unsafe { transmute(usize::MAX) };
//~^ERROR: too close to the end of the address space
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&i8>: encountered a reference that is too close to the end of the address space for a pointee of 1 bytes
--> tests/fail/validity/maybe_dangling_ref_too_big.rs:LL:CC
|
LL | let _x: MaybeDangling<&i8> = unsafe { transmute(usize::MAX) };
| ^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

Loading