1- #![ allow( non_snake_case) ]
2-
31use std:: ffi:: { OsString , OsStr } ;
42use std:: env;
53use std:: convert:: TryFrom ;
6- use std:: collections:: hash_map:: Values ;
74
85use crate :: stacked_borrows:: Tag ;
96use crate :: rustc_target:: abi:: LayoutOf ;
@@ -43,10 +40,6 @@ impl<'tcx> EnvVars<'tcx> {
4340 }
4441 ecx. update_environ ( )
4542 }
46-
47- fn values ( & self ) -> InterpResult < ' tcx , Values < ' _ , OsString , Pointer < Tag > > > {
48- Ok ( self . map . values ( ) )
49- }
5043}
5144
5245fn alloc_env_var_as_target_str < ' mir , ' tcx > (
@@ -100,11 +93,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
10093 } )
10194 }
10295
96+ #[ allow( non_snake_case) ]
10397 fn GetEnvironmentVariableW (
10498 & mut self ,
105- name_op : OpTy < ' tcx , Tag > , // LPCWSTR lpName
106- buf_op : OpTy < ' tcx , Tag > , // LPWSTR lpBuffer
107- size_op : OpTy < ' tcx , Tag > , // DWORD nSize
99+ name_op : OpTy < ' tcx , Tag > , // LPCWSTR
100+ buf_op : OpTy < ' tcx , Tag > , // LPWSTR
101+ size_op : OpTy < ' tcx , Tag > , // DWORD
108102 ) -> InterpResult < ' tcx , u64 > {
109103 let this = self . eval_context_mut ( ) ;
110104 this. assert_target_os ( "windows" , "GetEnvironmentVariableW" ) ;
@@ -119,7 +113,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
119113 let var_ptr = Scalar :: from ( var_ptr. offset ( Size :: from_bytes ( name_offset_bytes) , this) ?) ;
120114
121115 let var_size = u64:: try_from ( this. read_os_str_from_wide_str ( var_ptr) ?. len ( ) ) . unwrap ( ) ;
122- // `buf_size` represent size in characters.
116+ // `buf_size` represents the size in characters.
123117 let buf_size = u64:: try_from ( this. read_scalar ( size_op) ?. to_u32 ( ) ?) . unwrap ( ) ;
124118 let return_val = if var_size. checked_add ( 1 ) . unwrap ( ) > buf_size {
125119 // If lpBuffer is not large enough to hold the data, the return value is the buffer size, in characters,
@@ -142,31 +136,41 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
142136 } )
143137 }
144138
139+ #[ allow( non_snake_case) ]
145140 fn GetEnvironmentStringsW ( & mut self ) -> InterpResult < ' tcx , Scalar < Tag > > {
146141 let this = self . eval_context_mut ( ) ;
147142 this. assert_target_os ( "windows" , "GetEnvironmentStringsW" ) ;
148143
149144 // Info on layout of environment blocks in Windows:
150145 // https://docs.microsoft.com/en-us/windows/win32/procthread/environment-variables
151146 let mut env_vars = std:: ffi:: OsString :: new ( ) ;
152- for & item in this. machine . env_vars . values ( ) ? {
147+ for & item in this. machine . env_vars . map . values ( ) {
153148 let env_var = this. read_os_str_from_wide_str ( Scalar :: from ( item) ) ?;
154149 env_vars. push ( env_var) ;
155150 env_vars. push ( "\0 " ) ;
156151 }
157152 // Allocate environment block & Store environment variables to environment block.
158153 // Final null terminator(block terminator) is added by `alloc_os_str_to_wide_str`.
154+ // FIXME: MemoryKind should be `MiMemoryKind::Machine`,
155+ // but using it results in a Stacked Borrows error when running MIRI on 'tests/run-pass/env.rs'
156+ // For now, use `MiriMemoryKind::WinHeap` instead.
159157 let envblock_ptr = this. alloc_os_str_as_wide_str ( & env_vars, MiriMemoryKind :: WinHeap . into ( ) ) ;
160-
158+ // If the function succeeds, the return value is a pointer to the environment block of the current process.
161159 Ok ( envblock_ptr. into ( ) )
162160 }
163161
164- fn FreeEnvironmentStringsW ( & mut self , env_block_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , bool > {
162+ #[ allow( non_snake_case) ]
163+ fn FreeEnvironmentStringsW ( & mut self , env_block_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > {
165164 let this = self . eval_context_mut ( ) ;
166165 this. assert_target_os ( "windows" , "FreeEnvironmentStringsW" ) ;
167166
168167 let env_block_ptr = this. read_scalar ( env_block_op) ?. not_undef ( ) ?;
169- Ok ( this. memory . deallocate ( this. force_ptr ( env_block_ptr) ?, None , MiriMemoryKind :: WinHeap . into ( ) ) . is_ok ( ) )
168+ // FIXME: MemoryKind should be `MiMemoryKind::Machine`,
169+ // but using it results in a Stacked Borrows error when running MIRI on 'tests/run-pass/env.rs'
170+ // For now, use `MiriMemoryKind::WinHeap` instead.
171+ let result = this. memory . deallocate ( this. force_ptr ( env_block_ptr) ?, None , MiriMemoryKind :: WinHeap . into ( ) ) ;
172+ // If the function succeeds, the return value is nonzero.
173+ Ok ( result. is_ok ( ) as i32 )
170174 }
171175
172176 fn setenv (
@@ -205,10 +209,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
205209 }
206210 }
207211
212+ #[ allow( non_snake_case) ]
208213 fn SetEnvironmentVariableW (
209214 & mut self ,
210- name_op : OpTy < ' tcx , Tag > , // LPCWSTR lpName,
211- value_op : OpTy < ' tcx , Tag > , // LPCWSTR lpValue,
215+ name_op : OpTy < ' tcx , Tag > , // LPCWSTR
216+ value_op : OpTy < ' tcx , Tag > , // LPCWSTR
212217 ) -> InterpResult < ' tcx , i32 > {
213218 let mut this = self . eval_context_mut ( ) ;
214219 this. assert_target_os ( "windows" , "SetEnvironmentVariableW" ) ;
@@ -218,14 +223,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
218223
219224 if this. is_null ( name_ptr) ? {
220225 // ERROR CODE is not clearly explained in docs.. For now, throw UB instead.
221- throw_ub_format ! ( "Pointer to environment variable name is NULL" ) ;
226+ throw_ub_format ! ( "pointer to environment variable name is NULL" ) ;
222227 }
223228
224229 let name = this. read_os_str_from_wide_str ( name_ptr) ?;
225230 if name. is_empty ( ) {
226- throw_unsup_format ! ( "Environment variable name is an empty string" ) ;
231+ throw_unsup_format ! ( "environment variable name is an empty string" ) ;
227232 } else if name. to_string_lossy ( ) . contains ( '=' ) {
228- throw_unsup_format ! ( "Environment variable name contains '='" ) ;
233+ throw_unsup_format ! ( "environment variable name contains '='" ) ;
229234 } else if this. is_null ( value_ptr) ? {
230235 // Delete environment variable `{name}`
231236 if let Some ( var) = this. machine . env_vars . map . remove ( & name) {
@@ -266,6 +271,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
266271 this. update_environ ( ) ?;
267272 Ok ( 0 )
268273 } else {
274+ // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
275+ let einval = this. eval_libc ( "EINVAL" ) ?;
276+ this. set_last_error ( einval) ?;
269277 Ok ( -1 )
270278 }
271279 }
0 commit comments