1
1
use std:: collections:: HashMap ;
2
+ use std:: env;
2
3
3
- use rustc:: ty:: layout:: { Size } ;
4
- use rustc_mir:: interpret:: { Pointer , Memory } ;
5
4
use crate :: stacked_borrows:: Tag ;
6
5
use crate :: * ;
6
+ use rustc:: ty:: layout:: Size ;
7
+ use rustc_mir:: interpret:: { Memory , Pointer } ;
7
8
8
9
#[ derive( Default ) ]
9
10
pub struct EnvVars {
@@ -21,9 +22,10 @@ impl EnvVars {
21
22
excluded_env_vars. push ( "TERM" . to_owned ( ) ) ;
22
23
23
24
if ecx. machine . communicate {
24
- for ( name, value) in std :: env:: vars ( ) {
25
+ for ( name, value) in env:: vars ( ) {
25
26
if !excluded_env_vars. contains ( & name) {
26
- let var_ptr = alloc_env_var ( name. as_bytes ( ) , value. as_bytes ( ) , ecx. memory_mut ( ) ) ;
27
+ let var_ptr =
28
+ alloc_env_var ( name. as_bytes ( ) , value. as_bytes ( ) , ecx. memory_mut ( ) ) ;
27
29
ecx. machine . env_vars . map . insert ( name. into_bytes ( ) , var_ptr) ;
28
30
}
29
31
}
@@ -45,17 +47,16 @@ fn alloc_env_var<'mir, 'tcx>(
45
47
46
48
impl < ' mir , ' tcx > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
47
49
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
48
- fn getenv (
49
- & mut self ,
50
- name_op : OpTy < ' tcx , Tag > ,
51
- ) -> InterpResult < ' tcx , Scalar < Tag > > {
50
+ fn getenv ( & mut self , name_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , Scalar < Tag > > {
52
51
let this = self . eval_context_mut ( ) ;
53
52
54
53
let name_ptr = this. read_scalar ( name_op) ?. not_undef ( ) ?;
55
54
let name = this. memory ( ) . read_c_str ( name_ptr) ?;
56
55
Ok ( match this. machine . env_vars . map . get ( name) {
57
56
// The offset is used to strip the "{name}=" part of the string.
58
- Some ( var_ptr) => Scalar :: Ptr ( var_ptr. offset ( Size :: from_bytes ( name. len ( ) as u64 + 1 ) , this) ?) ,
57
+ Some ( var_ptr) => {
58
+ Scalar :: Ptr ( var_ptr. offset ( Size :: from_bytes ( name. len ( ) as u64 + 1 ) , this) ?)
59
+ }
59
60
None => Scalar :: ptr_null ( & * this. tcx ) ,
60
61
} )
61
62
}
@@ -80,18 +81,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
80
81
if let Some ( ( name, value) ) = new {
81
82
let var_ptr = alloc_env_var ( & name, & value, this. memory_mut ( ) ) ;
82
83
if let Some ( var) = this. machine . env_vars . map . insert ( name. to_owned ( ) , var_ptr) {
83
- this. memory_mut ( ) . deallocate ( var, None , MiriMemoryKind :: Env . into ( ) ) ?;
84
+ this. memory_mut ( )
85
+ . deallocate ( var, None , MiriMemoryKind :: Env . into ( ) ) ?;
84
86
}
85
87
Ok ( 0 )
86
88
} else {
87
89
Ok ( -1 )
88
90
}
89
91
}
90
92
91
- fn unsetenv (
92
- & mut self ,
93
- name_op : OpTy < ' tcx , Tag > ,
94
- ) -> InterpResult < ' tcx , i32 > {
93
+ fn unsetenv ( & mut self , name_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > {
95
94
let this = self . eval_context_mut ( ) ;
96
95
97
96
let name_ptr = this. read_scalar ( name_op) ?. not_undef ( ) ?;
@@ -104,11 +103,52 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
104
103
}
105
104
if let Some ( old) = success {
106
105
if let Some ( var) = old {
107
- this. memory_mut ( ) . deallocate ( var, None , MiriMemoryKind :: Env . into ( ) ) ?;
106
+ this. memory_mut ( )
107
+ . deallocate ( var, None , MiriMemoryKind :: Env . into ( ) ) ?;
108
108
}
109
109
Ok ( 0 )
110
110
} else {
111
111
Ok ( -1 )
112
112
}
113
113
}
114
+
115
+ fn getcwd (
116
+ & mut self ,
117
+ buf_op : OpTy < ' tcx , Tag > ,
118
+ size_op : OpTy < ' tcx , Tag > ,
119
+ ) -> InterpResult < ' tcx , Scalar < Tag > > {
120
+ let this = self . eval_context_mut ( ) ;
121
+
122
+ if !this. machine . communicate {
123
+ throw_unsup_format ! ( "`getcwd` not available when isolation is enabled" )
124
+ }
125
+
126
+ let tcx = & { this. tcx . tcx } ;
127
+
128
+ let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
129
+ let size = this. read_scalar ( size_op) ?. to_usize ( & * this. tcx ) ?;
130
+ // If we cannot get the current directory, we return null
131
+ match env:: current_dir ( ) {
132
+ Ok ( cwd) => {
133
+ // It is not clear what happens with non-utf8 paths here
134
+ let mut bytes = cwd. display ( ) . to_string ( ) . into_bytes ( ) ;
135
+ // If the buffer is smaller or equal than the path, we return null.
136
+ if ( bytes. len ( ) as u64 ) < size {
137
+ // We add a `/0` terminator
138
+ bytes. push ( 0 ) ;
139
+ // This is ok because the buffer is larger than the path with the null terminator.
140
+ this. memory_mut ( )
141
+ . get_mut ( buf. alloc_id ) ?
142
+ . write_bytes ( tcx, buf, & bytes) ?;
143
+ return Ok ( Scalar :: Ptr ( buf) ) ;
144
+ }
145
+ this. machine . last_error = this
146
+ . eval_path_scalar ( & [ "libc" , "ERANGE" ] ) ?
147
+ . unwrap ( )
148
+ . to_u32 ( ) ?;
149
+ }
150
+ Err ( e) => this. machine . last_error = e. raw_os_error ( ) . unwrap ( ) as u32 ,
151
+ }
152
+ Ok ( Scalar :: ptr_null ( & * this. tcx ) )
153
+ }
114
154
}
0 commit comments