Repository navigation
M1.c U1a: the probe build runs a concrete, identified toolchain under a constructed environment - #12496
M1.c U1a: the probe build runs a concrete, identified toolchain under a constructed environment#12496briansrls wants to merge 1 commit into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31744cb4a0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let Some(cargo_home) = | ||
| value("CARGO_HOME").or_else(|| value("HOME").map(|h| h.join(".cargo"))) | ||
| { | ||
| candidates.push(cargo_home.join("config")); | ||
| candidates.push(cargo_home.join("config.toml")); |
There was a problem hiding this comment.
Resolve relative CARGO_HOME from the crate directory
When CARGO_HOME is relative, Cargo resolves it from the child command's working directory (crate_dir), but this observer resolves the candidate against the host process's current directory. Cargo 1.93 accepts this form and reads <crate_dir>/<CARGO_HOME>/config.toml; consequently, changing that file can change the executable while this code continues to report no configuration and the same environment digest. Resolve relative CARGO_HOME against crate_dir before hashing its configuration.
Useful? React with 👍 / 👎.
| let invocation_cargo_path = invocation.cargo_path.clone(); | ||
| let invocation_cargo_identity = invocation.cargo_identity.clone(); | ||
| let invocation_environment_names = invocation.environment_names.clone(); | ||
| let invocation_environment_digest = invocation.environment_digest.clone(); | ||
| let invocation_cargo_configuration = invocation.cargo_configuration.clone(); |
There was a problem hiding this comment.
Capture build inputs from the command that actually runs
When an admitted environment value, Cargo configuration, or toolchain changes between this preflight resolution and the build, these copied fields describe the first resolution, while run_cargo below independently calls probe_cargo_command again and executes the second. The new build inputs line can therefore report paths and digests for a command that never ran, defeating its provenance purpose; carry the already-bound command and invocation into execution, or return the actual invocation from run_cargo.
Useful? React with 👍 / 👎.
… a constructed environment M1.c keys a stored compiler on the inputs that produce its bytes, so nothing the build can see may sit outside the key: - The environment is cleared and rebuilt from the exact names in v2.extdeps.languages.rust rust_host_build_environment (PATH, HOME, TMPDIR, CARGO_HOME, RUSTUP_HOME, RUSTUP_TOOLCHAIN), with a SHA-256 over the length-framed names and values. Ambient CARGO_PROFILE_*, CARGO_INCREMENTAL, RUSTC_BOOTSTRAP, CC and the like can no longer reach the build. - The entry compiler (RUSTC or PATH, usually a rustup proxy) is asked for its sysroot. The build then runs that sysroot's own cargo, never $CARGO or a PATH lookup at spawn time, and binds RUSTC to that sysroot's own rustc. Both are identified (-vV / -Vv) under the build's environment, from the crate's directory. - Every cargo configuration file discovery would read is recorded with a streamed digest; an unreadable one refuses. - The streamed digest has one home (emitted_closure_compile_host sha256_feed_file), and the native lane runner reads through it. The facts print on the route's build-inputs line until U7 carries them in the receipt. Controls: exact-name allowlist asserted on the constructed value; the spawn runs the toolchain's cargo even with CARGO planted; configuration observed, and an unreadable file refuses; a sysroot without cargo refuses. Wet (operator receipt): the same crate built at one path with and without planted CARGO_PROFILE_RELEASE_OPT_LEVEL/DEBUG and CARGO_INCREMENTAL gives identical bytes. RED: with env_clear removed, the bytes differ. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
31744cb to
0c5d1a0
Compare
M1.c U1a. Stacked on #12474 (U2); review that first. M1.c is native-compiler cross-run reuse, whose delivery the operator assigned to this lane on 2026-09-27, with U0–U2 admitted against pinned base
eb5987e38f5.M1.c will key a stored compiler on the inputs that produce its bytes. So every input the probe build can see must either be in the key or be unable to reach the build. Before this PR:
$CARGOorcargoon PATH resolved at spawn time;RUSTCwas usually a rustup proxy.As a result, an ambient
CARGO_PROFILE_*,CARGO_INCREMENTAL,RUSTC_BOOTSTRAPorCCcould change the executable under an unchanged key, and the receipt named the proxy rather than the compiler that ran.Changes (
v1_compiler.emitted_closure_compile_host)v2.extdeps.languages.rustrust_host_build_environment:PATH, HOME, TMPDIR, CARGO_HOME, RUSTUP_HOME, RUSTUP_TOOLCHAIN. A SHA-256 is taken over the length-framed names and values. The identity probes run under the same environment.RUSTCor PATH) is asked--print sysroot. The build then runs that sysroot's owncargo, bound to that sysroot's ownrustc. Both are identified (-vV/-Vv) from the crate's directory. A sysroot with no cargo refuses withProbeToolchainUnresolved..cargo/config[.toml], thenCARGO_HOME) is recorded with a streamed digest. An unreadable one refuses withCargoConfigurationUnreadable.sha256_feed_file/sha256_file_streamed, moved here from the native lane runner, which reads through it.build inputsline. U7 carries them into the receipt, and U3 reads them into the key.RUSTFLAGSand admission are unchanged. The cargo spawn and the self-host receipt now name the real sysrootrustcrather than the proxy.Controls
CARGO_PROFILE_RELEASE_OPT_LEVEL,CARGO_INCREMENTAL,RUSTC_BOOTSTRAP,CC,CARGO_BUILD_TARGET,RUSTFLAGS,CARGO_HOME_EXTRAall excluded; the digest changes with an admitted value and not with a foreign oneCARGO=/planted/cargoCARGO_HOMEobserved with digests; a mode-000 file refusesCARGO_PROFILE_RELEASE_OPT_LEVEL=0,CARGO_PROFILE_RELEASE_DEBUG=true,CARGO_INCREMENTAL=1→ identical bytes#[ignore]receiptenv_clearlocally removed → the bytes differ (4399e0…vs339f80…)-p v1-compiler --all-targets -D warningstools.seed_growth_change_population mainover the committed diff (U2+U1a)Real path (the pairing obligation).
gunbc test //gunbc/instruments:self-hostwith the U1a seed, on a git-archive snapshot of this commit, exit 0 in 19m04s:argv[0]=<sysroot>/bin/cargoandcompiler=<sysroot>/bin/rustc, withenvironment_names=["HOME","PATH"]andcargo_configuration=[];closure=18eae89c…f070is unchanged;binary=f2b32eb5…still differs from another run's (960f4ee6…), because build paths reach the bytes. That is U1c.Stated divergence (not a fork)
v1_compiler.v1_interpreteremit_host_constructed_build_environment,emit_host_cargo_configuration_digestandobserve_tool_identityanswer the same questions for the emit-host transport, but with a 64-bit non-cryptographic hash and whole-file reads. This host needs SHA-256 over streamed bytes for a cross-run key.Trigger for unifying them:
extdeps.realization.emit_on_demand_hostResolvedBuildContextmoving to a cryptographicstd.content_hashfamily. The admitted-name list is a seed copy of the.dagrow. Its executing drift control is the U7 admission clause, and until then it rests on review diligence. This is recorded ingunbc.native_compiler_reuse_seed_growth.Not in this PR
--locked, fetch.🤖 Generated with Claude Code