Skip to content

Commit f31db8b

Browse files
authored
Don't leak default_shell_env into published CrateInfo.rustc_env (#3990)
Fixes #3989.
1 parent 6d85959 commit f31db8b

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

rust/private/rustc.bzl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,8 +1797,12 @@ def rustc_compile_action(
17971797
)
17981798

17991799
if crate_info_dict != None:
1800+
# Persist only rustc-specific env; the merged `env` above also carries
1801+
# ctx.configuration.default_shell_env, which must not leak through
1802+
# CrateInfo -- it would otherwise clobber cc_toolchain link_env in
1803+
# downstream rust_test(crate = ...) (see bazelbuild/rules_rust#3989).
18001804
crate_info_dict.update({
1801-
"rustc_env": env,
1805+
"rustc_env": env_from_args,
18021806
})
18031807
crate_info = rust_common.create_crate_info(
18041808
deps = depset(deps),

test/unit/crate_info/crate_info_test.bzl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,41 @@ def _rule_does_not_provide_crate_info_test_impl(ctx):
3535
)
3636
return analysistest.end(env)
3737

38+
# Sentinel injected via `--action_env` (see config_settings below). It enters
39+
# `ctx.configuration.default_shell_env` of the target under test; if the leak
40+
# regresses, it will surface inside `CrateInfo.rustc_env`.
41+
_LEAK_CANARY_KEY = "RULES_RUST_CRATE_INFO_LEAK_CANARY"
42+
_LEAK_CANARY_VALUE = "leaked"
43+
44+
def _crate_info_does_not_leak_default_shell_env_test_impl(ctx):
45+
env = analysistest.begin(ctx)
46+
tut = analysistest.target_under_test(env)
47+
crate_info = tut[rust_common.crate_info]
48+
49+
# Note: a structural "no key from default_shell_env appears in rustc_env"
50+
# check would false-positive on Windows, where `env_from_args` legitimately
51+
# carries cc_toolchain link_env values (PATH, ...) for crates that emit a
52+
# dylib (e.g. proc_macro). The canary is unambiguous: nothing except an
53+
# explicit --action_env produces it, so its presence proves a leak.
54+
asserts.false(
55+
env,
56+
_LEAK_CANARY_KEY in crate_info.rustc_env,
57+
("CrateInfo.rustc_env leaked default_shell_env: found key '{key}'. " +
58+
"See bazelbuild/rules_rust#3989.").format(key = _LEAK_CANARY_KEY),
59+
)
60+
61+
return analysistest.end(env)
62+
3863
rule_provides_crate_info_test = analysistest.make(_rule_provides_crate_info_test_impl)
3964
rule_does_not_provide_crate_info_test = analysistest.make(_rule_does_not_provide_crate_info_test_impl)
65+
crate_info_does_not_leak_default_shell_env_test = analysistest.make(
66+
_crate_info_does_not_leak_default_shell_env_test_impl,
67+
config_settings = {
68+
"//command_line_option:action_env": [
69+
"{}={}".format(_LEAK_CANARY_KEY, _LEAK_CANARY_VALUE),
70+
],
71+
},
72+
)
4073

4174
def _crate_info_test():
4275
rust_library(
@@ -83,6 +116,16 @@ def _crate_info_test():
83116
target_under_test = ":staticlib",
84117
)
85118

119+
crate_info_does_not_leak_default_shell_env_test(
120+
name = "rlib_crate_info_does_not_leak_default_shell_env_test",
121+
target_under_test = ":rlib",
122+
)
123+
124+
crate_info_does_not_leak_default_shell_env_test(
125+
name = "proc_macro_crate_info_does_not_leak_default_shell_env_test",
126+
target_under_test = ":proc_macro",
127+
)
128+
86129
def crate_info_test_suite(name):
87130
"""Entry-point macro called from the BUILD file.
88131
@@ -98,5 +141,7 @@ def crate_info_test_suite(name):
98141
":proc_macro_provides_crate_info_test",
99142
":cdylib_does_not_provide_crate_info_test",
100143
":staticlib_does_not_provide_crate_info_test",
144+
":rlib_crate_info_does_not_leak_default_shell_env_test",
145+
":proc_macro_crate_info_does_not_leak_default_shell_env_test",
101146
],
102147
)

0 commit comments

Comments
 (0)