git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: git@vger.kernel.org
Cc: Shubham Kanodia <shubham.kanodia10@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Derrick Stolee <stolee@gmail.com>
Subject: [PATCH v2] builtin/gc: fix crash when running `git maintenance start`
Date: Wed, 9 Oct 2024 09:08:33 +0200	[thread overview]
Message-ID: <5798c31e1ef9346e7faf73f8c80b32c436937a8a.1728455715.git.ps@pks.im> (raw)
In-Reply-To: <CAG=Um+0mJW-oAH+YLC3dWEU64JwS-zMkkTiFWYBe4g6HMbe-iA@mail.gmail.com>

It was reported on the mailing list that running `git maintenance start`
immediately segfaults starting with b6c3f8e12c (builtin/maintenance: fix
leak in `get_schedule_cmd()`, 2024-09-26). And indeed, this segfault is
trivial to reproduce up to a point where one is scratching their head
why we didn't catch this regression in our test suite.

The root cause of this error is `get_schedule_cmd()`, which does not
populate the `out` parameter in all cases anymore starting with the
mentioned commit. Callers do assume it to always be populated though and
will e.g. call `strvec_split()` on the returned value, which will of
course segfault when the variable is uninitialized.

So why didn't we catch this trivial regression? The reason is that our
tests always set up the "GIT_TEST_MAINT_SCHEDULER" environment variable
via "t/test-lib.sh", which allows us to override the scheduler command
with a custom one so that we don't accidentally modify the developer's
system. But the faulty code where we don't set the `out` parameter will
only get hit in case that environment variable is _not_ set, which is
never the case when executing our tests.

Fix the regression by again unconditionally allocating the value in the
`out` parameter, if provided. Add a test that unsets the environment
variable to catch future regressions in this area.

Reported-by: Shubham Kanodia <shubham.kanodia10@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---

There's a single fix compared to v1, where Stolee mentioned that the
added test fails on both Windows and macOS because the "crontab"
scheduler isn't available there. I've adapted the test to instead use
the "systemd" scheduler, which _is_ available on all platforms when the
systemctl(1) binary can be found.

Thanks!

Patrick

 builtin/gc.c           |  7 +++++--
 t/t7900-maintenance.sh | 16 ++++++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/builtin/gc.c b/builtin/gc.c
index 6a7a2da006..d52735354c 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1832,7 +1832,7 @@ static const char *get_extra_launchctl_strings(void) {
  *     | Input |                     Output                      |
  *     | *cmd  | return code |       *out        | *is_available |
  *     +-------+-------------+-------------------+---------------+
- *     | "foo" |    false    | NULL              |  (unchanged)  |
+ *     | "foo" |    false    | "foo" (allocated) |  (unchanged)  |
  *     +-------+-------------+-------------------+---------------+
  *
  *   GIT_TEST_MAINT_SCHEDULER set to “foo:./mock_foo.sh,bar:./mock_bar.sh”
@@ -1850,8 +1850,11 @@ static int get_schedule_cmd(const char *cmd, int *is_available, char **out)
 	struct string_list_item *item;
 	struct string_list list = STRING_LIST_INIT_NODUP;
 
-	if (!testing)
+	if (!testing) {
+		if (out)
+			*out = xstrdup(cmd);
 		return 0;
+	}
 
 	if (is_available)
 		*is_available = 0;
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index a66d0e089d..e75b485319 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -646,6 +646,22 @@ test_expect_success !MINGW 'register and unregister with regex metacharacters' '
 		maintenance.repo "$(pwd)/$META"
 '
 
+test_expect_success 'start without GIT_TEST_MAINT_SCHEDULER' '
+	test_when_finished "rm -rf systemctl.log script repo" &&
+	mkdir script &&
+	write_script script/systemctl <<-EOF &&
+	echo "\$*" >>"$(pwd)"/systemctl.log
+	EOF
+	git init repo &&
+	(
+		cd repo &&
+		sane_unset GIT_TEST_MAINT_SCHEDULER &&
+		PATH="$(pwd)/../script:$PATH" git maintenance start --scheduler=systemd
+	) &&
+	test_grep -- "--user list-timers" systemctl.log &&
+	test_grep -- "enable --now git-maintenance@" systemctl.log
+'
+
 test_expect_success 'start --scheduler=<scheduler>' '
 	test_expect_code 129 git maintenance start --scheduler=foo 2>err &&
 	test_grep "unrecognized --scheduler argument" err &&

Range-diff against v1:
1:  976c97081a ! 1:  5798c31e1e builtin/gc: fix crash when running `git maintenance start`
    @@ t/t7900-maintenance.sh: test_expect_success !MINGW 'register and unregister with
      '
      
     +test_expect_success 'start without GIT_TEST_MAINT_SCHEDULER' '
    -+	test_when_finished "rm -rf crontab.log script repo" &&
    ++	test_when_finished "rm -rf systemctl.log script repo" &&
     +	mkdir script &&
    -+	write_script script/crontab <<-EOF &&
    -+	echo "\$*" >>"$(pwd)"/crontab.log
    ++	write_script script/systemctl <<-EOF &&
    ++	echo "\$*" >>"$(pwd)"/systemctl.log
     +	EOF
     +	git init repo &&
     +	(
     +		cd repo &&
     +		sane_unset GIT_TEST_MAINT_SCHEDULER &&
    -+		PATH="$(pwd)/../script:$PATH" git maintenance start --scheduler=crontab
    ++		PATH="$(pwd)/../script:$PATH" git maintenance start --scheduler=systemd
     +	) &&
    -+	test_grep -- -l crontab.log &&
    -+	test_grep -- git_cron_edit_tmp crontab.log
    ++	test_grep -- "--user list-timers" systemctl.log &&
    ++	test_grep -- "enable --now git-maintenance@" systemctl.log
     +'
     +
      test_expect_success 'start --scheduler=<scheduler>' '
-- 
2.47.0.rc1.33.g90fe3800b9.dirty


  parent reply	other threads:[~2024-10-09  7:08 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-08 10:50 Bug: `git maintenance start` is likely broken in 2.47 Shubham Kanodia
2024-10-08 11:45 ` Patrick Steinhardt
2024-10-08 12:15 ` [PATCH] builtin/gc: fix crash when running `git maintenance start` Patrick Steinhardt
2024-10-08 18:30   ` Derrick Stolee
2024-10-09  2:58     ` Derrick Stolee
2024-10-09  6:28       ` Patrick Steinhardt
2024-10-08 18:33   ` Junio C Hamano
2024-10-09 23:14     ` Junio C Hamano
2024-10-10  4:54       ` Patrick Steinhardt
2024-10-10  5:10         ` Patrick Steinhardt
2024-10-09  7:08 ` Patrick Steinhardt [this message]
2024-10-09 13:13   ` [PATCH v2] " Derrick Stolee
2024-10-09 17:28     ` Junio C Hamano
2024-10-09 17:10   ` Junio C Hamano
2024-10-10  5:33 ` [PATCH v3] " Patrick Steinhardt
2024-10-10 17:09   ` Junio C Hamano
2024-10-14  4:44     ` Shubham Kanodia
2024-10-14  8:38       ` Patrick Steinhardt
2024-10-15  0:36         ` Taylor Blau

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=5798c31e1ef9346e7faf73f8c80b32c436937a8a.1728455715.git.ps@pks.im \
    --to=ps@pks.im \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=shubham.kanodia10@gmail.com \
    --cc=stolee@gmail.com \
    /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).