1
1
use std:: env;
2
+ use std:: ffi:: OsString ;
2
3
3
4
#[ cfg( feature = "convert-case" ) ]
4
5
use convert_case:: { Case , Casing } ;
@@ -7,6 +8,7 @@ use crate::error::Result;
7
8
use crate :: map:: Map ;
8
9
use crate :: source:: Source ;
9
10
use crate :: value:: { Value , ValueKind } ;
11
+ use crate :: ConfigError ;
10
12
11
13
/// An environment source collects a dictionary of environment variables values into a hierarchical
12
14
/// config Value type. We have to be aware how the config tree is created from the environment
@@ -243,10 +245,16 @@ impl Source for Environment {
243
245
. as_ref ( )
244
246
. map ( |prefix| format ! ( "{prefix}{prefix_separator}" ) . to_lowercase ( ) ) ;
245
247
246
- let collector = |( key, value) : ( String , String ) | {
248
+ let collector = |( key, value) : ( OsString , OsString ) | {
249
+ let key = match key. into_string ( ) {
250
+ Ok ( key) => key,
251
+ // Key is not valid unicode, skip it
252
+ Err ( _) => return Ok ( ( ) ) ,
253
+ } ;
254
+
247
255
// Treat empty environment variables as unset
248
256
if self . ignore_empty && value. is_empty ( ) {
249
- return ;
257
+ return Ok ( ( ) ) ;
250
258
}
251
259
252
260
let mut key = key. to_lowercase ( ) ;
@@ -260,10 +268,18 @@ impl Source for Environment {
260
268
}
261
269
} else {
262
270
// Skip this key
263
- return ;
271
+ return Ok ( ( ) ) ;
264
272
}
265
273
}
266
274
275
+ // At this point, we don't know if the key is required or not.
276
+ // Therefore if the value is not a valid unicode string, we error out.
277
+ let value = value. into_string ( ) . map_err ( |os_string| {
278
+ ConfigError :: Message ( format ! (
279
+ "env variable {key:?} contains non-Unicode data: {os_string:?}"
280
+ ) )
281
+ } ) ?;
282
+
267
283
// If separator is given replace with `.`
268
284
if !separator. is_empty ( ) {
269
285
key = key. replace ( separator, "." ) ;
@@ -308,12 +324,18 @@ impl Source for Environment {
308
324
} ;
309
325
310
326
m. insert ( key, Value :: new ( Some ( & uri) , value) ) ;
327
+
328
+ Ok ( ( ) )
311
329
} ;
312
330
313
331
match & self . source {
314
- Some ( source) => source. clone ( ) . into_iter ( ) . for_each ( collector) ,
315
- None => env:: vars ( ) . for_each ( collector) ,
316
- }
332
+ Some ( source) => source
333
+ . clone ( )
334
+ . into_iter ( )
335
+ . map ( |( key, value) | ( key. into ( ) , value. into ( ) ) )
336
+ . try_for_each ( collector) ,
337
+ None => env:: vars_os ( ) . try_for_each ( collector) ,
338
+ } ?;
317
339
318
340
Ok ( m)
319
341
}
0 commit comments