Skip to content

Commit 441419a

Browse files
committed
properly catch invalid-drop-fn errors
1 parent 19bd72e commit 441419a

File tree

4 files changed

+16
-14
lines changed

4 files changed

+16
-14
lines changed

src/librustc_middle/mir/interpret/error.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ use super::{AllocId, Pointer, RawConst, ScalarMaybeUndef};
33
use crate::mir::interpret::ConstValue;
44
use crate::ty::layout::LayoutError;
55
use crate::ty::query::TyCtxtAt;
6-
use crate::ty::tls;
7-
use crate::ty::{self, layout, Ty};
6+
use crate::ty::{self, layout, tls, FnSig, Ty};
87

98
use rustc_data_structures::sync::Lock;
109
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
@@ -329,7 +328,7 @@ impl fmt::Display for CheckInAllocMsg {
329328
}
330329

331330
/// Error information for when the program caused Undefined Behavior.
332-
pub enum UndefinedBehaviorInfo {
331+
pub enum UndefinedBehaviorInfo<'tcx> {
333332
/// Free-form case. Only for errors that are never caught!
334333
Ub(String),
335334
/// Unreachable code was executed.
@@ -347,6 +346,8 @@ pub enum UndefinedBehaviorInfo {
347346
PointerArithOverflow,
348347
/// Invalid metadata in a wide pointer (using `str` to avoid allocations).
349348
InvalidMeta(&'static str),
349+
/// Invalid drop function in vtable.
350+
InvalidDropFn(FnSig<'tcx>),
350351
/// Reading a C string that does not end within its allocation.
351352
UnterminatedCString(Pointer),
352353
/// Dereferencing a dangling pointer after it got freed.
@@ -393,7 +394,7 @@ pub enum UndefinedBehaviorInfo {
393394
},
394395
}
395396

396-
impl fmt::Display for UndefinedBehaviorInfo {
397+
impl fmt::Display for UndefinedBehaviorInfo<'_> {
397398
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398399
use UndefinedBehaviorInfo::*;
399400
match self {
@@ -406,6 +407,11 @@ impl fmt::Display for UndefinedBehaviorInfo {
406407
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
407408
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
408409
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
410+
InvalidDropFn(sig) => write!(
411+
f,
412+
"invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
413+
sig
414+
),
409415
UnterminatedCString(p) => write!(
410416
f,
411417
"reading a null-terminated string starting at {} with no null found before end of allocation",
@@ -448,9 +454,7 @@ impl fmt::Display for UndefinedBehaviorInfo {
448454
InvalidFunctionPointer(p) => {
449455
write!(f, "using {} as function pointer but it does not point to a function", p)
450456
}
451-
InvalidStr(err) => {
452-
write!(f, "this string is not valid UTF-8: {}", err)
453-
}
457+
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
454458
InvalidUndefBytes(Some(p)) => write!(
455459
f,
456460
"reading uninitialized memory at {}, but this operation requires initialized memory",
@@ -554,7 +558,7 @@ impl dyn MachineStopType {
554558

555559
pub enum InterpError<'tcx> {
556560
/// The program caused undefined behavior.
557-
UndefinedBehavior(UndefinedBehaviorInfo),
561+
UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
558562
/// The program did something the interpreter does not support (some of these *might* be UB
559563
/// but the interpreter is not sure).
560564
Unsupported(UnsupportedOpInfo),

src/librustc_mir/interpret/operand.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
327327
pub fn read_str(&self, mplace: MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> {
328328
let len = mplace.len(self)?;
329329
let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len))?;
330-
let str = ::std::str::from_utf8(bytes)
331-
.map_err(|err| err_ub!(InvalidStr(err)))?;
330+
let str = ::std::str::from_utf8(bytes).map_err(|err| err_ub!(InvalidStr(err)))?;
332331
Ok(str)
333332
}
334333

src/librustc_mir/interpret/traits.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
147147
// The drop function takes `*mut T` where `T` is the type being dropped, so get that.
148148
let args = fn_sig.inputs();
149149
if args.len() != 1 {
150-
throw_ub_format!("drop fn should have 1 argument, but signature is {:?}", fn_sig);
150+
throw_ub!(InvalidDropFn(fn_sig));
151151
}
152152
let ty = args[0]
153153
.builtin_deref(true)
154-
.ok_or_else(|| {
155-
err_ub_format!("drop fn argument type {} is not a pointer type", args[0])
156-
})?
154+
.ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?
157155
.ty;
158156
Ok((drop_instance, ty))
159157
}

src/librustc_mir/interpret/validity.rs

+1
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
313313
try_validation!(
314314
self.ecx.read_drop_type_from_vtable(vtable),
315315
self.path,
316+
err_ub!(InvalidDropFn(..)) |
316317
err_ub!(DanglingIntPointer(..)) |
317318
err_ub!(InvalidFunctionPointer(..)) |
318319
err_unsup!(ReadBytesAsPointer) =>

0 commit comments

Comments
 (0)