Skip to content

Commit

Permalink
Put checks that detect UB under their own flag below debug_assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Apr 3, 2024
1 parent c7491b9 commit 294d980
Show file tree
Hide file tree
Showing 25 changed files with 50 additions and 22 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ fn codegen_stmt<'tcx>(
layout.offset_of_subfield(fx, fields.iter()).bytes()
}
NullOp::UbChecks => {
let val = fx.tcx.sess.opts.debug_assertions;
let val = fx.tcx.sess.ub_checks();
let val = CValue::by_val(
fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()),
fx.layout_of(fx.tcx.types.bool),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.cx().const_usize(val)
}
mir::NullOp::UbChecks => {
let val = bx.tcx().sess.opts.debug_assertions;
let val = bx.tcx().sess.ub_checks();
bx.cx().const_bool(val)
}
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(trap_unreachable, Some(false));
tracked!(treat_err_as_bug, NonZero::new(1));
tracked!(tune_cpu, Some(String::from("abc")));
tracked!(ub_checks, Some(false));
tracked!(uninit_const_chunk_threshold, 123);
tracked!(unleash_the_miri_inside_of_you, true);
tracked!(use_ctors_section, Some(true));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/check_alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment {
if sess.target.llvm_target == "i686-pc-windows-msvc" {
return false;
}
sess.opts.debug_assertions
sess.ub_checks()
}

fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/instsimplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {

fn simplify_ub_check(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue {
let const_ = Const::from_bool(self.tcx, self.tcx.sess.opts.debug_assertions);
let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,9 @@ written to standard error output)"),
"in diagnostics, use heuristics to shorten paths referring to items"),
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select processor to schedule for (`rustc --print target-cpus` for details)"),
#[rustc_lint_opt_deny_field_access("use `Session::ub_checks` instead of this field")]
ub_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"emit runtime checks for Undefined Behavior (default: -Cdebug-assertions)"),
ui_testing: bool = (false, parse_bool, [UNTRACKED],
"emit compiler diagnostics in a form suitable for UI testing (default: no)"),
uninit_const_chunk_threshold: usize = (16, parse_number, [TRACKED],
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,10 @@ impl Session {
self.opts.cg.overflow_checks.unwrap_or(self.opts.debug_assertions)
}

pub fn ub_checks(&self) -> bool {
self.opts.unstable_opts.ub_checks.unwrap_or(self.opts.debug_assertions)
}

pub fn relocation_model(&self) -> RelocModel {
self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
"-Zmir-emit-retag",
"-Zmir-keep-place-mention",
"-Zmir-opt-level=0",
"-Zmir-enable-passes=-CheckAlignment",
"-Zub-checks=no",
// Deduplicating diagnostics means we miss events when tracking what happens during an
// execution. Let's not do that.
"-Zdeduplicate-diagnostics=no",
Expand Down
1 change: 0 additions & 1 deletion src/tools/miri/tests/fail/unaligned_pointers/alignment.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@compile-flags: -Cdebug-assertions=no

fn main() {
// No retry needed, this fails reliably.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@compile-flags: -Zmiri-symbolic-alignment-check -Cdebug-assertions=no
//@compile-flags: -Zmiri-symbolic-alignment-check
#![feature(core_intrinsics)]

fn main() {
Expand Down
2 changes: 0 additions & 2 deletions src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//@compile-flags: -Cdebug-assertions=no

#[repr(transparent)]
struct HasDrop(u8);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// should find the bug even without, but gets masked by optimizations
//@compile-flags: -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-stacked-borrows
//@normalize-stderr-test: "but found [0-9]+" -> "but found $$ALIGN"

#[repr(align(256))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance -Cdebug-assertions=no
//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance
// With the symbolic alignment check, even with intptrcast and without
// validation, we want to be *sure* to catch bugs that arise from pointers being
// insufficiently aligned. The only way to achieve that is not to let programs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without SB
//@compile-flags: -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-stacked-borrows

#![allow(dead_code, unused_variables)]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows

fn main() {
// Try many times as this might work by chance.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows

fn main() {
// No retry needed, this fails reliably.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows

fn main() {
// Try many times as this might work by chance.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows

fn main() {
// Make sure we notice when a u16 is loaded at offset 1 into a u8 allocation.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without validation
//@compile-flags: -Zmiri-disable-validation -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-validation

fn main() {
// Try many times as this might work by chance.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This should fail even without Stacked Borrows.
//@compile-flags: -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-stacked-borrows

#![allow(invalid_reference_casting)] // for u16 -> u32

Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/disable-alignment-check.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=no
//@compile-flags: -Zmiri-disable-alignment-check

fn main() {
let mut x = [0u8; 20];
Expand Down
23 changes: 23 additions & 0 deletions tests/codegen/ub-checks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// With -Zub-checks=yes (enabled by default by -Cdebug-assertions=yes) we will produce a runtime
// check that the index to slice::get_unchecked is in-bounds of the slice. That is tested for by
// tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
//
// This test ensures that such a runtime check is *not* emitted when debug-assertions are enabled,
// but ub-checks are explicitly disabled.

//@ compile-flags: -O -Cdebug-assertions=yes -Zub-checks=no

#![crate_type = "lib"]

use std::ops::Range;

// CHECK-LABEL: @slice_get_unchecked(
#[no_mangle]
pub unsafe fn slice_get_unchecked(x: &[i32], i: usize) -> &i32 {
// CHECK-NEXT: start:
// CHECK-NEXT: icmp ult
// CHECK-NEXT: tail call void @llvm.assume
// CHECK-NEXT: getelementptr inbounds
// CHECK-NEXT: ret ptr
x.get_unchecked(i)
}
2 changes: 1 addition & 1 deletion tests/ui/precondition-checks/misaligned-slice.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ run-fail
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
//@ ignore-debug

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/precondition-checks/null-slice.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ run-fail
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
//@ ignore-debug

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ run-fail
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: slice::get_unchecked requires
//@ ignore-debug

Expand Down

0 comments on commit 294d980

Please sign in to comment.