Auto merge of #124636 - tbu-:pr_env_unsafe, r=petrochenkov · model-checking/verify-rust-std@ba98164 (original) (raw)
`@@ -318,22 +318,25 @@ 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.
`
325
``
`-
///
`
326
321
`/// This function is safe to call in a single-threaded program.
`
327
322
`///
`
328
``
`-
/// In multi-threaded programs, you must ensure that are no other threads
`
329
``
`-
/// concurrently writing or reading(!) from the environment through functions
`
330
``
`-
/// other than the ones in this module. You are responsible for figuring out
`
331
``
`` -
/// how to achieve this, but we strongly suggest not using set_var
or
``
332
``
`` -
/// remove_var
in multi-threaded programs at all.
``
333
``
`-
///
`
334
``
`-
/// Most C libraries, including libc itself do not advertise which functions
`
335
``
`-
/// read from the environment. Even functions from the Rust standard library do
`
336
``
`` -
/// that, e.g. for DNS lookups from [std:🥅:ToSocketAddrs
].
``
``
323
`+
/// This function is also always safe to call on Windows, in single-threaded
`
``
324
`+
/// and multi-threaded programs.
`
``
325
`+
///
`
``
326
`+
/// In multi-threaded programs on other operating systems, we strongly suggest
`
``
327
`` +
/// not using set_var
or remove_var
at all. The exact requirement is: you
``
``
328
`+
/// must ensure that there are no other threads concurrently writing or
`
``
329
`+
/// reading(!) the environment through functions or global variables other
`
``
330
`+
/// than the ones in this module. The problem is that these operating systems
`
``
331
`+
/// do not provide a thread-safe way to read the environment, and most C
`
``
332
`+
/// libraries, including libc itself, do not advertise which functions read
`
``
333
`+
/// from the environment. Even functions from the Rust standard library may
`
``
334
`+
/// read the environment without going through this module, e.g. for DNS
`
``
335
`` +
/// lookups from [std:🥅:ToSocketAddrs
]. No stable guarantee is made about
``
``
336
`+
/// which functions may read from the environment in future versions of a
`
``
337
`+
/// library. All this makes it not practically possible for you to guarantee
`
``
338
`+
/// that no other thread will read the environment, so the only safe option is
`
``
339
`` +
/// to not use set_var
or remove_var
in multi-threaded programs at all.
``
337
340
`///
`
338
341
`/// Discussion of this unsafety on Unix may be found in:
`
339
342
`///
`
`@@ -353,15 +356,26 @@ impl Error for VarError {
`
353
356
`/// use std::env;
`
354
357
`///
`
355
358
`/// let key = "KEY";
`
356
``
`-
/// env::set_var(key, "VALUE");
`
``
359
`+
/// unsafe {
`
``
360
`+
/// env::set_var(key, "VALUE");
`
``
361
`+
/// }
`
357
362
`/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
`
358
363
```` /// ```
``
`364`
`+
#[cfg(not(bootstrap))]
`
``
`365`
`+
#[rustc_deprecated_safe_2024]
`
`359`
`366`
`#[stable(feature = "env", since = "1.0.0")]
`
`360`
``
`-
pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
`
``
`367`
`+
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
`
`361`
`368`
`_set_var(key.as_ref(), value.as_ref())
`
`362`
`369`
`}
`
`363`
`370`
``
`364`
``
`-
fn _set_var(key: &OsStr, value: &OsStr) {
`
``
`371`
`+
#[cfg(bootstrap)]
`
``
`372`
`+
#[allow(missing_docs)]
`
``
`373`
`+
#[stable(feature = "env", since = "1.0.0")]
`
``
`374`
`+
pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
`
``
`375`
`+
unsafe { _set_var(key.as_ref(), value.as_ref()) }
`
``
`376`
`+
}
`
``
`377`
`+`
``
`378`
`+
unsafe fn _set_var(key: &OsStr, value: &OsStr) {
`
`365`
`379`
` os_imp::setenv(key, value).unwrap_or_else(|e| {
`
`366`
`380`
`` panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
``
`367`
`381`
`})
`
`@@ -371,22 +385,25 @@ fn _set_var(key: &OsStr, value: &OsStr) {
`
`371`
`385`
`///
`
`372`
`386`
`/// # Safety
`
`373`
`387`
`///
`
`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`
`388`
`/// This function is safe to call in a single-threaded program.
`
`380`
`389`
`///
`
`381`
``
`-
/// In multi-threaded programs, you must ensure that are no other threads
`
`382`
``
`-
/// concurrently writing or *reading*(!) from the environment through functions
`
`383`
``
`-
/// other than the ones in this module. You are responsible for figuring out
`
`384`
``
`` -
/// how to achieve this, but we strongly suggest not using `set_var` or
``
`385`
``
`` -
/// `remove_var` in multi-threaded programs at all.
``
`386`
``
`-
///
`
`387`
``
`-
/// Most C libraries, including libc itself do not advertise which functions
`
`388`
``
`-
/// read from the environment. Even functions from the Rust standard library do
`
`389`
``
`` -
/// that, e.g. for DNS lookups from [`std:🥅:ToSocketAddrs`].
``
``
`390`
`+
/// This function is also always safe to call on Windows, in single-threaded
`
``
`391`
`+
/// and multi-threaded programs.
`
``
`392`
`+
///
`
``
`393`
`+
/// In multi-threaded programs on other operating systems, we strongly suggest
`
``
`394`
`` +
/// not using `set_var` or `remove_var` at all. The exact requirement is: you
``
``
`395`
`+
/// must ensure that there are no other threads concurrently writing or
`
``
`396`
`+
/// *reading*(!) the environment through functions or global variables other
`
``
`397`
`+
/// than the ones in this module. The problem is that these operating systems
`
``
`398`
`+
/// do not provide a thread-safe way to read the environment, and most C
`
``
`399`
`+
/// libraries, including libc itself, do not advertise which functions read
`
``
`400`
`+
/// from the environment. Even functions from the Rust standard library may
`
``
`401`
`+
/// read the environment without going through this module, e.g. for DNS
`
``
`402`
`` +
/// lookups from [`std:🥅:ToSocketAddrs`]. No stable guarantee is made about
``
``
`403`
`+
/// which functions may read from the environment in future versions of a
`
``
`404`
`+
/// library. All this makes it not practically possible for you to guarantee
`
``
`405`
`+
/// that no other thread will read the environment, so the only safe option is
`
``
`406`
`` +
/// to not use `set_var` or `remove_var` in multi-threaded programs at all.
``
`390`
`407`
`///
`
`391`
`408`
`/// Discussion of this unsafety on Unix may be found in:
`
`392`
`409`
`///
`
`@@ -403,22 +420,35 @@ fn _set_var(key: &OsStr, value: &OsStr) {
`
`403`
`420`
`///
`
`404`
`421`
`/// # Examples
`
`405`
`422`
`///
`
`406`
``
```` -
/// ```
``
423
/// ```no_run
407
424
`/// use std::env;
`
408
425
`///
`
409
426
`/// let key = "KEY";
`
410
``
`-
/// env::set_var(key, "VALUE");
`
``
427
`+
/// unsafe {
`
``
428
`+
/// env::set_var(key, "VALUE");
`
``
429
`+
/// }
`
411
430
`/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
`
412
431
`///
`
413
``
`-
/// env::remove_var(key);
`
``
432
`+
/// unsafe {
`
``
433
`+
/// env::remove_var(key);
`
``
434
`+
/// }
`
414
435
`/// assert!(env::var(key).is_err());
`
415
436
```` /// ```
````
``
437
`+
#[cfg(not(bootstrap))]
`
``
438
`+
#[rustc_deprecated_safe_2024]
`
416
439
`#[stable(feature = "env", since = "1.0.0")]
`
417
``
`-
pub fn remove_var<K: AsRef>(key: K) {
`
``
440
`+
pub unsafe fn remove_var<K: AsRef>(key: K) {
`
418
441
`_remove_var(key.as_ref())
`
419
442
`}
`
420
443
``
421
``
`-
fn _remove_var(key: &OsStr) {
`
``
444
`+
#[cfg(bootstrap)]
`
``
445
`+
#[allow(missing_docs)]
`
``
446
`+
#[stable(feature = "env", since = "1.0.0")]
`
``
447
`+
pub fn remove_var<K: AsRef>(key: K) {
`
``
448
`+
unsafe { _remove_var(key.as_ref()) }
`
``
449
`+
}
`
``
450
+
``
451
`+
unsafe fn _remove_var(key: &OsStr) {
`
422
452
` os_imp::unsetenv(key)
`
423
453
`` .unwrap_or_else(|e| panic!("failed to remove environment variable {key:?}
: {e}"))
``
424
454
`}
`