@@ -318,10 +318,52 @@ impl Error for VarError {
318
318
///
319
319
/// # Safety
320
320
///
321
- /// Even though this function is currently not marked as `unsafe`, it needs to
322
- /// be because invoking it can cause undefined behaviour. The function will be
323
- /// marked `unsafe` in a future version of Rust. This is tracked in
324
- /// [rust#27970](https://github.com/rust-lang/rust/issues/27970).
321
+ /// This function is safe to call in a single-threaded program.
322
+ ///
323
+ /// In multi-threaded programs, you must ensure that are no other threads
324
+ /// concurrently writing or *reading*(!) from the environment through functions
325
+ /// other than the ones in this module. You are responsible for figuring out
326
+ /// how to achieve this, but we strongly suggest not using `set_var` or
327
+ /// `remove_var` in multi-threaded programs at all.
328
+ ///
329
+ /// Most C libraries, including libc itself do not advertise which functions
330
+ /// read from the environment. Even functions from the Rust standard library do
331
+ /// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`].
332
+ ///
333
+ /// Discussion of this unsafety on Unix may be found in:
334
+ ///
335
+ /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
336
+ /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
337
+ ///
338
+ /// [`std::net::ToSocketAddrs`]: crate::net::ToSocketAddrs
339
+ ///
340
+ /// # Panics
341
+ ///
342
+ /// This function may panic if `key` is empty, contains an ASCII equals sign `'='`
343
+ /// or the NUL character `'\0'`, or when `value` contains the NUL character.
344
+ ///
345
+ /// # Examples
346
+ ///
347
+ /// ```
348
+ /// use std::env;
349
+ ///
350
+ /// let key = "KEY";
351
+ /// unsafe {
352
+ /// env::set_var(key, "VALUE");
353
+ /// }
354
+ /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
355
+ /// ```
356
+ #[ cfg( not( bootstrap) ) ]
357
+ #[ rustc_deprecated_safe_2024]
358
+ #[ stable( feature = "env" , since = "1.0.0" ) ]
359
+ pub unsafe fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
360
+ _set_var ( key. as_ref ( ) , value. as_ref ( ) )
361
+ }
362
+
363
+ /// Sets the environment variable `key` to the value `value` for the currently running
364
+ /// process.
365
+ ///
366
+ /// # Safety
325
367
///
326
368
/// This function is safe to call in a single-threaded program.
327
369
///
@@ -350,18 +392,23 @@ impl Error for VarError {
350
392
/// # Examples
351
393
///
352
394
/// ```
395
+ /// # #![allow(unused_unsafe)]
396
+ ///
353
397
/// use std::env;
354
398
///
355
399
/// let key = "KEY";
356
- /// env::set_var(key, "VALUE");
400
+ /// unsafe {
401
+ /// env::set_var(key, "VALUE");
402
+ /// }
357
403
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
358
404
/// ```
405
+ #[ cfg( bootstrap) ]
359
406
#[ stable( feature = "env" , since = "1.0.0" ) ]
360
407
pub fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
361
- _set_var ( key. as_ref ( ) , value. as_ref ( ) )
408
+ unsafe { _set_var ( key. as_ref ( ) , value. as_ref ( ) ) }
362
409
}
363
410
364
- fn _set_var ( key : & OsStr , value : & OsStr ) {
411
+ unsafe fn _set_var ( key : & OsStr , value : & OsStr ) {
365
412
os_imp:: setenv ( key, value) . unwrap_or_else ( |e| {
366
413
panic ! ( "failed to set environment variable `{key:?}` to `{value:?}`: {e}" )
367
414
} )
@@ -371,11 +418,6 @@ fn _set_var(key: &OsStr, value: &OsStr) {
371
418
///
372
419
/// # Safety
373
420
///
374
- /// Even though this function is currently not marked as `unsafe`, it needs to
375
- /// be because invoking it can cause undefined behaviour. The function will be
376
- /// marked `unsafe` in a future version of Rust. This is tracked in
377
- /// [rust#27970](https://github.com/rust-lang/rust/issues/27970).
378
- ///
379
421
/// This function is safe to call in a single-threaded program.
380
422
///
381
423
/// In multi-threaded programs, you must ensure that are no other threads
@@ -403,22 +445,81 @@ fn _set_var(key: &OsStr, value: &OsStr) {
403
445
///
404
446
/// # Examples
405
447
///
448
+ /// ```no_run
449
+ /// use std::env;
450
+ ///
451
+ /// let key = "KEY";
452
+ /// unsafe {
453
+ /// env::set_var(key, "VALUE");
454
+ /// }
455
+ /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
456
+ ///
457
+ /// unsafe {
458
+ /// env::remove_var(key);
459
+ /// }
460
+ /// assert!(env::var(key).is_err());
406
461
/// ```
462
+ #[ cfg( not( bootstrap) ) ]
463
+ #[ rustc_deprecated_safe_2024]
464
+ #[ stable( feature = "env" , since = "1.0.0" ) ]
465
+ pub unsafe fn remove_var < K : AsRef < OsStr > > ( key : K ) {
466
+ _remove_var ( key. as_ref ( ) )
467
+ }
468
+
469
+ /// Removes an environment variable from the environment of the currently running process.
470
+ ///
471
+ /// # Safety
472
+ ///
473
+ /// This function is safe to call in a single-threaded program.
474
+ ///
475
+ /// In multi-threaded programs, you must ensure that are no other threads
476
+ /// concurrently writing or *reading*(!) from the environment through functions
477
+ /// other than the ones in this module. You are responsible for figuring out
478
+ /// how to achieve this, but we strongly suggest not using `set_var` or
479
+ /// `remove_var` in multi-threaded programs at all.
480
+ ///
481
+ /// Most C libraries, including libc itself do not advertise which functions
482
+ /// read from the environment. Even functions from the Rust standard library do
483
+ /// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`].
484
+ ///
485
+ /// Discussion of this unsafety on Unix may be found in:
486
+ ///
487
+ /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
488
+ /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
489
+ ///
490
+ /// [`std::net::ToSocketAddrs`]: crate::net::ToSocketAddrs
491
+ ///
492
+ /// # Panics
493
+ ///
494
+ /// This function may panic if `key` is empty, contains an ASCII equals sign
495
+ /// `'='` or the NUL character `'\0'`, or when the value contains the NUL
496
+ /// character.
497
+ ///
498
+ /// # Examples
499
+ ///
500
+ /// ```no_run
501
+ /// # #![allow(unused_unsafe)]
502
+ ///
407
503
/// use std::env;
408
504
///
409
505
/// let key = "KEY";
410
- /// env::set_var(key, "VALUE");
506
+ /// unsafe {
507
+ /// env::set_var(key, "VALUE");
508
+ /// }
411
509
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
412
510
///
413
- /// env::remove_var(key);
511
+ /// unsafe {
512
+ /// env::remove_var(key);
513
+ /// }
414
514
/// assert!(env::var(key).is_err());
415
515
/// ```
516
+ #[ cfg( bootstrap) ]
416
517
#[ stable( feature = "env" , since = "1.0.0" ) ]
417
518
pub fn remove_var < K : AsRef < OsStr > > ( key : K ) {
418
- _remove_var ( key. as_ref ( ) )
519
+ unsafe { _remove_var ( key. as_ref ( ) ) }
419
520
}
420
521
421
- fn _remove_var ( key : & OsStr ) {
522
+ unsafe fn _remove_var ( key : & OsStr ) {
422
523
os_imp:: unsetenv ( key)
423
524
. unwrap_or_else ( |e| panic ! ( "failed to remove environment variable `{key:?}`: {e}" ) )
424
525
}
0 commit comments