diff --git a/src/eval.rs b/src/eval.rs index 0970edb2b75f..ae57bcf98b96 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -39,7 +39,6 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( Evaluator::new(config.communicate), MemoryExtra::new(StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.validate), ); - // Complete initialization. EnvVars::init(&mut ecx, config.communicate); diff --git a/src/lib.rs b/src/lib.rs index 738419c2498b..cea99d86eaa8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextEx pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt; pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData}; pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt}; -pub use crate::shims::env::EnvVars; +pub use crate::shims::env::{EnvVars, EvalContextExt as EnvEvalContextExt}; pub use crate::operator::EvalContextExt as OperatorEvalContextExt; pub use crate::range_map::RangeMap; pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt}; diff --git a/src/shims/env.rs b/src/shims/env.rs index 05c5fbb04309..c941bf4f50e3 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -22,21 +22,9 @@ impl EnvVars { } } } - - pub(crate) fn get(&self, name: &[u8]) -> Option<&Pointer> { - self.map.get(name) - } - - pub(crate) fn unset(&mut self, name: &[u8]) -> Option> { - self.map.remove(name) - } - - pub(crate) fn set(&mut self, name: Vec, ptr: Pointer) -> Option>{ - self.map.insert(name, ptr) - } } -pub(crate) fn alloc_env_value<'mir, 'tcx>( +fn alloc_env_value<'mir, 'tcx>( bytes: &[u8], memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>, ) -> Pointer { @@ -58,3 +46,72 @@ pub(crate) fn alloc_env_value<'mir, 'tcx>( alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap(); ptr } + +impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { + fn getenv( + &mut self, + name_op: OpTy<'tcx, Tag>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let name_ptr = this.read_scalar(name_op)?.not_undef()?; + let name = this.memory().read_c_str(name_ptr)?; + Ok(match this.machine.env_vars.map.get(name) { + Some(&var) => Scalar::Ptr(var), + None => Scalar::ptr_null(&*this.tcx), + }) + } + + fn setenv( + &mut self, + name_op: OpTy<'tcx, Tag>, + value_op: OpTy<'tcx, Tag>, + ) -> InterpResult<'tcx, i32> { + let this = self.eval_context_mut(); + + let name_ptr = this.read_scalar(name_op)?.not_undef()?; + let value_ptr = this.read_scalar(value_op)?.not_undef()?; + let value = this.memory().read_c_str(value_ptr)?; + let mut new = None; + if !this.is_null(name_ptr)? { + let name = this.memory().read_c_str(name_ptr)?; + if !name.is_empty() && !name.contains(&b'=') { + new = Some((name.to_owned(), value.to_owned())); + } + } + if let Some((name, value)) = new { + let value_copy = alloc_env_value(&value, this.memory_mut()); + if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), value_copy) { + this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?; + } + Ok(0) + } else { + Ok(-1) + } + } + + fn unsetenv( + &mut self, + name_op: OpTy<'tcx, Tag>, + ) -> InterpResult<'tcx, i32> { + let this = self.eval_context_mut(); + + let name_ptr = this.read_scalar(name_op)?.not_undef()?; + let mut success = None; + if !this.is_null(name_ptr)? { + let name = this.memory().read_c_str(name_ptr)?.to_owned(); + if !name.is_empty() && !name.contains(&b'=') { + success = Some(this.machine.env_vars.map.remove(&name)); + } + } + if let Some(old) = success { + if let Some(var) = old { + this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?; + } + Ok(0) + } else { + Ok(-1) + } + } +} diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 2d2b917eb275..59e7673dcab5 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -8,7 +8,6 @@ use syntax::attr; use syntax::symbol::sym; use crate::*; -use crate::shims::env::alloc_env_value; impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { @@ -423,60 +422,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } "getenv" => { - let result = { - let name_ptr = this.read_scalar(args[0])?.not_undef()?; - let name = this.memory().read_c_str(name_ptr)?; - match this.machine.env_vars.get(name) { - Some(&var) => Scalar::Ptr(var), - None => Scalar::ptr_null(&*this.tcx), - } - }; + let result = this.getenv(args[0])?; this.write_scalar(result, dest)?; } "unsetenv" => { - let mut success = None; - { - let name_ptr = this.read_scalar(args[0])?.not_undef()?; - if !this.is_null(name_ptr)? { - let name = this.memory().read_c_str(name_ptr)?.to_owned(); - if !name.is_empty() && !name.contains(&b'=') { - success = Some(this.machine.env_vars.unset(&name)); - } - } - } - if let Some(old) = success { - if let Some(var) = old { - this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?; - } - this.write_null(dest)?; - } else { - this.write_scalar(Scalar::from_int(-1, dest.layout.size), dest)?; - } + let result = this.unsetenv(args[0])?; + this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?; } "setenv" => { - let mut new = None; - { - let name_ptr = this.read_scalar(args[0])?.not_undef()?; - let value_ptr = this.read_scalar(args[1])?.not_undef()?; - let value = this.memory().read_c_str(value_ptr)?; - if !this.is_null(name_ptr)? { - let name = this.memory().read_c_str(name_ptr)?; - if !name.is_empty() && !name.contains(&b'=') { - new = Some((name.to_owned(), value.to_owned())); - } - } - } - if let Some((name, value)) = new { - let value_copy = alloc_env_value(&value, this.memory_mut()); - if let Some(var) = this.machine.env_vars.set(name.to_owned(), value_copy) { - this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?; - } - this.write_null(dest)?; - } else { - this.write_scalar(Scalar::from_int(-1, dest.layout.size), dest)?; - } + let result = this.setenv(args[0], args[1])?; + this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?; } "write" => {