add -Zextra-const-ub-checks to enable more UB checking in const-eval
This commit is contained in:
parent
cc71eef498
commit
be6bb56ee0
@ -236,6 +236,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
|
||||
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
|
||||
}
|
||||
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
|
@ -1005,6 +1005,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
/// It will error if the bits at the destination do not match the ones described by the layout.
|
||||
#[inline(always)]
|
||||
pub fn validate_operand(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
|
||||
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
|
||||
// still correct to not use `ctfe_mode`: that mode is for validation of the final constant
|
||||
// value, it rules out things like `UnsafeCell` in awkward places. It also can make checking
|
||||
// recurse through references which, for now, we don't want here, either.
|
||||
self.validate_operand_internal(op, vec![], None, None)
|
||||
}
|
||||
}
|
||||
|
@ -1310,6 +1310,8 @@ options! {
|
||||
"emit the bc module with thin LTO info (default: yes)"),
|
||||
export_executable_symbols: bool = (false, parse_bool, [TRACKED],
|
||||
"export symbols from executables, as if they were dynamic libraries"),
|
||||
extra_const_ub_checks: bool = (false, parse_bool, [TRACKED],
|
||||
"turns on more checks to detect const UB, which can be slow (default: no)"),
|
||||
#[cfg_attr(not(bootstrap), rustc_lint_opt_deny_field_access("use `Session::fewer_names` instead of this field"))]
|
||||
fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
|
||||
|
@ -38,6 +38,7 @@
|
||||
-Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
|
||||
-Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
|
||||
-Z export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries
|
||||
-Z extra-const-ub-checks=val -- turns on more checks to detect const UB, which can be slow (default: no)
|
||||
-Z fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
|
||||
-Z force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
|
||||
-Z fuel=val -- set the optimization fuel quota for a crate
|
||||
|
43
src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
Normal file
43
src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// compile-flags: -Zextra-const-ub-checks
|
||||
#![feature(const_ptr_read)]
|
||||
|
||||
use std::mem::transmute;
|
||||
|
||||
const INVALID_BOOL: () = unsafe {
|
||||
let _x: bool = transmute(3u8);
|
||||
//~^ ERROR: evaluation of constant value failed
|
||||
//~| invalid value
|
||||
};
|
||||
|
||||
const INVALID_PTR_IN_INT: () = unsafe {
|
||||
let _x: usize = transmute(&3u8);
|
||||
//~^ ERROR: evaluation of constant value failed
|
||||
//~| invalid value
|
||||
};
|
||||
|
||||
const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe {
|
||||
let x: &[u8] = &[0; 32];
|
||||
let _x: (usize, usize) = transmute(x);
|
||||
//~^ ERROR: evaluation of constant value failed
|
||||
//~| invalid value
|
||||
};
|
||||
|
||||
const UNALIGNED_PTR: () = unsafe {
|
||||
let _x: &u32 = transmute(&[0u8; 4]);
|
||||
//~^ ERROR: evaluation of constant value failed
|
||||
//~| invalid value
|
||||
};
|
||||
|
||||
const UNALIGNED_READ: () = {
|
||||
INNER; //~ERROR any use of this value will cause an error
|
||||
//~| previously accepted
|
||||
// There is an error here but its span is in the standard library so we cannot match it...
|
||||
// so we have this in a *nested* const, such that the *outer* const fails to use it.
|
||||
const INNER: () = unsafe {
|
||||
let x = &[0u8; 4];
|
||||
let ptr = x.as_ptr().cast::<u32>();
|
||||
ptr.read();
|
||||
};
|
||||
};
|
||||
|
||||
fn main() {}
|
71
src/test/ui/consts/extra-const-ub/detect-extra-ub.stderr
Normal file
71
src/test/ui/consts/extra-const-ub/detect-extra-ub.stderr
Normal file
@ -0,0 +1,71 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:7:20
|
||||
|
|
||||
LL | let _x: bool = transmute(3u8);
|
||||
| ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:13:21
|
||||
|
|
||||
LL | let _x: usize = transmute(&3u8);
|
||||
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:20:30
|
||||
|
|
||||
LL | let _x: (usize, usize) = transmute(x);
|
||||
| ^^^^^^^^^^^^ constructing invalid value at .0: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:26:20
|
||||
|
|
||||
LL | let _x: &u32 = transmute(&[0u8; 4]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
|
||||
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| accessing memory with alignment 1, but alignment 4 is required
|
||||
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
|
||||
::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
||||
LL | unsafe { read(self) }
|
||||
| ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
||||
::: $DIR/detect-extra-ub.rs:39:9
|
||||
|
|
||||
LL | ptr.read();
|
||||
| ---------- inside `INNER` at $DIR/detect-extra-ub.rs:39:9
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/detect-extra-ub.rs:32:5
|
||||
|
|
||||
LL | const UNALIGNED_READ: () = {
|
||||
| ------------------------
|
||||
LL | INNER;
|
||||
| ^^^^^ referenced constant has errors
|
||||
|
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/detect-extra-ub.rs:32:5
|
||||
|
|
||||
LL | const UNALIGNED_READ: () = {
|
||||
| ------------------------
|
||||
LL | INNER;
|
||||
| ^^^^^ referenced constant has errors
|
||||
|
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||
|
Loading…
x
Reference in New Issue
Block a user