range-diff: don't segfault with mode-only changes
In ef283b3699
("apply: make parse_git_diff_header public", 2019-07-11)
the 'parse_git_diff_header' function was made public and useable by
callers outside of apply.c.
However it was missed that its (then) only caller, 'find_header' did
some error handling, and completing 'struct patch' appropriately.
range-diff then started using this function, and tried to handle this
appropriately itself, but fell short in some cases. This in turn
would lead to range-diff segfaulting when there are mode-only changes
in a range.
Move the error handling and completing of the struct into the
'parse_git_diff_header' function, so other callers can take advantage
of it. This fixes the segfault in 'git range-diff'.
Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
499352c2ad
commit
2b6a9b13ca
43
apply.c
43
apply.c
@ -1361,11 +1361,32 @@ int parse_git_diff_header(struct strbuf *root,
|
||||
if (check_header_line(*linenr, patch))
|
||||
return -1;
|
||||
if (res > 0)
|
||||
return offset;
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (!patch->old_name && !patch->new_name) {
|
||||
if (!patch->def_name) {
|
||||
error(Q_("git diff header lacks filename information when removing "
|
||||
"%d leading pathname component (line %d)",
|
||||
"git diff header lacks filename information when removing "
|
||||
"%d leading pathname components (line %d)",
|
||||
parse_hdr_state.p_value),
|
||||
parse_hdr_state.p_value, *linenr);
|
||||
return -128;
|
||||
}
|
||||
patch->old_name = xstrdup(patch->def_name);
|
||||
patch->new_name = xstrdup(patch->def_name);
|
||||
}
|
||||
if ((!patch->new_name && !patch->is_delete) ||
|
||||
(!patch->old_name && !patch->is_new)) {
|
||||
error(_("git diff header lacks filename information "
|
||||
"(line %d)"), *linenr);
|
||||
return -128;
|
||||
}
|
||||
patch->is_toplevel_relative = 1;
|
||||
return offset;
|
||||
}
|
||||
|
||||
@ -1546,26 +1567,6 @@ static int find_header(struct apply_state *state,
|
||||
return -128;
|
||||
if (git_hdr_len <= len)
|
||||
continue;
|
||||
if (!patch->old_name && !patch->new_name) {
|
||||
if (!patch->def_name) {
|
||||
error(Q_("git diff header lacks filename information when removing "
|
||||
"%d leading pathname component (line %d)",
|
||||
"git diff header lacks filename information when removing "
|
||||
"%d leading pathname components (line %d)",
|
||||
state->p_value),
|
||||
state->p_value, state->linenr);
|
||||
return -128;
|
||||
}
|
||||
patch->old_name = xstrdup(patch->def_name);
|
||||
patch->new_name = xstrdup(patch->def_name);
|
||||
}
|
||||
if ((!patch->new_name && !patch->is_delete) ||
|
||||
(!patch->old_name && !patch->is_new)) {
|
||||
error(_("git diff header lacks filename information "
|
||||
"(line %d)"), state->linenr);
|
||||
return -128;
|
||||
}
|
||||
patch->is_toplevel_relative = 1;
|
||||
*hdrsize = git_hdr_len;
|
||||
return offset;
|
||||
}
|
||||
|
Reference in New Issue
Block a user