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.
This commit is contained in:
parent
0f6ba39fd8
commit
cae1918b29
@ -227,7 +227,11 @@ pub enum UndefinedBehaviorInfo<'tcx> {
|
||||
/// Invalid metadata in a wide pointer (using `str` to avoid allocations).
|
||||
InvalidMeta(&'static str),
|
||||
/// Invalid drop function in vtable.
|
||||
InvalidDropFn(FnSig<'tcx>),
|
||||
InvalidVtableDropFn(FnSig<'tcx>),
|
||||
/// Invalid size in a vtable: too large.
|
||||
InvalidVtableSize,
|
||||
/// Invalid alignment in a vtable: too large, or not a power of 2.
|
||||
InvalidVtableAlignment(String),
|
||||
/// Reading a C string that does not end within its allocation.
|
||||
UnterminatedCString(Pointer),
|
||||
/// Dereferencing a dangling pointer after it got freed.
|
||||
@ -287,11 +291,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
|
||||
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
|
||||
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
|
||||
InvalidDropFn(sig) => write!(
|
||||
InvalidVtableDropFn(sig) => write!(
|
||||
f,
|
||||
"invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
|
||||
sig
|
||||
),
|
||||
InvalidVtableSize => {
|
||||
write!(f, "invalid vtable: size is bigger than largest supported object")
|
||||
}
|
||||
InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg),
|
||||
UnterminatedCString(p) => write!(
|
||||
f,
|
||||
"reading a null-terminated string starting at {} with no null found before end of allocation",
|
||||
|
@ -137,9 +137,10 @@ pub fn read_drop_type_from_vtable(
|
||||
// The drop function takes `*mut T` where `T` is the type being dropped, so get that.
|
||||
let args = fn_sig.inputs();
|
||||
if args.len() != 1 {
|
||||
throw_ub!(InvalidDropFn(fn_sig));
|
||||
throw_ub!(InvalidVtableDropFn(fn_sig));
|
||||
}
|
||||
let ty = args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?.ty;
|
||||
let ty =
|
||||
args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidVtableDropFn(fn_sig)))?.ty;
|
||||
Ok((drop_instance, ty))
|
||||
}
|
||||
|
||||
@ -158,14 +159,10 @@ pub fn read_size_and_align_from_vtable(
|
||||
let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
|
||||
let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?;
|
||||
let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
|
||||
let align = Align::from_bytes(align)
|
||||
.map_err(|e| err_ub_format!("invalid vtable: alignment {}", e))?;
|
||||
let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
|
||||
|
||||
if size >= self.tcx.data_layout.obj_size_bound() {
|
||||
throw_ub_format!(
|
||||
"invalid vtable: \
|
||||
size is bigger than largest supported object"
|
||||
);
|
||||
throw_ub!(InvalidVtableSize);
|
||||
}
|
||||
Ok((Size::from_bytes(size), align))
|
||||
}
|
||||
|
@ -349,12 +349,16 @@ fn check_wide_ptr_meta(
|
||||
err_ub!(InvalidFunctionPointer(..)) |
|
||||
err_unsup!(ReadBytesAsPointer) =>
|
||||
{ "invalid drop function pointer in vtable (not pointing to a function)" },
|
||||
err_ub!(InvalidDropFn(..)) =>
|
||||
err_ub!(InvalidVtableDropFn(..)) =>
|
||||
{ "invalid drop function pointer in vtable (function has incompatible signature)" },
|
||||
);
|
||||
try_validation!(
|
||||
self.ecx.read_size_and_align_from_vtable(vtable),
|
||||
self.path,
|
||||
err_ub!(InvalidVtableSize) =>
|
||||
{ "invalid vtable: size is bigger than largest supported object" },
|
||||
err_ub!(InvalidVtableAlignment(msg)) =>
|
||||
{ "invalid vtable: alignment {}", msg },
|
||||
err_unsup!(ReadPointerAsBytes) => { "invalid size or align in vtable" },
|
||||
);
|
||||
// FIXME: More checks for the vtable.
|
||||
|
Loading…
Reference in New Issue
Block a user