From 92e75c0f88a5cc09642285fe61a4c1be14fe314d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2019 13:57:46 +0200 Subject: [PATCH] factor wide ptr metadata checking into separate method also fat -> wide --- src/librustc_mir/interpret/validity.rs | 75 +++++++++++-------- .../consts/const-eval/union-ub-fat-ptr.stderr | 12 +-- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 82d6d7db01c8..f358a21f4af7 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -11,7 +11,7 @@ use std::hash::Hash; use super::{ GlobalAlloc, InterpResult, - OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, + Scalar, OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, }; macro_rules! throw_validation_failure { @@ -250,6 +250,44 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M self.path.truncate(path_len); Ok(()) } + + fn check_wide_ptr_meta( + &mut self, + meta: Option>, + pointee: TyLayout<'tcx>, + ) -> InterpResult<'tcx> { + let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); + match tail.sty { + ty::Dynamic(..) => { + let vtable = meta.unwrap(); + try_validation!( + self.ecx.memory.check_ptr_access( + vtable, + 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align + self.ecx.tcx.data_layout.pointer_align.abi, + ), + "dangling or unaligned vtable pointer in wide pointer or too small vtable", + self.path + ); + try_validation!(self.ecx.read_drop_type_from_vtable(vtable), + "invalid drop fn in vtable", self.path); + try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), + "invalid size or align in vtable", self.path); + // FIXME: More checks for the vtable. + } + ty::Slice(..) | ty::Str => { + try_validation!(meta.unwrap().to_usize(self.ecx), + "non-integer slice length in wide pointer", self.path); + } + ty::Foreign(..) => { + // Unsized, but not wide. + } + _ => + bug!("Unexpected unsized type tail: {:?}", tail), + } + + Ok(()) + } } impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> @@ -353,44 +391,15 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } } _ if ty.is_box() || ty.is_region_ptr() => { - // Handle fat pointers. + // Handle wide pointers. // Check metadata early, for better diagnostics let ptr = try_validation!(value.to_scalar_ptr(), "undefined address in pointer", self.path); let meta = try_validation!(value.to_meta(), - "uninitialized data in fat pointer metadata", self.path); + "uninitialized data in wide pointer metadata", self.path); let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; if layout.is_unsized() { - let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(layout.ty, - self.ecx.param_env); - match tail.sty { - ty::Dynamic(..) => { - let vtable = meta.unwrap(); - try_validation!( - self.ecx.memory.check_ptr_access( - vtable, - 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align - self.ecx.tcx.data_layout.pointer_align.abi, - ), - "dangling or unaligned vtable pointer or too small vtable", - self.path - ); - try_validation!(self.ecx.read_drop_type_from_vtable(vtable), - "invalid drop fn in vtable", self.path); - try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), - "invalid size or align in vtable", self.path); - // FIXME: More checks for the vtable. - } - ty::Slice(..) | ty::Str => { - try_validation!(meta.unwrap().to_usize(self.ecx), - "non-integer slice length in fat pointer", self.path); - } - ty::Foreign(..) => { - // Unsized, but not fat. - } - _ => - bug!("Unexpected unsized type tail: {:?}", tail), - } + self.check_wide_ptr_meta(meta, layout)?; } // Make sure this is dereferencable and all. let (size, align) = self.ecx.size_and_align_of(meta, layout)? diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr index aac32ecc5b74..54c33006d2b1 100644 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr +++ b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:81:1 | LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:84:1 | LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:93:1 | LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:97:1 | LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -50,7 +50,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:100:1 | LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -58,7 +58,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:103:1 | LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior