From 5ee4fdcd15cc404f6d195027b11c24bdb0905204 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 23 Jun 2017 13:31:00 +0200 Subject: [PATCH] fetch_tls_dtor "read" an `Undef` as nonzero --- src/eval_context.rs | 6 +++++- src/memory.rs | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/eval_context.rs b/src/eval_context.rs index 0a2bce922df5..7052a411f7e2 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -362,7 +362,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { StackPopCleanup::None => {}, StackPopCleanup::Tls(key) => { // either fetch the next dtor or start new from the beginning, if any are left with a non-null data - if let Some((instance, ptr, key)) = self.memory.fetch_tls_dtor(key).or_else(|| self.memory.fetch_tls_dtor(None)) { + let dtor = match self.memory.fetch_tls_dtor(key)? { + dtor @ Some(_) => dtor, + None => self.memory.fetch_tls_dtor(None)?, + }; + if let Some((instance, ptr, key)) = dtor { trace!("Running TLS dtor {:?} on {:?}", instance, ptr); // TODO: Potentially, this has to support all the other possible instances? See eval_fn_call in terminator/mod.rs let mir = self.load_mir(instance.def)?; diff --git a/src/memory.rs b/src/memory.rs index e34737f464de..5794dc783cfe 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -404,22 +404,22 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { /// with associated destructors, implementations may stop calling destructors, /// or they may continue calling destructors until no non-NULL values with /// associated destructors exist, even though this might result in an infinite loop. - pub(crate) fn fetch_tls_dtor(&mut self, key: Option) -> Option<(ty::Instance<'tcx>, PrimVal, TlsKey)> { + pub(crate) fn fetch_tls_dtor(&mut self, key: Option) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, PrimVal, TlsKey)>> { use std::collections::Bound::*; let start = match key { Some(key) => Excluded(key), None => Unbounded, }; for (&key, &mut TlsEntry { ref mut data, dtor }) in self.thread_local.range_mut((start, Unbounded)) { - if *data != PrimVal::Bytes(0) { + if !data.is_null()? { if let Some(dtor) = dtor { let ret = Some((dtor, *data, key)); *data = PrimVal::Bytes(0); - return ret; + return Ok(ret); } } } - return None; + return Ok(None); } }