Skip to content

Commit 91faabb

Browse files
authored
Rollup merge of #86174 - lqd:const-ub-align, r=RalfJung
Detect incorrect vtable alignment during const eval This PR fixes #86132 by detecting invalid alignment values for trait objects in the interpreter, and emitting an error about this conversion failure, to avoid the ICE. I've noticed that the error emitted at https://github.com/rust-lang/rust/blob/a50d72158e08e02cfc051b863017bdbd2c45b637/compiler/rustc_mir/src/interpret/traits.rs#L163-L166 doesn't seem to be present in the const-ub tests, so I've tried adding a test that triggers both of these cases: one for the invalid size, and another for the invalid alignment that #86132 tracks (I have found different magic values triggering different `Align::from_bytes` errors than the "power of 2" one, if need be). However, when doing that, I *cannot* for the life of me figure out the correct incantation to make these 2 errors trigger with the "it is undefined behavior to use this value" message rather than the "any use of this value will cause an error" lint. I've tried Oli's suggestions of different values, tuples and arrays, using the transparent wrapper trick from the other tests and I was only able to trigger the regular const-ub errors about the size of the vtable, or that the drop pointer was invalid. Maybe these "type validation failed" errors happen before this part of the interpreter is reached and there just needs some magic incorrect values to bypass them, I don't know. Since this fixes an ICE, and if the constants are indeed used, these 2 tests will turn into a hard error, I thought I'd open the PR anyways. And if ```@RalfJung``` you know of a way I could manage that (if you think that these tests are worth checking that the `throw_ub_format!` does indeed create const-ub errors as we expect) I'd be grateful. For that reason, r? ```@RalfJung``` and cc ```@oli-obk.```
2 parents 79c0559 + d449903 commit 91faabb

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

compiler/rustc_mir/src/interpret/traits.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
158158
let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
159159
let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?;
160160
let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
161+
let align = Align::from_bytes(align)
162+
.map_err(|e| err_ub_format!("invalid vtable: alignment {}", e))?;
161163

162164
if size >= self.tcx.data_layout.obj_size_bound() {
163165
throw_ub_format!(
164166
"invalid vtable: \
165167
size is bigger than largest supported object"
166168
);
167169
}
168-
Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
170+
Ok((Size::from_bytes(size), align))
169171
}
170172
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// This test contains code with incorrect vtables in a const context:
2+
// - from issue 86132: a trait object with invalid alignment caused an ICE in const eval, and now
3+
// triggers an error
4+
// - a similar test that triggers a previously-untested const UB error: emitted close to the above
5+
// error, it checks the correctness of the size
6+
7+
trait Trait {}
8+
9+
const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
10+
unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
11+
//~^ ERROR any use of this value will cause an error
12+
//~| WARNING this was previously accepted by the compiler
13+
//~| invalid vtable: alignment `1000` is not a power of 2
14+
15+
const INVALID_VTABLE_SIZE: &dyn Trait =
16+
unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
17+
//~^ ERROR any use of this value will cause an error
18+
//~| WARNING this was previously accepted by the compiler
19+
//~| invalid vtable: size is bigger than largest supported object
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: any use of this value will cause an error
2+
--> $DIR/ub-incorrect-vtable.rs:10:14
3+
|
4+
LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
5+
LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
6+
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
7+
| |
8+
| invalid vtable: alignment `1000` is not a power of 2
9+
|
10+
= note: `#[deny(const_err)]` on by default
11+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
12+
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
13+
14+
error: any use of this value will cause an error
15+
--> $DIR/ub-incorrect-vtable.rs:16:14
16+
|
17+
LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
18+
LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
19+
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
20+
| |
21+
| invalid vtable: size is bigger than largest supported object
22+
|
23+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
24+
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
25+
26+
error: aborting due to 2 previous errors
27+

0 commit comments

Comments
 (0)