Skip to content

Commit cae1918

Browse files
committed
Turn incorrect vtable size/alignment errors into hard const-UB errors
They were "freeform const UB" error message, but could reach validation and trigger ICEs there. We now catch them during validation to avoid that.
1 parent 0f6ba39 commit cae1918

File tree

3 files changed

+20
-11
lines changed

3 files changed

+20
-11
lines changed

compiler/rustc_middle/src/mir/interpret/error.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ pub enum UndefinedBehaviorInfo<'tcx> {
227227
/// Invalid metadata in a wide pointer (using `str` to avoid allocations).
228228
InvalidMeta(&'static str),
229229
/// Invalid drop function in vtable.
230-
InvalidDropFn(FnSig<'tcx>),
230+
InvalidVtableDropFn(FnSig<'tcx>),
231+
/// Invalid size in a vtable: too large.
232+
InvalidVtableSize,
233+
/// Invalid alignment in a vtable: too large, or not a power of 2.
234+
InvalidVtableAlignment(String),
231235
/// Reading a C string that does not end within its allocation.
232236
UnterminatedCString(Pointer),
233237
/// Dereferencing a dangling pointer after it got freed.
@@ -287,11 +291,15 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
287291
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
288292
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
289293
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
290-
InvalidDropFn(sig) => write!(
294+
InvalidVtableDropFn(sig) => write!(
291295
f,
292296
"invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
293297
sig
294298
),
299+
InvalidVtableSize => {
300+
write!(f, "invalid vtable: size is bigger than largest supported object")
301+
}
302+
InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg),
295303
UnterminatedCString(p) => write!(
296304
f,
297305
"reading a null-terminated string starting at {} with no null found before end of allocation",

compiler/rustc_mir/src/interpret/traits.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
137137
// The drop function takes `*mut T` where `T` is the type being dropped, so get that.
138138
let args = fn_sig.inputs();
139139
if args.len() != 1 {
140-
throw_ub!(InvalidDropFn(fn_sig));
140+
throw_ub!(InvalidVtableDropFn(fn_sig));
141141
}
142-
let ty = args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?.ty;
142+
let ty =
143+
args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidVtableDropFn(fn_sig)))?.ty;
143144
Ok((drop_instance, ty))
144145
}
145146

@@ -158,14 +159,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
158159
let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
159160
let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?;
160161
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))?;
162+
let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
163163

164164
if size >= self.tcx.data_layout.obj_size_bound() {
165-
throw_ub_format!(
166-
"invalid vtable: \
167-
size is bigger than largest supported object"
168-
);
165+
throw_ub!(InvalidVtableSize);
169166
}
170167
Ok((Size::from_bytes(size), align))
171168
}

compiler/rustc_mir/src/interpret/validity.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
349349
err_ub!(InvalidFunctionPointer(..)) |
350350
err_unsup!(ReadBytesAsPointer) =>
351351
{ "invalid drop function pointer in vtable (not pointing to a function)" },
352-
err_ub!(InvalidDropFn(..)) =>
352+
err_ub!(InvalidVtableDropFn(..)) =>
353353
{ "invalid drop function pointer in vtable (function has incompatible signature)" },
354354
);
355355
try_validation!(
356356
self.ecx.read_size_and_align_from_vtable(vtable),
357357
self.path,
358+
err_ub!(InvalidVtableSize) =>
359+
{ "invalid vtable: size is bigger than largest supported object" },
360+
err_ub!(InvalidVtableAlignment(msg)) =>
361+
{ "invalid vtable: alignment {}", msg },
358362
err_unsup!(ReadPointerAsBytes) => { "invalid size or align in vtable" },
359363
);
360364
// FIXME: More checks for the vtable.

0 commit comments

Comments
 (0)