Skip to content

run-command: avoid NULL dereference for missing Windows shell - #6358

Draft
slix wants to merge 1 commit into
git-for-windows:mainfrom
slix:fix-missing-shell-path
Draft

run-command: avoid NULL dereference for missing Windows shell#6358
slix wants to merge 1 commit into
git-for-windows:mainfrom
slix:fix-missing-shell-path

Conversation

@slix

@slix slix commented Aug 4, 2026

Copy link
Copy Markdown

Summary

On native Windows, git_shell_path() assumes that locate_in_PATH("sh")
always succeeds and passes its result directly to convert_slashes(). If
sh is absent from PATH, the lookup returns NULL and Git terminates
with an access violation.

Check the lookup result and report a fatal error instead:

fatal: cannot find 'sh' in PATH

This prevents the NULL dereference. It does not add a shell fallback, so
commands requiring a shell still fail when no shell is available.

Crash analysis

The failure was reproduced in git-remote-https.exe from Git for Windows
2.55.0.windows.3. ProcDump captured the unhandled exception:

Process:               git-remote-https.exe (97196)
Process image:         C:\Program Files\Git\mingw64\libexec\git-core\git-remote-https.exe
Exception monitor:     Unhandled

[21:32:43]Exception: C0000005.ACCESS_VIOLATION
[21:32:43]Unhandled: C0000005.ACCESS_VIOLATION
[21:32:43]Dump 1 initiated: D:\Libraries\Downloads\git-remote-https-crash.dmp
[21:32:44]Dump 1 writing: Estimated dump file size is 47 MB.
[21:32:44]Dump 1 complete: 47 MB written in 0.6 seconds

The dump confirms that the faulting instruction attempted to read through
RAX while RAX was zero:

C0000005.ACCESS_VIOLATION
RAX=0000000000000000
movzx edx, byte ptr [rax]

Correlation of the surrounding disassembly with the source shows it
loading "sh", performing the PATH lookup, and then entering the slash
conversion. This matches the native Windows implementation:

char *p = locate_in_PATH("sh");
convert_slashes(p);

The reproduced missing-sh condition therefore leaves p as NULL,
which is dereferenced by convert_slashes().

Regression test

Add a MINGW-only regression test that clears PATH inside
test-tool run-command, calls git_shell_path(), and verifies that Git
reports the controlled fatal diagnostic instead of crashing.

The helper clears PATH after process startup, making the missing-shell
condition deterministic without depending on Windows startup PATH
reconstruction.

Testing

Passed:

  • git diff --check
  • Shell syntax check for t/t0061-run-command.sh
  • Added-line formatting and commit-message checks

The native Windows test suite was not run locally because a Git for
Windows SDK/compiler was unavailable in the test environment. Windows CI
is expected to build the change and run t0061-run-command.sh.
codex-clipboard-d4f6fbaa-5f73-4e36-8923-acc0596047db

When Git's native Windows environment omits its usr/bin directory from
PATH, locate_in_PATH("sh") returns NULL. git_shell_path() passes that value
to convert_slashes(), causing git-remote-https.exe to terminate with an
access violation while preparing a credential helper.

Report the missing shell as a fatal Git error instead. This avoids the
NULL-pointer dereference and adds a Windows-only regression test that
clears PATH inside test-tool and verifies the diagnostic.

Signed-off-by: Peter Kowalczyk <peter@slix.io>
@dscho

dscho commented Aug 4, 2026

Copy link
Copy Markdown
Member

On native Windows, git_shell_path() assumes that locate_in_PATH("sh")
always succeeds and passes its result directly to convert_slashes(). If
sh is absent from PATH, the lookup returns NULL and Git terminates
with an access violation.

Running Git for Windows in an environment where sh is absent from the PATH is an unsupported scenario. git.exe specifically ensures that /usr/bin/ (where sh.exe resides unless you willfully remove it, and with it, remove yourself from any supported use case) is present in the PATH. The git-remote-https.exe helper is private to Git, and its only supported use is by being called from git.exe. Therefore, sh.exe is always guaranteed to be in the PATH when git-remote-https.exe is running, unless the installation has been corrupted.

Therefore, this PR looks like a fix for something that is not considered a bug, but an incorrect usage of git-remote-https.exe.

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.

2 participants