From 4f5fdc581014ecb17a9aa14ada2a2f186c9a46a8 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 4 Mar 2020 13:24:01 -0500 Subject: [PATCH] update the environ shim when environment changes --- src/eval.rs | 2 +- src/machine.rs | 19 ++++++++++--------- src/shims/env.rs | 41 +++++++++++++++++++++++++++-------------- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index dacd996c4a6e..1981a8d1e03e 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -77,8 +77,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( ), ); // Complete initialization. - EnvVars::init(&mut ecx, config.excluded_env_vars); MemoryExtra::init_extern_statics(&mut ecx)?; + EnvVars::init(&mut ecx, config.excluded_env_vars); // Setup first stack-frame let main_instance = ty::Instance::mono(tcx, main_id); diff --git a/src/machine.rs b/src/machine.rs index 0e3cc58df736..ece4b62d3af1 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -70,7 +70,7 @@ pub struct AllocExtra { /// Extra global memory data #[derive(Clone, Debug)] -pub struct MemoryExtra { +pub struct MemoryExtra<'tcx> { pub stacked_borrows: Option, pub intptrcast: intptrcast::MemoryExtra, @@ -85,11 +85,11 @@ pub struct MemoryExtra { /// (helps for debugging memory leaks). tracked_alloc_id: Option, - /// The `AllocId` for the `environ` static. - pub(crate) environ: Option>, + /// Place where the `environ` static is stored. + pub(crate) environ: Option>, } -impl MemoryExtra { +impl<'tcx> MemoryExtra<'tcx> { pub fn new(rng: StdRng, stacked_borrows: bool, tracked_pointer_tag: Option, tracked_alloc_id: Option) -> Self { let stacked_borrows = if stacked_borrows { Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(tracked_pointer_tag)))) @@ -107,7 +107,7 @@ impl MemoryExtra { } /// Sets up the "extern statics" for this machine. - pub fn init_extern_statics<'mir, 'tcx>( + pub fn init_extern_statics<'mir>( this: &mut MiriEvalContext<'mir, 'tcx>, ) -> InterpResult<'tcx> { match this.tcx.sess.target.target.target_os.as_str() { @@ -126,12 +126,13 @@ impl MemoryExtra { // "environ" let layout = this.layout_of(this.tcx.types.usize)?; let place = this.allocate(layout, MiriMemoryKind::Machine.into()); - this.write_scalar(this.memory.extra.environ.unwrap(), place.into())?; + this.write_scalar(Scalar::from_machine_usize(0, &*this.tcx), place.into())?; this.memory .extra .extern_statics .insert(Symbol::intern("environ"), place.ptr.assert_ptr().alloc_id) .unwrap_none(); + this.memory.extra.environ = Some(place); } _ => {} // No "extern statics" supported on this platform } @@ -217,7 +218,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { type MemoryKinds = MiriMemoryKind; type FrameExtra = FrameData<'tcx>; - type MemoryExtra = MemoryExtra; + type MemoryExtra = MemoryExtra<'tcx>; type AllocExtra = AllocExtra; type PointerTag = Tag; type ExtraFnVal = Dlsym; @@ -343,7 +344,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { } fn init_allocation_extra<'b>( - memory_extra: &MemoryExtra, + memory_extra: &MemoryExtra<'tcx>, id: AllocId, alloc: Cow<'b, Allocation>, kind: Option>, @@ -380,7 +381,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { } #[inline(always)] - fn tag_static_base_pointer(memory_extra: &MemoryExtra, id: AllocId) -> Self::PointerTag { + fn tag_static_base_pointer(memory_extra: &MemoryExtra<'tcx>, id: AllocId) -> Self::PointerTag { if let Some(stacked_borrows) = memory_extra.stacked_borrows.as_ref() { stacked_borrows.borrow_mut().static_base_ptr(id) } else { diff --git a/src/shims/env.rs b/src/shims/env.rs index 833fef69f28f..05c098bc4e72 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -21,29 +21,16 @@ impl EnvVars { ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>, excluded_env_vars: Vec, ) { - let mut vars = Vec::new(); if ecx.machine.communicate { for (name, value) in env::vars() { if !excluded_env_vars.contains(&name) { let var_ptr = alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx); ecx.machine.env_vars.map.insert(OsString::from(name), var_ptr); - vars.push(var_ptr.into()); } } } - // Add the trailing null pointer - vars.push(Scalar::from_int(0, ecx.pointer_size())); - // Make an array with all these pointers inside Miri. - let tcx = ecx.tcx; - let environ_layout = - ecx.layout_of(tcx.mk_array(tcx.mk_imm_ptr(tcx.types.u8), vars.len() as u64)).unwrap(); - let environ_place = ecx.allocate(environ_layout, MiriMemoryKind::Machine.into()); - for (idx, var) in vars.into_iter().enumerate() { - let place = ecx.mplace_field(environ_place, idx as u64).unwrap(); - ecx.write_scalar(var, place.into()).unwrap(); - } - ecx.memory.extra.environ = Some(environ_place.ptr.into()); + ecx.update_environ().unwrap(); } } @@ -94,6 +81,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx if let Some((name, value)) = new { let var_ptr = alloc_env_var_as_c_str(&name, &value, &mut this); if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) { + this.update_environ()?; this.memory .deallocate(var, None, MiriMemoryKind::Machine.into())?; } @@ -112,6 +100,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let name = this.read_os_str_from_c_str(name_ptr)?.to_owned(); if !name.is_empty() && !name.to_string_lossy().contains('=') { success = Some(this.machine.env_vars.map.remove(&name)); + this.update_environ()?; } } if let Some(old) = success { @@ -165,4 +154,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } } } + + fn update_environ(&mut self) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + // Collect all the pointers to each variable in a vector. + let mut vars: Vec> = this.machine.env_vars.map.values().map(|&ptr| ptr.into()).collect(); + // Add the trailing null pointer. + vars.push(Scalar::from_int(0, this.pointer_size())); + // Make an array with all these pointers inside Miri. + let tcx = this.tcx; + let vars_layout = + this.layout_of(tcx.mk_array(tcx.types.usize, vars.len() as u64))?; + let vars_place = this.allocate(vars_layout, MiriMemoryKind::Machine.into()); + for (idx, var) in vars.into_iter().enumerate() { + let place = this.mplace_field(vars_place, idx as u64)?; + this.write_scalar(var, place.into())?; + } + + this.write_scalar( + vars_place.ptr, + this.memory.extra.environ.unwrap().into(), + )?; + + Ok(()) + } }