Skip to content

Commit f0478d4

Browse files
committed
diff: reject negative values for -U/--unified
Passing a negative value to -U is silently accepted and produces corrupt unified diff output with malformed hunk headers: $ git log -1 -p -U-500 -- GIT-VERSION-GEN | grep '^@@' @@ -503,999- +503,999- @@ Line 503 of a 106-line file, count "999-" is not a valid integer. The config variable diff.context already rejects negative values, but the command line callback diff_opt_unified() uses strtol() with no range check. Change the type of diff_options.context and its static default from int to unsigned int, matching the change to interhunkcontext in the previous commit. The type change requires reworking the callback and config parsing to validate in a local variable before assigning to the now-unsigned field. Unlike --inter-hunk-context which could be converted to OPT_UNSIGNED, -U needs OPT_CALLBACK_F for PARSE_OPT_OPTARG (bare -U with no value enables patch output). Add a range check in the callback instead. Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
1 parent cca75ec commit f0478d4

3 files changed

Lines changed: 14 additions & 5 deletions

File tree

diff.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static int diff_suppress_blank_empty;
6060
static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN;
6161
static int diff_color_moved_default;
6262
static int diff_color_moved_ws_default;
63-
static int diff_context_default = 3;
63+
static unsigned int diff_context_default = 3;
6464
static unsigned int diff_interhunk_context_default;
6565
static char *diff_word_regex_cfg;
6666
static struct external_diff external_diff_cfg;
@@ -382,9 +382,10 @@ int git_diff_ui_config(const char *var, const char *value,
382382
return 0;
383383
}
384384
if (!strcmp(var, "diff.context")) {
385-
diff_context_default = git_config_int(var, value, ctx->kvi);
386-
if (diff_context_default < 0)
385+
int val = git_config_int(var, value, ctx->kvi);
386+
if (val < 0)
387387
return -1;
388+
diff_context_default = val;
388389
return 0;
389390
}
390391
if (!strcmp(var, "diff.interhunkcontext")) {
@@ -5924,9 +5925,12 @@ static int diff_opt_unified(const struct option *opt,
59245925
BUG_ON_OPT_NEG(unset);
59255926

59265927
if (arg) {
5927-
options->context = strtol(arg, &s, 10);
5928+
long val = strtol(arg, &s, 10);
59285929
if (*s)
59295930
return error(_("%s expects a numerical value"), "--unified");
5931+
if (val < 0)
5932+
return error(_("%s expects a non-negative integer"), "--unified");
5933+
options->context = val;
59305934
}
59315935
enable_patch_output(&options->output_format);
59325936

diff.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ struct diff_options {
294294
enum git_colorbool use_color;
295295

296296
/* Number of context lines to generate in patch output. */
297-
int context;
297+
unsigned int context;
298298

299299
unsigned int interhunkcontext;
300300

t/t4055-diff-context.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ test_expect_success 'negative integer config parsing' '
8282
test_grep "bad config variable" output
8383
'
8484

85+
test_expect_success '-U-1 is rejected' '
86+
test_must_fail git diff -U-1 2>err &&
87+
test_grep "expects a non-negative integer" err
88+
'
89+
8590
test_expect_success '-U0 is valid, so is diff.context=0' '
8691
test_config diff.context 0 &&
8792
git diff >output &&

0 commit comments

Comments
 (0)