Skip to content

Don't leak default_shell_env into published CrateInfo.rustc_env#3990

Open
JSGette wants to merge 1 commit intobazelbuild:mainfrom
JSGette:fix/crateinfo-env-leak
Open

Don't leak default_shell_env into published CrateInfo.rustc_env#3990
JSGette wants to merge 1 commit intobazelbuild:mainfrom
JSGette:fix/crateinfo-env-leak

Conversation

@JSGette
Copy link
Copy Markdown

@JSGette JSGette commented Apr 24, 2026

Fixes #3989.

At the tail of rustc_compile_action, CrateInfo is re-created with
rustc_env = env. But env was built as `dict(default_shell_env) +
env_from_args`, so it carries the host's default_shell_env (PATH, LIB,
INCLUDE, ...) on top of the rustc-specific env.

Every downstream consumer that inherits crate_info.rustc_env (notably
rust_test(crate = ...)) then picks up the host env, and at its own
compile time the inherited values clobber cc_toolchain's link_env --
construct_arguments applies link_env first (~L1183) and
crate_info.rustc_env after.

Persisting only env_from_args keeps CrateInfo honest: Bazel re-injects
default_shell_env at action execution anyway, so there is no reason to
bake it into provider state.

Fixes bazelbuild#3989.
gh-worker-dd-mergequeue-cf854d Bot pushed a commit to DataDog/datadog-agent that referenced this pull request Apr 24, 2026
…tch (#49862)

### What does this PR do?

Removes the global `--action_env=PATH=...` / `--host_action_env=PATH=...` from the `bazel:test:windows-amd64` GitLab job, and replaces it with a scoped fix to `rules_rust` applied via `MODULE.bazel`.

Concrete changes:

- `.gitlab/build/bazel/test.yml`: drop the `--action_env=PATH` and `--host_action_env=PATH` overrides from the Windows test job.
- `MODULE.bazel`: apply `bazel/patches/rules_rust-crateinfo-env-leak.patch` on top of the pinned `rules_rust` commit.
- `bazel/patches/rules_rust-crateinfo-env-leak.patch`: stops `rustc_compile_action` (`rust/private/rustc.bzl`) from publishing `ctx.configuration.default_shell_env` into `CrateInfo.rustc_env`. Only `env_from_args` (the rustc-specific env) is persisted; Bazel re-injects `default_shell_env` at action execution anyway, so nothing is lost.
- `.bazelrc`: leave commented-out `--@rules_rust//rust/settings:extra_rustc_env=PATH=...` / `extra_exec_rustc_env` hints near the other Windows-specific settings, as documentation for the fallback knob if a scoped PATH injection ever becomes necessary again.
- `MODULE.bazel.lock`: regenerated to reflect the patched `rules_rust`.

### Motivation

The previous `--action_env=PATH=C:/tools/msys64/mingw64/bin;...` was needed because `rustc` actions on Windows-GNU were ending up with a `PATH` that didn't include `mingw64/bin` — linking of `rust_test(crate = ...)` targets failed with `collect2.exe` unable to locate MinGW runtime DLLs.

Root cause (debugged in detail — see bazelbuild/rules_rust#3989): at the tail of `rustc_compile_action`, `CrateInfo` was re-created with `rustc_env = env`, where `env = dict(default_shell_env) + env_from_args`. That baked host environment variables (including a Windows-native `PATH` without `mingw64/bin`) into the provider. Downstream `rust_test(crate = :lib)` inherited the polluted `rustc_env`, and in the test's own rustc action it overwrote the correct `PATH` that `cc_toolchain.link_env` had just supplied via `construct_arguments` — silently clobbering the C++ toolchain's env contract.

`--action_env=PATH=...` worked around this by making `default_shell_env`'s `PATH` happen to contain `mingw64/bin`, but:

- It invalidates the global action cache any time the value changes (or when adding/removing any env var pinned alongside it).
- It leaks a host-specific path into every action's environment, not just Rust's.
- It masks the underlying `rules_rust` bug for everyone in the repo.

The in-tree patch fixes the root cause (scoped to Rust actions only), and the existing `-Clinker=<abs>` / `-Cdlltool=<abs>` flags in `rust.repository_set` (already on `main`) keep rlib compile actions working without needing `mingw64/bin` on `PATH`.

Upstream tracking:

- Issue: bazelbuild/rules_rust#3989
- PR with the same fix: bazelbuild/rules_rust#3990

Once the fix lands and we bump `rules_rust`, `bazel/patches/rules_rust-crateinfo-env-leak.patch` and the `patches = [...]` entry in `MODULE.bazel` can be removed.

### Describe how you validated your changes

- `bazel test //comp/core/log/rust/...` and `//pkg/procmgr/rust/...` pass on Windows without `--action_env=PATH`. Without the patch these fail at link time with `collect2.exe` errors, reproducing the pre-patch symptom.
- `bazel:test:windows-amd64` GitLab job on this PR (pipeline [109481274](https://gitlab.ddbuild.io/DataDog/datadog-agent/-/jobs/1627555041)).
- Linux and macOS are unaffected (the leak exists but has nothing to clobber — most `cc_toolchain`s don't set `env_set` on link actions).

### Additional Notes

- No agent binary behavior changes — build-system-only.
- The commented-out `extra_rustc_env` lines in `.bazelrc` are intentional: they document the scoped-PATH injection path as a fallback knob in case anyone hits a similar issue again before we can drop the patch.
- Related upstream: comment on bazelbuild/rules_rust#3785 noting an adjacent gap (rlib compile actions don't receive `cc_toolchain.link_env` at all — currently worked around by the `-Clinker`/`-Cdlltool` absolute paths).


Co-authored-by: joseph.gette <joseph.gette@datadoghq.com>
Copy link
Copy Markdown
Collaborator

@UebelAndre UebelAndre left a comment

Choose a reason for hiding this comment

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

Thanks! Can you add a unit test for this somewhere in //test/unit?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rustc_compile_action leaks default_shell_env into published CrateInfo.rustc_env, clobbering cc_toolchain link_env in downstream rust_test(crate = ...)

2 participants