From: "Priedhorsky, Reid" <reidpr@lanl.gov>
To: "git@vger.kernel.org" <git@vger.kernel.org>
Subject: bug? subprocesses can use wrong Git if $PATH is unset
Date: Thu, 1 Jun 2023 22:21:05 +0000 [thread overview]
Message-ID: <E7D87B07-C416-4A58-8726-CCDA0907AC66@lanl.gov> (raw)
Hello,
I may have found a bug in Git. It seems that if (1) multiple git(1) are installed on the system, (2) one is in the shell’s default path (i.e., used if $PATH is unset, not the default value of $PATH), and (3) the desired git(1) is at a different path, then subprocesses of the desired git(1) invoke the undesired git(1) instead.
$PATH unset is indeed a pathological situation; one of our own bugs in our software that calls git(1) inappropriately cleared it. However, in my view it’s surprising enough to be a usability bug. I would expect git(1) to call itself for subprocesses regardless of the environment.
> Thank you for filling out a Git bug report!
> Please answer the following questions to help us understand your issue.
>
> What did you do before the bug happened? (Steps to reproduce your issue)
1. If /usr/bin/git exists, move it out of the way.
2. Write a shell script at /usr/bin/git that prints an error message and then fails.
3. Install a different Git at prefix other than /usr and put it in your path before /usr/bin.
4. Run the following Python script. (It’s Python because I know how to manipulate the environment how I wanted, and I don’t in shell.)
~~~~
#!/usr/bin/env python3
import os
import subprocess
import sys
def chdir(p):
print("", file=sys.stderr)
print("$ cd %s" % p, file=sys.stderr)
os.chdir(p)
def c(msg, argv, **kwargs):
print("", file=sys.stderr)
print("# " + msg, file=sys.stderr)
print("$ " + " ".join(argv), file=sys.stderr)
try:
subprocess.run(argv, check=True, **kwargs)
except subprocess.CalledProcessError as x:
print("# command failed with exit code %d" % x.returncode)
else:
print("# success")
c("fake system Git contents", ["cat", "/usr/bin/git"])
c("path to desired Git", ["which", "git"])
c("Git version", ["git", "--version"])
chdir("/tmp")
c("remove existing test repo", ["rm", "-Rf", "test"])
c("create test repo", ["git", "init", "-q", "test"])
chdir("test")
c("test commit A", ["git", "commit", "-m", "a", "--allow-empty"])
c("branch", ["git", "checkout", "-b", "foo"])
c("test commit B", ["git", "commit", "-m", "b", "--allow-empty"])
# This uses the existing $PATH to find git(1), but then runs it with an empty
# environment.
c("checkout w/ empty env", ["git", "checkout", "master"], env=dict())
~~~~
> What happened instead? (Actual behavior)
> (Note re-ordering for clarity.)
Script output:
# fake system Git contents
$ cat /usr/bin/git
#!/bin/sh
echo 'you should not see this' 1>&2
exit 1
# success
# path to desired Git
$ which git
/usr/local/bin/git
# success
# Git version
$ git --version
git version 2.41.0
# success
$ cd /tmp
# remove existing test repo
$ rm -Rf test
# success
# create test repo
$ git init -q test
# success
$ cd test
# test commit A
$ git commit -m a --allow-empty
[master (root-commit) 03e2eb0] a
# success
# branch
$ git checkout -b foo
Switched to a new branch 'foo'
# success
# test commit B
$ git commit -m b --allow-empty
[foo c417cee] b
# success
# checkout w/ empty env
$ git checkout master
you should not see this
# command failed with exit code 1
> What did you expect to happen? (Expected behavior)
Every command in the script should be successful. In particular, I expected the final output to be:
# checkout w/ empty env
$ git checkout master
[... normal checkout chatter ...]
# success
> What's different between what you expected and what actually happened?
/usr/local/bin/git called /usr/bin/git for some subprocess. I expected it to call itself.
> Anything else you want to add
Usually for us, the version skew is close enough that everything seemed to work. I believe we installed Git 2.40.0 and subprocesses were presumably using the system’s 2.31 and everything appeared to work fine. Only when we tried our software on a different box where the system Git was 1.8 did it crash. Therefore, I worry about silent problems due to version skew in the internal command-line API.
> Please review the rest of the bug report below.
> You can delete any lines you don't wish to share.
>
> [System Info]
> git version:
> git version 2.41.0
> cpu: x86_64
> no commit associated with this build [I built the source tarball]
> sizeof-long: 8
> sizeof-size_t: 8
> shell-path: /bin/sh
> uname: Linux 5.10.0-23-amd64 #1 SMP Debian 5.10.179-1 (2023-05-12) x86_64
> compiler info: gnuc: 10.2
> libc info: glibc: 2.31
> $SHELL (typically, interactive shell): /bin/bash
>
> [Enabled Hooks]
Thanks,
Reid
—
he/his
next reply other threads:[~2023-06-01 22:48 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-01 22:21 Priedhorsky, Reid [this message]
2023-06-02 0:35 ` bug? subprocesses can use wrong Git if $PATH is unset brian m. carlson
2023-06-02 16:14 ` Priedhorsky, Reid
2023-06-02 20:20 ` brian m. carlson
2023-06-03 1:38 ` Junio C Hamano
2023-06-07 17:43 ` Priedhorsky, Reid
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=E7D87B07-C416-4A58-8726-CCDA0907AC66@lanl.gov \
--to=reidpr@lanl.gov \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).