Auto merge of #134424 - 1c3t3a:null-checks, r=saethlin
Insert null checks for pointer dereferences when debug assertions are enabled Similar to how the alignment is already checked, this adds a check for null pointer dereferences in debug mode. It is implemented similarly to the alignment check as a `MirPass`. This inserts checks in the same places as the `CheckAlignment` pass and additionally also inserts checks for `Borrows`, so code like ```rust let ptr: *const u32 = std::ptr::null(); let val: &u32 = unsafe { &*ptr }; ``` will have a check inserted on dereference. This is done because null references are UB. The alignment check doesn't cover these places, because in `&(*ptr).field`, the exact requirement is that the final reference must be aligned. This is something to consider further enhancements of the alignment check. For now this is implemented as a separate `MirPass`, to make it easy to disable this check if necessary. This is related to a 2025H1 project goal for better UB checks in debug mode: https://github.com/rust-lang/rust-project-goals/pull/177. r? `@saethlin`
This commit is contained in:
commit
aa4cfd0809
33 changed files with 551 additions and 164 deletions
|
@ -17,6 +17,9 @@ middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further itera
|
|||
middle_assert_misaligned_ptr_deref =
|
||||
misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
|
||||
|
||||
middle_assert_null_ptr_deref =
|
||||
null pointer dereference occurred
|
||||
|
||||
middle_assert_op_overflow =
|
||||
attempt to compute `{$left} {$op} {$right}`, which would overflow
|
||||
|
||||
|
|
|
@ -1076,6 +1076,7 @@ pub enum AssertKind<O> {
|
|||
ResumedAfterReturn(CoroutineKind),
|
||||
ResumedAfterPanic(CoroutineKind),
|
||||
MisalignedPointerDereference { required: O, found: O },
|
||||
NullPointerDereference,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
|
|
|
@ -206,6 +206,7 @@ impl<O> AssertKind<O> {
|
|||
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
|
||||
LangItem::PanicGenFnNonePanic
|
||||
}
|
||||
NullPointerDereference => LangItem::PanicNullPointerDereference,
|
||||
|
||||
BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
|
||||
bug!("Unexpected AssertKind")
|
||||
|
@ -271,6 +272,7 @@ impl<O> AssertKind<O> {
|
|||
"\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}"
|
||||
)
|
||||
}
|
||||
NullPointerDereference => write!(f, "\"null pointer dereference occured\""),
|
||||
ResumedAfterReturn(CoroutineKind::Coroutine(_)) => {
|
||||
write!(f, "\"coroutine resumed after completion\"")
|
||||
}
|
||||
|
@ -341,7 +343,7 @@ impl<O> AssertKind<O> {
|
|||
ResumedAfterPanic(CoroutineKind::Coroutine(_)) => {
|
||||
middle_assert_coroutine_resume_after_panic
|
||||
}
|
||||
|
||||
NullPointerDereference => middle_assert_null_ptr_deref,
|
||||
MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
|
||||
}
|
||||
}
|
||||
|
@ -374,7 +376,7 @@ impl<O> AssertKind<O> {
|
|||
add!("left", format!("{left:#?}"));
|
||||
add!("right", format!("{right:#?}"));
|
||||
}
|
||||
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
|
||||
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {}
|
||||
MisalignedPointerDereference { required, found } => {
|
||||
add!("required", format!("{required:#?}"));
|
||||
add!("found", format!("{found:#?}"));
|
||||
|
|
|
@ -636,7 +636,7 @@ macro_rules! make_mir_visitor {
|
|||
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
|
||||
self.visit_operand(op, location);
|
||||
}
|
||||
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
|
||||
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {
|
||||
// Nothing to visit
|
||||
}
|
||||
MisalignedPointerDereference { required, found } => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue