@@ -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+
3863rule_provides_crate_info_test = analysistest .make (_rule_provides_crate_info_test_impl )
3964rule_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
4174def _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+
86129def 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