From: "D. Ben Knoble" <ben.knoble+github@gmail.com>
To: git@vger.kernel.org
Cc: "D. Ben Knoble" <ben.knoble+github@gmail.com>,
"Johannes Schindelin" <johannes.schindelin@gmx.de>,
"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
"Junio C Hamano" <gitster@pobox.com>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH 4/4] drop git_exec_path() from non-Git commands' PATH
Date: Tue, 20 May 2025 15:34:58 -0400 [thread overview]
Message-ID: <20250520193506.95199-5-ben.knoble+github@gmail.com> (raw)
In-Reply-To: <20250520193506.95199-1-ben.knoble+github@gmail.com>
We setup_path() with git_exec_path() unconditionally (8e3462837b (Modify
setup_path() to only add git_exec_path() to PATH, 2009-01-18)) when Git
starts; as a result, all child processes see Git's exec-path when run,
including editors and other programs that don't need it [1]. This can
cause confusion for such programs or shells, especially when they rely
on finding "git" in PATH to locate other nearby directories, in a
similar vein as a0b4507ef7 (stop putting argv[0] dirname at front of
PATH, 2015-04-22) solved.
Since we only need this for finding git-* subprocesses, drop it from
child processes that aren't Git commands.
[1]: https://public-inbox.org/git/CALnO6CDtGRRav8zK2GKi1oHTZWrHFTxZNmnOWu64-ab+oY3_Lw@mail.gmail.com/
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Suggested-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Notes:
A few interesting points:
- I'm not sure how best to deal with the memory leak here.
- Dscho suggested the essence of the patch in
https://github.com/git-for-windows/build-extra/pull/616#pullrequestreview-2839055049,
for the curious. My only major tweaks were this diff to skip past
"PATH=" when searching for the matching path (but still modify the
original buffer; b always points into buf.buf, so the later operations
with p and buf.buf are valid).
--->8---
diff --git i/run-command.c w/run-command.c
index b567e4fdd5..8a8b5c8455 100644
--- i/run-command.c
+++ w/run-command.c
@@ -452,17 +452,24 @@ static void remove_git_exec_path(struct string_list_item *path_item) {
struct strbuf buf = STRBUF_INIT;
const char *exec_path = git_exec_path();
size_t exec_len = strlen(exec_path);
- char *p;
+ char *b, *p;
/* Value comes from environ; we should not modify it directly. But
* strbuf copies data, so we now have our own playground. */
strbuf_addstr(&buf, (const char *)path_item->util);
- for (p = strstr(buf.buf, exec_path); p; p = strstr(p, exec_path)) {
- if ((p[exec_len] && p[exec_len] != PATH_SEP) || (p != buf.buf && p[-1] != PATH_SEP))
+
+ /* skip past "PATH=" to start search */
+ p = strchr(buf.buf, '=');
+ if (!p || !*(p + 1))
+ return;
+ b = p + 1;
+
+ for (p = strstr(b, exec_path); p; p = strstr(p, exec_path)) {
+ if ((p[exec_len] && p[exec_len] != PATH_SEP) || (p != b && p[-1] != PATH_SEP))
p += exec_len; /* false positive, skip */
else {
size_t offset = p - buf.buf, delete_len = exec_len;
- if (p != buf.buf) {
+ if (p != b) {
/* include the preceding path separator */
offset--;
delete_len++;
--->8---
- I /think/ this resolves the issues in my earlier mail beyond just Git
builtins; for example, git-jump also doesn't get exec-path because
it's not invoked with git_cmd set during execv_dashed_external.
run-command.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
t/t7005-editor.sh | 13 +++++++++++++
2 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/run-command.c b/run-command.c
index dee6ae3e62..8a8b5c8455 100644
--- a/run-command.c
+++ b/run-command.c
@@ -448,11 +448,51 @@ static int prepare_cmd(struct strvec *out, const struct child_process *cmd)
return 0;
}
-static char **prep_childenv(const char *const *deltaenv)
+static void remove_git_exec_path(struct string_list_item *path_item) {
+ struct strbuf buf = STRBUF_INIT;
+ const char *exec_path = git_exec_path();
+ size_t exec_len = strlen(exec_path);
+ char *b, *p;
+
+ /* Value comes from environ; we should not modify it directly. But
+ * strbuf copies data, so we now have our own playground. */
+ strbuf_addstr(&buf, (const char *)path_item->util);
+
+ /* skip past "PATH=" to start search */
+ p = strchr(buf.buf, '=');
+ if (!p || !*(p + 1))
+ return;
+ b = p + 1;
+
+ for (p = strstr(b, exec_path); p; p = strstr(p, exec_path)) {
+ if ((p[exec_len] && p[exec_len] != PATH_SEP) || (p != b && p[-1] != PATH_SEP))
+ p += exec_len; /* false positive, skip */
+ else {
+ size_t offset = p - buf.buf, delete_len = exec_len;
+ if (p != b) {
+ /* include the preceding path separator */
+ offset--;
+ delete_len++;
+ } else if (p[exec_len] == PATH_SEP) {
+ /* include the path separator following GIT_EXEC_PATH */
+ delete_len++;
+ }
+ strbuf_splice(&buf, offset, delete_len, "", 0);
+ }
+ }
+
+ /* Overwrite PATH value with new (owned) data. This leaks memory because
+ * the only future owner is a char** childenv, which is freed, but whose
+ * contents are not (because most of them come from environ). */
+ path_item->util = (void *)strbuf_detach(&buf, NULL);
+}
+
+static char **prep_childenv(const char *const *deltaenv, unsigned git_cmd)
{
extern char **environ;
char **childenv;
struct string_list env = STRING_LIST_INIT_DUP;
+ struct string_list_item *path_item;
struct strbuf key = STRBUF_INIT;
const char *const *p;
int i;
@@ -486,6 +526,9 @@ static char **prep_childenv(const char *const *deltaenv)
}
}
+ if (!git_cmd && (path_item = string_list_lookup(&env, "PATH")))
+ remove_git_exec_path(path_item);
+
/* Create an array of 'char *' to be used as the childenv */
ALLOC_ARRAY(childenv, env.nr + 1);
for (i = 0; i < env.nr; i++)
@@ -746,7 +789,7 @@ int start_command(struct child_process *cmd)
if (cmd->close_object_store)
close_object_store(the_repository->objects);
- childenv = prep_childenv(cmd->env.v);
+ childenv = prep_childenv(cmd->env.v, cmd->git_cmd);
#ifndef GIT_WINDOWS_NATIVE
{
diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh
index 06fa1ecd91..560e500b53 100755
--- a/t/t7005-editor.sh
+++ b/t/t7005-editor.sh
@@ -127,4 +127,17 @@
test space = "$(git show -s --pretty=format:%s)"
'
+test_expect_success 'editor does not see GIT_EXEC_PATH on PATH' '
+ cat >e-path <<-EOF &&
+ #!$SHELL_PATH
+ echo "\$PATH" | tr : "\\n" >actual
+ EOF
+ chmod +x e-path &&
+ (
+ test_set_editor ./e-path &&
+ git commit --amend
+ ) &&
+ test_grep ! ^"$(git --exec-path)"\$ actual
+'
+
test_done
--
2.48.1
next prev parent reply other threads:[~2025-05-20 19:36 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-20 19:34 [PATCH 0/4] Drop git-exec-path from non-Git child programs D. Ben Knoble
2025-05-20 19:34 ` [PATCH 1/4] t7005: sanitize test environment for subsequent tests D. Ben Knoble
2025-05-21 7:56 ` Patrick Steinhardt
2025-05-21 13:23 ` D. Ben Knoble
2025-05-20 19:34 ` [PATCH 2/4] editor: use standard strvec API to receive environment for external editors D. Ben Knoble
2025-05-21 7:56 ` Patrick Steinhardt
2025-05-21 13:26 ` D. Ben Knoble
2025-05-21 13:34 ` Patrick Steinhardt
2025-05-21 15:20 ` Junio C Hamano
2025-05-21 15:10 ` Junio C Hamano
2025-05-20 19:34 ` [PATCH 3/4] run-command: prep_childenv on all platforms D. Ben Knoble
2025-05-21 7:56 ` Patrick Steinhardt
2025-05-21 13:07 ` Phillip Wood
2025-05-21 13:33 ` D. Ben Knoble
2025-05-20 19:34 ` D. Ben Knoble [this message]
2025-05-20 20:33 ` [PATCH 4/4] drop git_exec_path() from non-Git commands' PATH Junio C Hamano
2025-05-21 13:44 ` D. Ben Knoble
2025-05-21 8:27 ` Patrick Steinhardt
2025-05-21 13:07 ` Phillip Wood
2025-05-21 13:17 ` Patrick Steinhardt
2025-05-21 15:27 ` Phillip Wood
2025-05-26 6:34 ` Patrick Steinhardt
2025-05-21 15:50 ` Justin Tobler
2025-05-26 6:31 ` Patrick Steinhardt
2025-05-21 13:48 ` D. Ben Knoble
2025-05-21 14:47 ` Junio C Hamano
2025-05-22 13:21 ` [PATCH 0/4] Drop git-exec-path from non-Git child programs Phillip Wood
2025-08-05 1:41 ` D. Ben Knoble
2025-08-05 2:40 ` [PATCH 0/2] clean up some code around editors D. Ben Knoble
2025-08-06 10:07 ` Phillip Wood
2025-08-05 2:40 ` [PATCH 1/2] t7005: sanitize test environment for subsequent tests D. Ben Knoble
2025-08-05 2:40 ` [PATCH 2/2] editor: use standard strvec API to receive environment for external editors D. Ben Knoble
2025-08-10 16:03 ` [PATCH 0/3] clean up some code around editors D. Ben Knoble
2025-08-10 16:06 ` D. Ben Knoble
2025-08-10 16:34 ` Ben Knoble
2025-08-11 22:16 ` [PATCH v3 0/4] " D. Ben Knoble
2025-08-11 22:59 ` Ben Knoble
2025-08-12 0:16 ` Eric Sunshine
2025-08-12 16:42 ` D. Ben Knoble
2025-08-12 17:35 ` Junio C Hamano
2025-08-12 18:13 ` Eric Sunshine
2025-08-12 18:22 ` Junio C Hamano
2025-08-12 18:30 ` Eric Sunshine
2025-08-12 17:02 ` [PATCH v4 0/3] " D. Ben Knoble
2025-08-13 10:14 ` Phillip Wood
2025-08-13 15:41 ` Junio C Hamano
2025-08-13 17:36 ` D. Ben Knoble
2025-08-13 17:50 ` [PATCH v5 " D. Ben Knoble
2025-08-15 16:00 ` Phillip Wood
2025-08-13 17:50 ` [PATCH v5 1/3] t7005: use modern test style D. Ben Knoble
2025-08-13 17:50 ` [PATCH v5 2/3] t7005: stop abusing --exec-path D. Ben Knoble
2025-08-13 17:50 ` [PATCH v5 3/3] t7005: sanitize test environment for subsequent tests D. Ben Knoble
2025-08-12 17:02 ` [PATCH v4 1/3] t7005: use modern test style D. Ben Knoble
2025-08-12 17:02 ` [PATCH v4 2/3] t7005: stop abusing --exec-path D. Ben Knoble
2025-08-12 17:02 ` [PATCH v4 3/3] t7005: sanitize test environment for subsequent tests D. Ben Knoble
2025-08-11 22:16 ` [PATCH v3 1/4] t7005: use modern test style D. Ben Knoble
2025-08-11 22:16 ` [PATCH v3 2/4] t7005: stop abusing --exec-path D. Ben Knoble
2025-08-11 22:16 ` [PATCH v3 3/4] t7005: sanitize test environment for subsequent tests D. Ben Knoble
2025-08-11 22:34 ` Eric Sunshine
2025-08-12 16:40 ` D. Ben Knoble
2025-08-12 17:13 ` Eric Sunshine
2025-08-11 22:16 ` [PATCH v3 4/4] editor: use standard strvec API to receive environment for external editors D. Ben Knoble
2025-08-11 22:46 ` Eric Sunshine
2025-08-11 23:58 ` Junio C Hamano
2025-08-10 16:03 ` [PATCH 1/3] t7005: use modern test style D. Ben Knoble
2025-08-10 19:42 ` Phillip Wood
2025-08-11 10:04 ` Phillip Wood
2025-08-10 16:03 ` [PATCH 2/3] t7005: sanitize test environment for subsequent tests D. Ben Knoble
2025-08-10 19:44 ` Phillip Wood
2025-08-10 19:53 ` Ben Knoble
2025-08-10 20:58 ` Eric Sunshine
2025-08-11 9:59 ` Phillip Wood
2025-08-10 16:03 ` [PATCH 3/3] editor: use standard strvec API to receive environment for external editors D. Ben Knoble
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=20250520193506.95199-5-ben.knoble+github@gmail.com \
--to=ben.knoble+github@gmail.com \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=johannes.schindelin@gmx.de \
/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 NNTP newsgroup(s).