Give run_git's config nulls a witness no -c reaches (improvise-3j70)

GIT_CONFIG_GLOBAL=/dev/null and GIT_CONFIG_NOSYSTEM=1 in run_git were
witnessed by a config excludesFile, which vwjj's -c
core.excludesFile=/dev/null outranks. So dropping either line passed
every test from vwjj onwards.

The hostile child's config, read as both GIT_CONFIG_GLOBAL and
GIT_CONFIG_SYSTEM, now also sets core.sharedRepository = nonsense.
Measured on git 2.55: git init and git add die on it, git ls-files
does not read it (so the walk, which does not null the user's config,
is unaffected), and run_git passes no -c for it. init.defaultObjectFormat
and init.defaultRefFormat were tried first; they only warn.

Dropping either env line is now red. Every other rival in the combined
test is unchanged, and there is still one child per test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-23 18:32:41 -07:00
parent 5b8bdc19b1
commit 12a92a8669
2 changed files with 26 additions and 3 deletions
+23 -1
View File
@@ -510,7 +510,7 @@ improvise-eahe. Each section below it once had a test of its own, and each of th
**The ones green before are green now.**
- `GIT_ICASE_PATHSPECS` is green, as its section explains.
- The prefix minus `GIT_TRACE2_EVENT` is green, because the `0` override covers it. It was red against the per-setting test at ddcdf93a, before #276 added the override.
- **Dropping `GIT_CONFIG_GLOBAL=/dev/null` or `GIT_CONFIG_NOSYSTEM=1` is green, both at #276's head and here.** Their witness is an excludes line, and vwjj's `-c core.excludesFile=/dev/null` outranks every config file, so the witness cannot see them. Consolidation did not cause this. It is filed as improvise-3j70.
- **Dropping `GIT_CONFIG_GLOBAL=/dev/null` or `GIT_CONFIG_NOSYSTEM=1` was green, both at #276's head and in eahe's first version.** Their witness was an excludes line, and vwjj's `-c core.excludesFile=/dev/null` outranks every config file, so the witness could not see them. Consolidation did not cause this. improvise-3j70 has since given them a witness that no `-c` reaches (see “The user's global and system excludes” below), and both rivals are red.
**Measured** on an Apple M4 Max (16 cores), three `cargo test --workspace` runs each, before and after. The median counts only binaries that ran a test:
@@ -576,6 +576,28 @@ Rivals:
- Drop `GIT_CONFIG_NOSYSTEM=1`: red, in the system run. The system scope is
there so that this half of the fix has a witness at all.
**Both rivals later went green, and nothing noticed (improvise-3j70).**
improvise-vwjj added `-c core.excludesFile=/dev/null` to `run_git`, and a `-c`
argument outranks every config file. So a global or system `excludesFile` could
no longer reach `git add` whether or not the config was nulled, and the two
rivals above passed from vwjj onwards. The config lines were still worth having,
since they null every *other* key, but nothing pinned them.
The witness is now a second key in the same config, `core.sharedRepository =
nonsense`. Measured on git 2.55:
- `git init` and `git add` die on it (`fatal: bad boolean config value
'nonsense' for 'core.sharedrepository'`);
- `git ls-files` does not read it, so the walk itself, which does not null the
user's config, is unaffected;
- `run_git` passes no `-c` for it.
Two keys were tried first and rejected: `init.defaultObjectFormat` and
`init.defaultRefFormat` only **warn** on an unknown value, so `init` carries on.
The key sits in `a_hostile_git_environment_changes_nothing`'s config, which the
child reads as both `GIT_CONFIG_GLOBAL` and `GIT_CONFIG_SYSTEM`, so there is
still one child. Dropping either env line is red. Every other rival in the
combined test is unchanged.
### The user's default ignore and attributes files (improvise-vwjj)
improvise-vwjj, found reviewing PR #248 at `f5cfc7ed`. The test above sets
+3 -2
View File
@@ -223,9 +223,10 @@ fn a_hostile_git_environment_changes_nothing() {
let excludes = home.path().join("ignore");
std::fs::write(&excludes, "*.gz\n").expect("writes");
let config = home.path().join("gitconfig");
// improvise-vav0: the same config also sends every trace2 target to stdout.
// vav0: trace2 targets go to stdout. 3j70: a bad sharedRepository kills `init`
// and `add` but not `ls-files`, and no `-c` in run_git overrides it.
let text = format!(
"[core]\n\texcludesFile = {}\n[trace2]\n\tnormalTarget = /dev/stdout\n\teventTarget = /dev/stdout\n\tperfTarget = /dev/stdout\n",
"[core]\n\texcludesFile = {}\n[trace2]\n\tnormalTarget = /dev/stdout\n\teventTarget = /dev/stdout\n\tperfTarget = /dev/stdout\n[core]\n\tsharedRepository = nonsense\n",
excludes.display()
);
std::fs::write(&config, text).expect("writes");