diff: reject negative values for --inter-hunk-context

Negative values for --inter-hunk-context produce structurally invalid
diff output with overlapping hunks:

    $ git log -1 -p -U3 --inter-hunk-context=-100 791aeddfa2 \
        -- git-compat-util.h | grep '^@@'
    @@ -110,6 +110,9 @@
    @@ -115,6 +118,9 @@
    @@ -116,6 +122,7 @@

Hunk 1 covers lines 110-115, hunk 2 starts at 115 (overlap), hunk 3
starts at 116 (overlaps both). The resulting patch cannot be applied.

The config variable diff.interHunkContext already rejects negative
values, but the command line option does not.

Change the type of diff_options.interhunkcontext and its static
default from int to unsigned int, and switch the option parser from
OPT_INTEGER_F to OPT_UNSIGNED. This rejects negative values at parse
time via git_parse_unsigned() and enforces the correct type at compile
time via BARF_UNLESS_UNSIGNED.

Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
main
Michael Montalbo 2026-05-12 18:10:20 +00:00 committed by Junio C Hamano
parent 94f057755b
commit 321f0ea17b
3 changed files with 13 additions and 8 deletions

13
diff.c
View File

@ -61,7 +61,7 @@ static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN;
static int diff_color_moved_default;
static int diff_color_moved_ws_default;
static int diff_context_default = 3;
static int diff_interhunk_context_default;
static unsigned int diff_interhunk_context_default;
static char *diff_word_regex_cfg;
static struct external_diff external_diff_cfg;
static char *diff_order_file_cfg;
@ -388,10 +388,10 @@ int git_diff_ui_config(const char *var, const char *value,
return 0;
}
if (!strcmp(var, "diff.interhunkcontext")) {
diff_interhunk_context_default = git_config_int(var, value,
ctx->kvi);
if (diff_interhunk_context_default < 0)
int val = git_config_int(var, value, ctx->kvi);
if (val < 0)
return -1;
diff_interhunk_context_default = val;
return 0;
}
if (!strcmp(var, "diff.renames")) {
@ -6111,9 +6111,8 @@ struct option *add_diff_options(const struct option *opts,
OPT_CALLBACK_F(0, "default-prefix", options, NULL,
N_("use default prefixes a/ and b/"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff_opt_default_prefix),
OPT_INTEGER_F(0, "inter-hunk-context", &options->interhunkcontext,
N_("show context between diff hunks up to the specified number of lines"),
PARSE_OPT_NONEG),
OPT_UNSIGNED(0, "inter-hunk-context", &options->interhunkcontext,
N_("show context between diff hunks up to the specified number of lines")),
OPT_CALLBACK_F(0, "output-indicator-new",
&options->output_indicators[OUTPUT_INDICATOR_NEW],
N_("<char>"),

2
diff.h
View File

@ -296,7 +296,7 @@ struct diff_options {
/* Number of context lines to generate in patch output. */
int context;

int interhunkcontext;
unsigned int interhunkcontext;

/* Affects the way detection logic for complete rewrites, renames and
* copies.

View File

@ -114,4 +114,10 @@ test_expect_success 'diff.interHunkContext invalid' '
test_must_fail git diff
'

test_expect_success '--inter-hunk-context rejects negative value' '
test_unconfig diff.interHunkContext &&
test_must_fail git diff --inter-hunk-context=-1 2>err &&
test_grep "expects a non-negative integer" err
'

test_done