11use std:: env;
2+ use std:: ffi:: OsString ;
23
34#[ cfg( feature = "convert-case" ) ]
45use convert_case:: { Case , Casing } ;
@@ -7,6 +8,7 @@ use crate::error::Result;
78use crate :: map:: Map ;
89use crate :: source:: Source ;
910use crate :: value:: { Value , ValueKind } ;
11+ use crate :: ConfigError ;
1012
1113/// An environment source collects a dictionary of environment variables values into a hierarchical
1214/// 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 {
243245 . as_ref ( )
244246 . map ( |prefix| format ! ( "{prefix}{prefix_separator}" ) . to_lowercase ( ) ) ;
245247
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+
247255 // Treat empty environment variables as unset
248256 if self . ignore_empty && value. is_empty ( ) {
249- return ;
257+ return Ok ( ( ) ) ;
250258 }
251259
252260 let mut key = key. to_lowercase ( ) ;
@@ -260,10 +268,18 @@ impl Source for Environment {
260268 }
261269 } else {
262270 // Skip this key
263- return ;
271+ return Ok ( ( ) ) ;
264272 }
265273 }
266274
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+
267283 // If separator is given replace with `.`
268284 if !separator. is_empty ( ) {
269285 key = key. replace ( separator, "." ) ;
@@ -308,12 +324,18 @@ impl Source for Environment {
308324 } ;
309325
310326 m. insert ( key, Value :: new ( Some ( & uri) , value) ) ;
327+
328+ Ok ( ( ) )
311329 } ;
312330
313331 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+ } ?;
317339
318340 Ok ( m)
319341 }
0 commit comments