Skip to content

Commit a4b124d

Browse files
committed
wip: handle GetEnvironmentStringsW/FreeEnvironmentStringsW
1 parent 328c0c9 commit a4b124d

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

src/helpers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
458458

459459
/// Dispatches to appropriate implementations for reading an OsString from Memory,
460460
/// depending on the interpretation target.
461-
fn read_os_str_from_target_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString> {
461+
fn read_os_str_from_target_str(&self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString> {
462462
let target_os = self.eval_context_ref().tcx.sess.target.target.target_os.as_str();
463463
match target_os {
464464
"linux" | "macos" => self.read_os_str_from_c_str(scalar).map(|x| x.to_os_string()),
@@ -492,7 +492,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
492492

493493
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
494494
/// which is what the Windows APIs usually handle.
495-
fn read_os_str_from_wide_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString> {
495+
fn read_os_str_from_wide_str(&self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString> {
496496
#[cfg(target_os = "windows")]
497497
fn u16vec_to_osstring<'tcx>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
498498
Ok(std::os::windows::ffi::OsStringExt::from_wide(&u16_vec[..]))

src/shims/env.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::ffi::{OsString, OsStr};
22
use std::env;
33
use std::convert::TryFrom;
4+
use std::collections::hash_map::Values;
45

56
use crate::stacked_borrows::Tag;
67
use crate::rustc_target::abi::LayoutOf;
@@ -36,6 +37,10 @@ impl<'tcx> EnvVars<'tcx> {
3637
}
3738
ecx.update_environ()
3839
}
40+
41+
pub(super) fn values(&self) -> InterpResult<'tcx, Values<'_, OsString, Pointer<Tag>>> {
42+
Ok(self.map.values())
43+
}
3944
}
4045

4146
fn alloc_env_var_as_target_str<'mir, 'tcx>(

src/shims/foreign_items/windows.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use crate::*;
2+
use crate::rustc_target::abi::LayoutOf;
23
use rustc::mir;
34
use rustc::ty::layout::Size;
45
use std::iter;
6+
use std::convert::TryFrom;
57

68
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
79
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
@@ -21,18 +23,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2123
// DWORD = ULONG = u32
2224
// BOOL = i32
2325

24-
"GetEnvironmentStringsW" => {
25-
// this.write_scalar(this.machine.env_vars.environ.unwrap().vtable(), dest)?;
26-
}
27-
2826
// Environment related shims
2927
"GetEnvironmentVariableW" => {
3028
let result = this.getenvironmentvariablew(args[0], args[1], args[2])?;
3129
if result == 0 {
3230
this.set_last_error(Scalar::from_u32(203))?; // ERROR_ENVVAR_NOT_FOUND
33-
// this.write_null(dest)?;
34-
} else {
35-
// this.write_scalar(Scalar::from_uint(result, dest.layout.size), dest)?;
3631
}
3732
this.write_scalar(Scalar::from_uint(result, dest.layout.size), dest)?;
3833
}
@@ -42,6 +37,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4237
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
4338
}
4439

40+
"GetEnvironmentStringsW" => {
41+
// Info on layout of environment blocks in Windows:
42+
// https://docs.microsoft.com/en-us/windows/win32/procthread/environment-variables
43+
let mut env_vars = std::ffi::OsString::new();
44+
for &item in this.machine.env_vars.values()? {
45+
let env_var = this.read_os_str_from_target_str(Scalar::from(item))?;
46+
env_vars.push(env_var);
47+
env_vars.push(" ");
48+
}
49+
50+
// Allocate environment block
51+
let tcx = this.tcx;
52+
let env_block_size = env_vars.len() + 1;
53+
let env_block_type = tcx.mk_array(tcx.types.u16, u64::try_from(env_block_size).unwrap());
54+
let env_block_place = this.allocate(this.layout_of(env_block_type)?, MiriMemoryKind::Machine.into());
55+
56+
// Store environment variables to environment block
57+
// Final null terminator(block terminator) is pushed by `write_os_str_to_wide_str`
58+
this.write_os_str_to_wide_str(&env_vars, env_block_place, u64::try_from(env_block_size).unwrap())?;
59+
60+
// If the function succeeds, the return value is a pointer to the environment block of the current process.
61+
this.write_scalar(env_block_place.ptr, dest)?;
62+
}
63+
64+
"FreeEnvironmentStringsW" => {
65+
// let old_vars_ptr = this.read_scalar(args[0])?.not_undef()?;
66+
// this.memory.deallocate(this.force_ptr(old_vars_ptr)?, None, MiriMemoryKind::Machine.into())?;
67+
}
68+
4569
// File related shims
4670
"WriteFile" => {
4771
let handle = this.read_scalar(args[0])?.to_machine_isize(this)?;

0 commit comments

Comments
 (0)