Skip to content

Commit c5d00b2

Browse files
authored
builtin/gc: fix crash when running git maintenance start (git-for-windows#5198)
> This patch was sent upstream by Patrick. I'm contributing it to Git for Windows quickly to make sure it gets into microsoft/git, but also in advance of any potential 2.47.1. It was reported on the mailing list that running `git maintenance start` immediately segfaults starting with b6c3f8e (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.
2 parents d53e464 + becfd0a commit c5d00b2

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

builtin/gc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,7 +1832,7 @@ static const char *get_extra_launchctl_strings(void) {
18321832
* | Input | Output |
18331833
* | *cmd | return code | *out | *is_available |
18341834
* +-------+-------------+-------------------+---------------+
1835-
* | "foo" | false | NULL | (unchanged) |
1835+
* | "foo" | false | "foo" (allocated) | (unchanged) |
18361836
* +-------+-------------+-------------------+---------------+
18371837
*
18381838
* 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)
18501850
struct string_list_item *item;
18511851
struct string_list list = STRING_LIST_INIT_NODUP;
18521852

1853-
if (!testing)
1853+
if (!testing) {
1854+
if (out)
1855+
*out = xstrdup(cmd);
18541856
return 0;
1857+
}
18551858

18561859
if (is_available)
18571860
*is_available = 0;

t/t7900-maintenance.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,22 @@ test_expect_success !MINGW 'register and unregister with regex metacharacters' '
646646
maintenance.repo "$(pwd)/$META"
647647
'
648648

649+
test_expect_success !MINGW,!DARWIN 'start without GIT_TEST_MAINT_SCHEDULER' '
650+
test_when_finished "rm -rf crontab.log script repo" &&
651+
mkdir script &&
652+
write_script script/crontab <<-EOF &&
653+
echo "\$*" >>"$(pwd)"/crontab.log
654+
EOF
655+
git init repo &&
656+
(
657+
cd repo &&
658+
sane_unset GIT_TEST_MAINT_SCHEDULER &&
659+
PATH="$(pwd)/../script:$PATH" git maintenance start --scheduler=crontab
660+
) &&
661+
test_grep -- -l crontab.log &&
662+
test_grep -- git_cron_edit_tmp crontab.log
663+
'
664+
649665
test_expect_success 'start --scheduler=<scheduler>' '
650666
test_expect_code 129 git maintenance start --scheduler=foo 2>err &&
651667
test_grep "unrecognized --scheduler argument" err &&

t/test-lib.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,6 +1738,12 @@ case $uname_s in
17381738
test_set_prereq GREP_STRIPS_CR
17391739
test_set_prereq WINDOWS
17401740
;;
1741+
*Darwin*)
1742+
test_set_prereq POSIXPERM
1743+
test_set_prereq BSLASHPSPEC
1744+
test_set_prereq EXECKEEPSPID
1745+
test_set_prereq DARWIN
1746+
;;
17411747
*)
17421748
test_set_prereq POSIXPERM
17431749
test_set_prereq BSLASHPSPEC

0 commit comments

Comments
 (0)