Skip to content

Make std::env::{set_var, remove_var} unsafe in edition 2024#124636

Merged
bors merged 4 commits into
rust-lang:masterfrom
tbu-:pr_env_unsafe
May 30, 2024
Merged

Make std::env::{set_var, remove_var} unsafe in edition 2024#124636
bors merged 4 commits into
rust-lang:masterfrom
tbu-:pr_env_unsafe

Conversation

@tbu-

@tbu- tbu- commented May 2, 2024

Copy link
Copy Markdown
Contributor

Allow calling these functions without unsafe blocks in editions up until 2021, but don't trigger the unused_unsafe lint for unsafe blocks containing these functions.

Fixes #27970.
Fixes #90308.
CC #124866.

@rustbot

rustbot commented May 2, 2024

Copy link
Copy Markdown
Collaborator

r? @joboet

rustbot has assigned @joboet.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc O-hermit Operating System: Hermit O-SGX Target: SGX O-solid Operating System: SOLID O-unix Operating system: Unix-like O-wasi Operating system: Wasi, Webassembly System Interface O-windows Operating system: Windows S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels May 2, 2024
@rustbot

rustbot commented May 2, 2024

Copy link
Copy Markdown
Collaborator

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

Some changes occurred in src/tools/compiletest

cc @jieyouxu

The Miri subtree was changed

cc @rust-lang/miri

@rust-log-analyzer

This comment has been minimized.

@rustbot

rustbot commented May 2, 2024

Copy link
Copy Markdown
Collaborator

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

The Miri subtree was changed

cc @rust-lang/miri

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Some changes occurred in src/tools/compiletest

cc @jieyouxu

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@RalfJung

RalfJung commented May 3, 2024

Copy link
Copy Markdown
Member

Should there be a warning on older editions, to make this not come entirely out of the blue when doing edition migration?

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@tbu-

tbu- commented May 3, 2024

Copy link
Copy Markdown
Contributor Author

Should there be a warning on older editions, to make this not come entirely out of the blue when doing edition migration?

I agree that this would be quite useful. It seems hard to do right now, though, because a stage 0 compiler will detect a lot of unused unsafe blocks because it doesn't know about the std::env::set_var unsafety. Perhaps this could be postponed until after one bootstrap cycle?

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@RalfJung

RalfJung commented May 3, 2024

Copy link
Copy Markdown
Member

I agree that this would be quite useful. It seems hard to do right now, though, because a stage 0 compiler will detect a lot of unused unsafe blocks because it doesn't know about the std::env::set_var unsafety. Perhaps this could be postponed until after one bootstrap cycle?

I wasn't talking about unused_unsafe, but a lint that warns against using set_var/remove_var outside an unsafe block on old editions.

Also, I am not sure if it's the best idea to add new lang items for these functions. In the past the proposal was to add an attribute for "deprecating safety". Then we could e.g. also add that attribute to before_exec.

@BoxyUwU

BoxyUwU commented Jun 27, 2024

Copy link
Copy Markdown
Member

This had the relnotes label added but as far as I can tell this only affects 2024 edition. Is that understanding correct or is there a subtle stable affecting change here :3

@beetrees

beetrees commented Jun 27, 2024

Copy link
Copy Markdown
Contributor

There is a change affecting other editions: the std::env::{set_var,remove_var} functions can no longer be converted to safe function pointers in any edition. For example, both of the following examples compile on current stable but not on current nightly:

use std::ffi::OsString;

fn main() {
	let x: fn(OsString, OsString) = std::env::set_var;
}

and

use std::ffi::OsString;

fn f(x: impl Fn(OsString, OsString)) {}

fn main() {
	f(std::env::set_var);
}

call to deprecated safe function `{$function}` is unsafe and requires unsafe block
.note = consult the function's documentation for information on how to avoid undefined behavior
.label = call to unsafe function
.suggestion = you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be incorrect if we mark any other functions with this attribute where the unsafety is for a different reason.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it'll be fixed before #125970 is merged. This PR was intentionally minimal so it could definitely make it into the Rust 2024 edition.

@joshtriplett

Copy link
Copy Markdown
Member

@beetrees Yikes, that doesn't seem right. That sounds like a bug in the implementation of rustc_deprecated_safe_2024; If you're allowed to treat the function as safe, you should be allowed to do anything with it you could have with a safe function, including passing it as an argument.

@RalfJung

RalfJung commented Jun 27, 2024 via email

Copy link
Copy Markdown
Member

@cuviper

cuviper commented Jun 28, 2024

Copy link
Copy Markdown
Member

For safe function pointers, a workaround is that you can wrap them in a safe closure.

let x: fn(OsString, OsString) = |name, value| std::env::set_var(name, value);

It's unfortunate, but maybe someone will figure out how to make this unnecessary later. Or it will just become moot after everyone migrates to 2024+ and they really are unsafe.

Comment thread library/std/src/env.rs
Comment on lines +338 to +339
/// that no other thread will read the environment, so the only safe option is
/// to not use `set_var` or `remove_var` in multi-threaded programs at all.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the only safe option is to not use set_var or remove_var in multi-threaded programs at all

Can't we use a static Mutex to guard env reads and writes? If so, saying that "the only option is not to use this" sounds misleading.

@ChrisDenton ChrisDenton Feb 20, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we cannot. There's a lot of discussion about that on the linked issues but in short that would only make it safe for people sharing the same Mutex and then only if all FFI was guarded by that Mutex (because any libc function is allowed to read the environment).

Comment thread library/std/src/env.rs
/// # Examples
///
/// ```
/// ```no_run

@RalfJung RalfJung May 12, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would have been good to add a comment explaining why this is no_run. Are you worried about UB in the doctest?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm worried about that. The doctest has no safety documentation, and I wouldn't know how I could prove that no other thread is running concurrently to it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not safe to use in a doctest. We would need to use an integration test.

A doctest could work on platforms where set_var is thread safe but I'm not sure there's much utility in a test only for those platforms if we can have something that works cross-platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. merged-by-bors This PR was explicitly merged by bors. O-hermit Operating System: Hermit O-SGX Target: SGX O-solid Operating System: SOLID O-unix Operating system: Unix-like O-wasi Operating system: Wasi, Webassembly System Interface O-windows Operating system: Windows relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet