Skip to content

Commit

Permalink
Auto merge of rust-lang#86194 - RalfJung:const-ub-hard-error, r=oli-obk
Browse files Browse the repository at this point in the history
make UB during CTFE a hard error

This is a next step for rust-lang#71800. `const_err` has been a future-incompatibility lint for 4 months now since rust-lang#80394 (and err-by-default for many years before that), so I think we could try making it a proper hard error at least in some situations.

I didn't yet adjust the tests, since I first want to gauge the fall-out via crater.
Cc `@rust-lang/wg-const-eval`
  • Loading branch information
bors committed Jun 18, 2021
2 parents ce1d561 + 7475661 commit ec57c60
Show file tree
Hide file tree
Showing 25 changed files with 336 additions and 859 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ impl InterpError<'_> {
use InterpError::*;
match *self {
MachineStop(ref err) => err.is_hard_err(),
InterpError::UndefinedBehavior(_) => true,
_ => false,
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/consts/const-eval/dangling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ use std::mem;
// Make sure we error with the right kind of error on a too large slice.
const TEST: () = { unsafe {
let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
let _val = &*slice; //~ ERROR: any use of this value will cause an error
let _val = &*slice; //~ ERROR: evaluation of constant value failed
//~| slice is bigger than largest supported object
//~| WARN this was previously accepted by the compiler but is being phased out
} };

fn main() {}
17 changes: 4 additions & 13 deletions src/test/ui/consts/const-eval/dangling.stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/dangling.rs:8:16
|
LL | / const TEST: () = { unsafe {
LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
LL | | let _val = &*slice;
| | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
LL | |
LL | |
LL | | } };
| |____-
|
= 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>
LL | let _val = &*slice;
| ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object

error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.
3 changes: 1 addition & 2 deletions src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ const FOO: i32 = foo();
const fn foo() -> i32 {
unsafe {
let _ = intrinsics::const_allocate(4, 3) as * mut i32;
//~^ error: any use of this value will cause an error [const_err]
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ error: evaluation of constant value failed
}
1

Expand Down
10 changes: 3 additions & 7 deletions src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/alloc_intrinsic_errors.rs:10:17
|
LL | const FOO: i32 = foo();
| -----------------------
| ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
...
LL | let _ = intrinsics::const_allocate(4, 3) as * mut i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| align has to be a power of 2, `3` is not a power of 2
| inside `foo` at $DIR/alloc_intrinsic_errors.rs:10:17
| inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
|
= 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 previous error

For more information about this error, try `rustc --explain E0080`.
3 changes: 1 addition & 2 deletions src/test/ui/consts/const-eval/issue-49296.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ const fn wat(x: u64) -> &'static u64 {
unsafe { transmute(&x) }
}
const X: u64 = *wat(42);
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR evaluation of constant value failed

fn main() {
println!("{}", X);
Expand Down
11 changes: 3 additions & 8 deletions src/test/ui/consts/const-eval/issue-49296.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/issue-49296.rs:19:16
|
LL | const X: u64 = *wat(42);
| ---------------^^^^^^^^-
| |
| pointer to alloc1 was dereferenced after this allocation got freed
|
= 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>
| ^^^^^^^^ pointer to alloc1 was dereferenced after this allocation got freed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.
31 changes: 9 additions & 22 deletions src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/ub-incorrect-vtable.rs:19:14
|
LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
| |
| invalid vtable: alignment `1000` is not a power of 2
|
= 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>
LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2

error: any use of this value will cause an error
--> $DIR/ub-incorrect-vtable.rs:25:14
|
LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
| |
| invalid vtable: size is bigger than largest supported object
error[E0080]: evaluation of constant value failed
--> $DIR/ub-incorrect-vtable.rs:24:14
|
= 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>
LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-incorrect-vtable.rs:36:1
--> $DIR/ub-incorrect-vtable.rs:34:1
|
LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
Expand All @@ -36,7 +23,7 @@ LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1us
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-incorrect-vtable.rs:41:1
--> $DIR/ub-incorrect-vtable.rs:39:1
|
LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
Expand Down
31 changes: 9 additions & 22 deletions src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/ub-incorrect-vtable.rs:19:14
|
LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
| |
| invalid vtable: alignment `1000` is not a power of 2
|
= 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>
LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2

error: any use of this value will cause an error
--> $DIR/ub-incorrect-vtable.rs:25:14
|
LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
| |
| invalid vtable: size is bigger than largest supported object
error[E0080]: evaluation of constant value failed
--> $DIR/ub-incorrect-vtable.rs:24:14
|
= 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>
LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-incorrect-vtable.rs:36:1
--> $DIR/ub-incorrect-vtable.rs:34:1
|
LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
Expand All @@ -36,7 +23,7 @@ LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1us
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-incorrect-vtable.rs:41:1
--> $DIR/ub-incorrect-vtable.rs:39:1
|
LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ trait Trait {}

const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
//~^ ERROR any use of this value will cause an error
//~| WARNING this was previously accepted by the compiler
//~^ ERROR evaluation of constant value failed
//~| invalid vtable: alignment `1000` is not a power of 2

const INVALID_VTABLE_SIZE: &dyn Trait =
unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
//~^ ERROR any use of this value will cause an error
//~| WARNING this was previously accepted by the compiler
//~^ ERROR evaluation of constant value failed
//~| invalid vtable: size is bigger than largest supported object

#[repr(transparent)]
Expand Down
31 changes: 8 additions & 23 deletions src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
00 00 00 00 │ ....
}

error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/ub-nonnull.rs:19:30
|
LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to null!
LL | | let out_of_bounds_ptr = &ptr[255];
| | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
LL | |
LL | | mem::transmute(out_of_bounds_ptr)
LL | | } };
| |____-
|
note: the lint level is defined here
--> $DIR/ub-nonnull.rs:15:8
|
LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
| ^^^^^^^^^
= 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>
LL | let out_of_bounds_ptr = &ptr[255];
| ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:24:1
--> $DIR/ub-nonnull.rs:23:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
Expand All @@ -42,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:26:1
--> $DIR/ub-nonnull.rs:25:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
Expand All @@ -53,7 +38,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:34:1
--> $DIR/ub-nonnull.rs:33:1
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
Expand All @@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:42:1
--> $DIR/ub-nonnull.rs:41:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
Expand All @@ -75,7 +60,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:48:1
--> $DIR/ub-nonnull.rs:47:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
Expand Down
31 changes: 8 additions & 23 deletions src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
00 00 00 00 00 00 00 00 │ ........
}

error: any use of this value will cause an error
error[E0080]: evaluation of constant value failed
--> $DIR/ub-nonnull.rs:19:30
|
LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to null!
LL | | let out_of_bounds_ptr = &ptr[255];
| | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
LL | |
LL | | mem::transmute(out_of_bounds_ptr)
LL | | } };
| |____-
|
note: the lint level is defined here
--> $DIR/ub-nonnull.rs:15:8
|
LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
| ^^^^^^^^^
= 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>
LL | let out_of_bounds_ptr = &ptr[255];
| ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:24:1
--> $DIR/ub-nonnull.rs:23:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
Expand All @@ -42,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:26:1
--> $DIR/ub-nonnull.rs:25:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
Expand All @@ -53,7 +38,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:34:1
--> $DIR/ub-nonnull.rs:33:1
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
Expand All @@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:42:1
--> $DIR/ub-nonnull.rs:41:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
Expand All @@ -75,7 +60,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:48:1
--> $DIR/ub-nonnull.rs:47:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/consts/const-eval/ub-nonnull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
// Use address-of-element for pointer arithmetic. This could wrap around to null!
let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed
mem::transmute(out_of_bounds_ptr)
} };

Expand Down
Loading

0 comments on commit ec57c60

Please sign in to comment.