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

`}

`