diff options
| author | bors <bors@rust-lang.org> | 2021-06-13 12:08:59 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-06-13 12:08:59 +0000 |
| commit | fb3ea63d9b4c3e9bb90d4250b870faaffb9c8fd2 (patch) | |
| tree | 94675917e0edd783192d018e3d0250e537f47d8a /compiler | |
| parent | 6cc5d5432aaed21630ead1fa59418245ee2e1047 (diff) | |
| parent | e29f3e837fb6262040d42d4cde8e2f775dee0fe7 (diff) | |
| download | rust-fb3ea63d9b4c3e9bb90d4250b870faaffb9c8fd2.tar.gz rust-fb3ea63d9b4c3e9bb90d4250b870faaffb9c8fd2.zip | |
Auto merge of #86245 - lqd:const-ub-align, r=RalfJung
Fix ICEs on invalid vtable size/alignment const UB errors The invalid vtable size/alignment errors from `InterpCx::read_size_and_align_from_vtable` were "freeform const UB errors", causing ICEs when reaching validation. This PR turns them into const UB hard errors to catch them during validation and avoid that. Fixes #86193 r? `@RalfJung` (It seemed cleaner to have 2 variants but they can be merged into one variant with a message payload if you prefer that ?)
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/error.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/traits.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/validity.rs | 6 |
3 files changed, 20 insertions, 11 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 65d9c1dd90e..aca39d438c1 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -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 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { 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", diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs index d0c04b5b414..9a59161f08f 100644 --- a/compiler/rustc_mir/src/interpret/traits.rs +++ b/compiler/rustc_mir/src/interpret/traits.rs @@ -137,9 +137,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // 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 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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)) } diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs index fb165a991bc..c9ebffe8d1c 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_mir/src/interpret/validity.rs @@ -349,12 +349,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' 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. |
