git: avoid segfault on "git --shallow-file" without a value

In "git.c", the other `handle_options()` options that take their value
as a separate argument, like `--git-dir`, `--namespace` or `-C`, check
that such an argument actually exists before using it, and error out
with a message and the usage string otherwise.

The `--shallow-file` option doesn't perform that check. It blindly
advances past the option and then dereferences the next element of
`argv`, which is the NULL terminator when no value was given. So
`git --shallow-file` segfaults:

  $ git --shallow-file
  Segmentation fault (core dumped)

Let's fix that by checking that a value was given, in the same way and
with a message worded like the ones the other options use.

While at it, let's also set the environment variable before advancing
past the option, instead of advancing first and using `(*argv)[0]`, so
that this option looks like the other ones.

Note that all the in-tree callers passing `--shallow-file` to a `git`
subprocess always pass a value after it, so they are not affected. In
`upload-pack.c` that value is an empty string, which is still accepted.

Signed-off-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
main
Christian Couder 2026-08-11 14:14:46 +02:00 committed by Junio C Hamano
parent 11c6700f10
commit 88249755a4
2 changed files with 14 additions and 3 deletions

10
git.c
View File

@ -304,11 +304,15 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--shallow-file")) {
(*argv)++;
(*argc)--;
setenv(GIT_SHALLOW_FILE_ENVIRONMENT, (*argv)[0], 1);
if (*argc < 2) {
fprintf(stderr, _("no file given for '%s' option\n" ), "--shallow-file");
usage(git_usage_string);
}
setenv(GIT_SHALLOW_FILE_ENVIRONMENT, (*argv)[1], 1);
if (envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
} else if (!strcmp(cmd, "-C")) {
if (*argc < 2) {
fprintf(stderr, _("no directory given for '%s' option\n" ), "-C");

View File

@ -107,4 +107,11 @@ test_expect_success 'for-each-ref usage error' '
test_grep "usage" actual.err
'

test_expect_success 'git --shallow-file without a value' '
test_must_fail git --shallow-file >actual 2>actual.err &&
test_line_count = 0 actual &&
test_grep "no file given for " actual.err &&
test_grep "usage" actual.err
'

test_done