@@ -53,6 +53,7 @@ pub struct Command {
53
53
uid : Option < uid_t > ,
54
54
gid : Option < gid_t > ,
55
55
saw_nul : bool ,
56
+ saw_malformed_env_key : bool ,
56
57
closures : Vec < Box < FnMut ( ) -> io:: Result < ( ) > + Send + Sync > > ,
57
58
stdin : Option < Stdio > ,
58
59
stdout : Option < Stdio > ,
@@ -102,6 +103,7 @@ impl Command {
102
103
uid : None ,
103
104
gid : None ,
104
105
saw_nul : saw_nul,
106
+ saw_malformed_env_key : false ,
105
107
closures : Vec :: new ( ) ,
106
108
stdin : None ,
107
109
stdout : None ,
@@ -127,7 +129,11 @@ impl Command {
127
129
let mut map = HashMap :: new ( ) ;
128
130
let mut envp = Vec :: new ( ) ;
129
131
for ( k, v) in env:: vars_os ( ) {
130
- let s = pair_to_key ( & k, & v, & mut self . saw_nul ) ;
132
+ let mut saw_nul = false ;
133
+ let mut saw_malformed_env_key = false ;
134
+ let s = pair_to_key ( & k, & v, & mut saw_nul, & mut saw_malformed_env_key) ;
135
+ assert ! ( !saw_nul) ;
136
+ assert ! ( !saw_malformed_env_key) ;
131
137
envp. push ( s. as_ptr ( ) ) ;
132
138
map. insert ( k, ( envp. len ( ) - 1 , s) ) ;
133
139
}
@@ -139,7 +145,8 @@ impl Command {
139
145
}
140
146
141
147
pub fn env ( & mut self , key : & OsStr , val : & OsStr ) {
142
- let new_key = pair_to_key ( key, val, & mut self . saw_nul ) ;
148
+ let new_key = pair_to_key ( key, val, & mut self . saw_nul , & mut self . saw_malformed_env_key ) ;
149
+
143
150
let ( map, envp) = self . init_env_map ( ) ;
144
151
145
152
// If `key` is already present then we just update `envp` in place
@@ -162,6 +169,8 @@ impl Command {
162
169
}
163
170
164
171
pub fn env_remove ( & mut self , key : & OsStr ) {
172
+ pair_to_key ( key, OsStr :: new ( "" ) , & mut self . saw_nul , & mut self . saw_malformed_env_key ) ;
173
+
165
174
let ( map, envp) = self . init_env_map ( ) ;
166
175
167
176
// If we actually ended up removing a key, then we need to update the
@@ -193,9 +202,6 @@ impl Command {
193
202
self . gid = Some ( id) ;
194
203
}
195
204
196
- pub fn saw_nul ( & self ) -> bool {
197
- self . saw_nul
198
- }
199
205
pub fn get_envp ( & self ) -> & Option < Vec < * const c_char > > {
200
206
& self . envp
201
207
}
@@ -237,6 +243,18 @@ impl Command {
237
243
self . stderr = Some ( stderr) ;
238
244
}
239
245
246
+ pub fn check_malformed ( & self ) -> io:: Result < ( ) > {
247
+ if self . saw_nul {
248
+ return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput ,
249
+ "nul byte found in provided data" ) ) ;
250
+ }
251
+ if self . saw_malformed_env_key {
252
+ return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput ,
253
+ "malformed env key in provided data" ) ) ;
254
+ }
255
+ Ok ( ( ) )
256
+ }
257
+
240
258
pub fn setup_io ( & self , default : Stdio , needs_stdin : bool )
241
259
-> io:: Result < ( StdioPipes , ChildPipes ) > {
242
260
let null = Stdio :: Null ;
@@ -261,6 +279,13 @@ impl Command {
261
279
}
262
280
}
263
281
282
+ fn check_env_key ( s : & OsStr , saw_malformed : & mut bool ) {
283
+ let bytes = s. as_bytes ( ) ;
284
+ if bytes. is_empty ( ) || bytes[ 1 ..] . contains ( & b'=' ) {
285
+ * saw_malformed = true ;
286
+ }
287
+ }
288
+
264
289
fn os2c ( s : & OsStr , saw_nul : & mut bool ) -> CString {
265
290
CString :: new ( s. as_bytes ( ) ) . unwrap_or_else ( |_e| {
266
291
* saw_nul = true ;
@@ -325,15 +350,19 @@ impl ChildStdio {
325
350
}
326
351
}
327
352
328
- fn pair_to_key ( key : & OsStr , value : & OsStr , saw_nul : & mut bool ) -> CString {
353
+ fn pair_to_key ( key : & OsStr , value : & OsStr , saw_nul : & mut bool , saw_malformed : & mut bool )
354
+ -> CString
355
+ {
356
+ check_env_key ( key, saw_malformed) ;
357
+
329
358
let ( key, value) = ( key. as_bytes ( ) , value. as_bytes ( ) ) ;
330
359
let mut v = Vec :: with_capacity ( key. len ( ) + value. len ( ) + 1 ) ;
331
360
v. extend ( key) ;
332
361
v. push ( b'=' ) ;
333
362
v. extend ( value) ;
334
363
CString :: new ( v) . unwrap_or_else ( |_e| {
335
364
* saw_nul = true ;
336
- CString :: new ( "foo=bar " ) . unwrap ( )
365
+ CString :: new ( "<ENV_WITH_NUL> " ) . unwrap ( )
337
366
} )
338
367
}
339
368
0 commit comments