From 1f9153fac3ed5678c45baae77a306fff3f753d57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 13 Jul 2017 17:25:38 -0700 Subject: [PATCH] validate TyClosure, TyTuple, TyNever --- src/librustc_mir/interpret/error.rs | 6 ++++++ src/librustc_mir/interpret/lvalue.rs | 18 ++++++++++++++++++ src/librustc_mir/interpret/step.rs | 4 ++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/error.rs b/src/librustc_mir/interpret/error.rs index dde64a46ff07..f84e4a3b1b21 100644 --- a/src/librustc_mir/interpret/error.rs +++ b/src/librustc_mir/interpret/error.rs @@ -57,6 +57,7 @@ pub enum EvalError<'tcx> { access: AccessKind, lock: LockInfo, }, + ValidationFailure(String), InvalidMemoryLockRelease { ptr: MemoryPointer, len: u64, @@ -110,6 +111,8 @@ impl<'tcx> Error for EvalError<'tcx> { "invalid use of NULL pointer", MemoryLockViolation { .. } => "memory access conflicts with lock", + ValidationFailure(..) => + "type validation failed", DeallocatedLockedMemory => "deallocated memory while a lock was held", InvalidMemoryLockRelease { .. } => @@ -221,6 +224,9 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "tried to release memory write lock at {:?}, size {}, which was not acquired by this function", ptr, len) } + ValidationFailure(ref err) => { + write!(f, "type validation failed: {}", err) + } NoMirFor(ref func) => write!(f, "no mir for `{}`", func), FunctionPointerTyMismatch(sig, got) => write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got), diff --git a/src/librustc_mir/interpret/lvalue.rs b/src/librustc_mir/interpret/lvalue.rs index c0976e9ded97..3f39d1c25c05 100644 --- a/src/librustc_mir/interpret/lvalue.rs +++ b/src/librustc_mir/interpret/lvalue.rs @@ -539,6 +539,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // TODO: Check if these are valid bool/float/UTF-8, respectively (and in particular, not undef). Ok(()) } + TyNever => { + Err(EvalError::ValidationFailure(format!("The empty type is never valid."))) + } TyRef(region, ty::TypeAndMut { ty: pointee_ty, mutbl }) => { let val = self.read_lvalue(lvalue)?; // Sharing restricts our context @@ -617,6 +620,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } } + TyTuple(ref types, _) => { + for (idx, field_ty) in types.iter().enumerate() { + let field_lvalue = self.lvalue_field(lvalue, idx, ty, field_ty)?; + self.validate(field_lvalue, field_ty, vctx)?; + } + Ok(()) + } + TyClosure(def_id, ref closure_substs) => { + for (idx, field_ty) in closure_substs.upvar_tys(def_id, self.tcx).enumerate() { + let field_lvalue = self.lvalue_field(lvalue, idx, ty, field_ty)?; + self.validate(field_lvalue, field_ty, vctx)?; + } + Ok(()) + } + TyParam(_) | TyInfer(_) => bug!("I got an incomplete type for validation"), _ => unimplemented!("Unimplemented type encountered when checking validity.") } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 4f7eb8eb6cc1..33651e733e6b 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -132,13 +132,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } // Validity checks. - Validate(ref op, ref lvalues) => { + Validate(op, ref lvalues) => { for operand in lvalues { // We need to monomorphize ty *without* erasing lifetimes let ty = operand.ty.subst(self.tcx, self.substs()); // TODO: do we have to self.tcx.normalize_associated_type(&{ty}) ? That however seems to erase lifetimes. let lvalue = self.eval_lvalue(&operand.lval)?; - self.validate(lvalue, ty, ValidationCtx::new(*op))?; + self.validate(lvalue, ty, ValidationCtx::new(op))?; } } EndRegion(ce) => {