@@ -26,10 +26,14 @@ impl<'tcx> EnvVars<'tcx> {
2626 excluded_env_vars : Vec < String > ,
2727 ) -> InterpResult < ' tcx > {
2828 if ecx. machine . communicate {
29+ let target_os = ecx. tcx . sess . target . target . target_os . as_str ( ) ;
2930 for ( name, value) in env:: vars ( ) {
3031 if !excluded_env_vars. contains ( & name) {
31- let var_ptr =
32- alloc_env_var_as_target_str ( name. as_ref ( ) , value. as_ref ( ) , ecx) ?;
32+ let var_ptr = match target_os {
33+ "linux" | "macos" => alloc_env_var_as_c_str ( name. as_ref ( ) , value. as_ref ( ) , ecx) ?,
34+ "windows" => alloc_env_var_as_wide_str ( name. as_ref ( ) , value. as_ref ( ) , ecx) ?,
35+ unsupported => throw_unsup_format ! ( "environment support for target OS `{}` not yet available" , unsupported) ,
36+ } ;
3337 ecx. machine . env_vars . map . insert ( OsString :: from ( name) , var_ptr) ;
3438 }
3539 }
@@ -38,30 +42,41 @@ impl<'tcx> EnvVars<'tcx> {
3842 }
3943}
4044
41- fn alloc_env_var_as_target_str < ' mir , ' tcx > (
45+ fn alloc_env_var_as_c_str < ' mir , ' tcx > (
4246 name : & OsStr ,
4347 value : & OsStr ,
4448 ecx : & mut InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ,
4549) -> InterpResult < ' tcx , Pointer < Tag > > {
4650 let mut name_osstring = name. to_os_string ( ) ;
4751 name_osstring. push ( "=" ) ;
4852 name_osstring. push ( value) ;
49- Ok ( ecx. alloc_os_str_as_target_str ( name_osstring. as_os_str ( ) , MiriMemoryKind :: Machine . into ( ) ) ?)
53+ Ok ( ecx. alloc_os_str_as_c_str ( name_osstring. as_os_str ( ) , MiriMemoryKind :: Machine . into ( ) ) )
54+ }
55+
56+ fn alloc_env_var_as_wide_str < ' mir , ' tcx > (
57+ name : & OsStr ,
58+ value : & OsStr ,
59+ ecx : & mut InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ,
60+ ) -> InterpResult < ' tcx , Pointer < Tag > > {
61+ let mut name_osstring = name. to_os_string ( ) ;
62+ name_osstring. push ( "=" ) ;
63+ name_osstring. push ( value) ;
64+ Ok ( ecx. alloc_os_str_as_wide_str ( name_osstring. as_os_str ( ) , MiriMemoryKind :: Machine . into ( ) ) )
5065}
5166
5267impl < ' mir , ' tcx > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
5368pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
5469 fn getenv ( & mut self , name_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , Scalar < Tag > > {
5570 let this = self . eval_context_mut ( ) ;
56- let target_os = this. tcx . sess . target . target . target_os . as_str ( ) ;
57- assert ! ( target_os == "linux" || target_os == "macos" , "`{} ` is only available for the UNIX target family" ) ;
71+ let target_os = & this. tcx . sess . target . target . target_os ;
72+ assert ! ( target_os == "linux" || target_os == "macos" , "`getenv ` is only available for the UNIX target family" ) ;
5873
5974 let name_ptr = this. read_scalar ( name_op) ?. not_undef ( ) ?;
6075 let name = this. read_os_str_from_c_str ( name_ptr) ?;
6176 Ok ( match this. machine . env_vars . map . get ( name) {
62- // The offset is used to strip the "{name}=" part of the string.
6377 Some ( var_ptr) => {
64- Scalar :: from ( var_ptr. offset ( Size :: from_bytes ( name. len ( ) ) + Size :: from_bytes ( 1 ) , this) ?)
78+ // The offset is used to strip the "{name}=" part of the string.
79+ Scalar :: from ( var_ptr. offset ( Size :: from_bytes ( u64:: try_from ( name. len ( ) ) . unwrap ( ) . checked_add ( 1 ) . unwrap ( ) ) , this) ?)
6580 }
6681 None => Scalar :: ptr_null ( & * this. tcx ) ,
6782 } )
@@ -73,32 +88,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7388 value_op : OpTy < ' tcx , Tag > ,
7489 ) -> InterpResult < ' tcx , i32 > {
7590 let mut this = self . eval_context_mut ( ) ;
91+ let target_os = & this. tcx . sess . target . target . target_os ;
92+ assert ! ( target_os == "linux" || target_os == "macos" , "`setenv` is only available for the UNIX target family" ) ;
7693
7794 let name_ptr = this. read_scalar ( name_op) ?. not_undef ( ) ?;
7895 let value_ptr = this. read_scalar ( value_op) ?. not_undef ( ) ?;
79- let value = this . read_os_str_from_target_str ( value_ptr ) ? ;
96+
8097 let mut new = None ;
8198 if !this. is_null ( name_ptr) ? {
82- let name = this. read_os_str_from_target_str ( name_ptr) ?;
99+ let name = this. read_os_str_from_c_str ( name_ptr) ?;
83100 if !name. is_empty ( ) && !name. to_string_lossy ( ) . contains ( '=' ) {
101+ let value = this. read_os_str_from_c_str ( value_ptr) ?;
84102 new = Some ( ( name. to_owned ( ) , value. to_owned ( ) ) ) ;
85103 }
86104 }
87105 if let Some ( ( name, value) ) = new {
88- let var_ptr = alloc_env_var_as_target_str ( & name, & value, & mut this) ?;
106+ let var_ptr = alloc_env_var_as_c_str ( & name, & value, & mut this) ?;
89107 if let Some ( var) = this. machine . env_vars . map . insert ( name, var_ptr) {
90108 this. memory
91109 . deallocate ( var, None , MiriMemoryKind :: Machine . into ( ) ) ?;
92110 }
93111 this. update_environ ( ) ?;
94- Ok ( 0 )
112+ Ok ( 0 ) // return zero on success
95113 } else {
114+ // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
115+ let einval = this. eval_libc ( "EINVAL" ) ?;
116+ this. set_last_error ( einval) ?;
96117 Ok ( -1 )
97118 }
98119 }
99120
100121 fn unsetenv ( & mut self , name_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > {
101122 let this = self . eval_context_mut ( ) ;
123+ let target_os = & this. tcx . sess . target . target . target_os ;
124+ assert ! ( target_os == "linux" || target_os == "macos" , "`unsetenv` is only available for the UNIX target family" ) ;
102125
103126 let name_ptr = this. read_scalar ( name_op) ?. not_undef ( ) ?;
104127 let mut success = None ;
@@ -116,6 +139,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
116139 this. update_environ ( ) ?;
117140 Ok ( 0 )
118141 } else {
142+ // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
143+ let einval = this. eval_libc ( "EINVAL" ) ?;
144+ this. set_last_error ( einval) ?;
119145 Ok ( -1 )
120146 }
121147 }
0 commit comments