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
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,17 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
source_info.span,
)
}
AssertKind::NullReferenceConstructed => {
let location = fx.get_caller_location(source_info).load_scalar(fx);

codegen_panic_inner(
fx,
rustc_hir::LangItem::PanicNullReferenceConstructed,
&[location],
*unwind,
source_info.span,
)
}
AssertKind::InvalidEnumConstruction(source) => {
let source = codegen_operand(fx, source).load_scalar(fx);
let location = fx.get_caller_location(source_info).load_scalar(fx);
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// `#[track_caller]` adds an implicit argument.
(LangItem::PanicNullPointerDereference, vec![location])
}
AssertKind::NullReferenceConstructed => {
// It's `fn panic_null_reference_constructed()`,
// `#[track_caller]` adds an implicit argument.
(LangItem::PanicNullReferenceConstructed, vec![location])
}
AssertKind::InvalidEnumConstruction(source) => {
let source = self.codegen_operand(bx, source).immediate();
// It's `fn panic_invalid_enum_construction(source: u128)`,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
found: eval_to_int(found)?,
},
NullPointerDereference => NullPointerDereference,
NullReferenceConstructed => NullReferenceConstructed,
InvalidEnumConstruction(source) => InvalidEnumConstruction(eval_to_int(source)?),
};
Err(ConstEvalErrKind::AssertFailure(err)).into()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ language_item_table! {
PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None;
PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None;
PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
PanicNullReferenceConstructed, sym::panic_null_reference_constructed, panic_null_reference_constructed, Target::Fn, GenericRequirement::None;
PanicInvalidEnumConstruction, sym::panic_invalid_enum_construction, panic_invalid_enum_construction, Target::Fn, GenericRequirement::None;
PanicCoroutineResumedDrop, sym::panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_drop, Target::Fn, GenericRequirement::None;
PanicAsyncFnResumedDrop, sym::panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_drop, Target::Fn, GenericRequirement::None;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,7 @@ pub enum AssertKind<O> {
ResumedAfterDrop(CoroutineKind),
MisalignedPointerDereference { required: O, found: O },
NullPointerDereference,
NullReferenceConstructed,
InvalidEnumConstruction(O),
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/mir/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ impl<O> AssertKind<O> {
LangItem::PanicGenFnNonePanic
}
NullPointerDereference => LangItem::PanicNullPointerDereference,
NullReferenceConstructed => LangItem::PanicNullReferenceConstructed,
InvalidEnumConstruction(_) => LangItem::PanicInvalidEnumConstruction,
ResumedAfterDrop(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumedDrop,
ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
Expand Down Expand Up @@ -287,6 +288,7 @@ impl<O> AssertKind<O> {
)
}
NullPointerDereference => write!(f, "\"null pointer dereference occurred\""),
NullReferenceConstructed => write!(f, "\"null reference produced\""),
InvalidEnumConstruction(source) => {
write!(f, "\"trying to construct an enum from an invalid value {{}}\", {source:?}")
}
Expand Down Expand Up @@ -387,6 +389,7 @@ impl<O: fmt::Debug> fmt::Display for AssertKind<O> {
write!(f, "coroutine resumed after panicking")
}
NullPointerDereference => write!(f, "null pointer dereference occurred"),
NullReferenceConstructed => write!(f, "null reference produced"),
InvalidEnumConstruction(source) => {
write!(f, "trying to construct an enum from an invalid value `{source:#?}`")
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ macro_rules! make_mir_visitor {
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) | InvalidEnumConstruction(op) => {
self.visit_operand(op, location);
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => {
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | NullReferenceConstructed | ResumedAfterDrop(_) => {
// Nothing to visit
}
MisalignedPointerDereference { required, found } => {
Expand Down
24 changes: 12 additions & 12 deletions compiler/rustc_mir_transform/src/check_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,19 @@ fn insert_null_check<'tcx>(
const_: Const::Val(ConstValue::from_target_usize(0, &tcx), tcx.types.usize),
}));

let pointee_should_be_checked = match context {
let (pointee_should_be_checked, assert_kind) = match context {
// Borrows pointing to "null" are UB even if the pointee is a ZST.
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
// Pointer should be checked unconditionally.
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::from_bool(tcx, true),
}))
(
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::from_bool(tcx, true),
})),
AssertKind::NullReferenceConstructed,
)
}
// Other usages of null pointers only are UB if the pointee is not a ZST.
_ => {
Expand All @@ -79,7 +82,7 @@ fn insert_null_check<'tcx>(
source_info,
StatementKind::Assign(Box::new((pointee_should_be_checked, rvalue))),
));
Operand::Copy(pointee_should_be_checked)
(Operand::Copy(pointee_should_be_checked), AssertKind::NullPointerDereference)
}
};

Expand Down Expand Up @@ -119,9 +122,6 @@ fn insert_null_check<'tcx>(
));

// Emit a PointerCheck that asserts on the condition and otherwise triggers
// a AssertKind::NullPointerDereference.
PointerCheck {
cond: Operand::Copy(is_ok),
assert_kind: Box::new(AssertKind::NullPointerDereference),
}
// the chosen AssertKind.
PointerCheck { cond: Operand::Copy(is_ok), assert_kind: Box::new(assert_kind) }
}
3 changes: 3 additions & 0 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
mir::AssertKind::NullPointerDereference => {
push_mono_lang_item(self, LangItem::PanicNullPointerDereference);
}
mir::AssertKind::NullReferenceConstructed => {
push_mono_lang_item(self, LangItem::PanicNullReferenceConstructed);
}
mir::AssertKind::InvalidEnumConstruction(_) => {
push_mono_lang_item(self, LangItem::PanicInvalidEnumConstruction);
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_public/src/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ pub enum AssertMessage {
ResumedAfterDrop(CoroutineKind),
MisalignedPointerDereference { required: Operand, found: Operand },
NullPointerDereference,
NullReferenceConstructed,
InvalidEnumConstruction(Operand),
}

Expand Down Expand Up @@ -342,6 +343,7 @@ impl AssertMessage {
Ok("misaligned pointer dereference")
}
AssertMessage::NullPointerDereference => Ok("null pointer dereference occurred"),
AssertMessage::NullReferenceConstructed => Ok("null reference produced"),
AssertMessage::InvalidEnumConstruction(_) => {
Ok("trying to construct an enum from an invalid value")
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_public/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::R
AssertMessage::NullPointerDereference => {
write!(writer, "\"null pointer dereference occurred\"")
}
AssertMessage::NullReferenceConstructed => {
write!(writer, "\"null reference produced\"")
}
AssertMessage::InvalidEnumConstruction(op) => {
let pretty_op = pretty_operand(op);
write!(writer, "\"trying to construct an enum from an invalid value {{}}\",{pretty_op}")
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_public/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ macro_rules! make_mir_visitor {
AssertMessage::ResumedAfterReturn(_)
| AssertMessage::ResumedAfterPanic(_)
| AssertMessage::NullPointerDereference
| AssertMessage::NullReferenceConstructed
| AssertMessage::ResumedAfterDrop(_) => {
//nothing to visit
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_public/src/unstable/convert/stable/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,9 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
}
}
AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference,
AssertKind::NullReferenceConstructed => {
crate::mir::AssertMessage::NullReferenceConstructed
}
AssertKind::InvalidEnumConstruction(source) => {
crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx))
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,7 @@ symbols! {
panic_misaligned_pointer_dereference,
panic_nounwind,
panic_null_pointer_dereference,
panic_null_reference_constructed,
panic_runtime,
panic_str_2015,
panic_unwind,
Expand Down
13 changes: 13 additions & 0 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ fn panic_null_pointer_dereference() -> ! {
)
}

#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
#[cfg_attr(panic = "immediate-abort", inline)]
#[track_caller]
#[lang = "panic_null_reference_constructed"] // needed by codegen for panic on null reference formation
#[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind
fn panic_null_reference_constructed() -> ! {
if cfg!(panic = "immediate-abort") {
super::intrinsics::abort()
}

panic_nounwind_fmt(format_args!("null reference produced"), /* force_no_backtrace */ false)
}

#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
#[cfg_attr(panic = "immediate-abort", inline)]
#[track_caller]
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/mir/null/borrowed_mut_null.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
//@ error-pattern: null reference produced

fn main() {
let ptr: *mut u32 = std::ptr::null_mut();
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/mir/null/borrowed_null.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
//@ error-pattern: null reference produced

fn main() {
let ptr: *const u32 = std::ptr::null();
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/mir/null/borrowed_null_zst.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
//@ error-pattern: null reference produced

fn main() {
let ptr: *const () = std::ptr::null();
Expand Down
Loading