Skip to content

Commit

Permalink
builtin/gc: fix crash when running git maintenance start (git-for-w…
Browse files Browse the repository at this point in the history
…indows#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.
  • Loading branch information
dscho authored Oct 9, 2024
2 parents d53e464 + becfd0a commit c5d00b2
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
7 changes: 5 additions & 2 deletions builtin/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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”
Expand All @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions t/t7900-maintenance.sh
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,22 @@ test_expect_success !MINGW 'register and unregister with regex metacharacters' '
maintenance.repo "$(pwd)/$META"
'

test_expect_success !MINGW,!DARWIN 'start without GIT_TEST_MAINT_SCHEDULER' '
test_when_finished "rm -rf crontab.log script repo" &&
mkdir script &&
write_script script/crontab <<-EOF &&
echo "\$*" >>"$(pwd)"/crontab.log
EOF
git init repo &&
(
cd repo &&
sane_unset GIT_TEST_MAINT_SCHEDULER &&
PATH="$(pwd)/../script:$PATH" git maintenance start --scheduler=crontab
) &&
test_grep -- -l crontab.log &&
test_grep -- git_cron_edit_tmp crontab.log
'

test_expect_success 'start --scheduler=<scheduler>' '
test_expect_code 129 git maintenance start --scheduler=foo 2>err &&
test_grep "unrecognized --scheduler argument" err &&
Expand Down
6 changes: 6 additions & 0 deletions t/test-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,12 @@ case $uname_s in
test_set_prereq GREP_STRIPS_CR
test_set_prereq WINDOWS
;;
*Darwin*)
test_set_prereq POSIXPERM
test_set_prereq BSLASHPSPEC
test_set_prereq EXECKEEPSPID
test_set_prereq DARWIN
;;
*)
test_set_prereq POSIXPERM
test_set_prereq BSLASHPSPEC
Expand Down

0 comments on commit c5d00b2

Please sign in to comment.