Commit ad5a909c by Patrick Steinhardt

patch_parse: fix parsing minimal trailing diff line

In a diff, the shortest possible hunk with a modification (that is, no
deletion) results from a file with only one line with a single character
which is removed. Thus the following hunk

    @@ -1 +1 @@
    -a
    +

is the shortest valid hunk modifying a line. The function parsing the
hunk body though assumes that there must always be at least 4 bytes
present to make up a valid hunk, which is obviously wrong in this case.
The absolute minimum number of bytes required for a modification is
actually 2 bytes, that is the "+" and the following newline. Note: if
there is no trailing newline, the assumption will not be offended as the
diff will have a line "\ No trailing newline" at its end.

This patch fixes the issue by lowering the amount of bytes required.
parent 62a2fc06
......@@ -562,8 +562,9 @@ static int parse_hunk_body(
int newlines = hunk->hunk.new_lines;
for (;
ctx->remain_len > 4 && (oldlines || newlines) &&
memcmp(ctx->line, "@@ -", 4) != 0;
ctx->remain_len > 1 &&
(oldlines || newlines) &&
(ctx->remain_len <= 4 || memcmp(ctx->line, "@@ -", 4) != 0);
parse_advance_line(ctx)) {
int origin;
......
......@@ -225,3 +225,24 @@ void test_diff_parse__foreach_works_with_parsed_patch(void)
git_diff_free(diff);
}
void test_diff_parse__parsing_minimal_patch_succeeds(void)
{
const char patch[] =
"diff --git a/obj1 b/obj2\n"
"index 1234567..7654321 10644\n"
"--- a/obj1\n"
"+++ b/obj2\n"
"@@ -1 +1 @@\n"
"-a\n"
"+\n";
git_buf buf = GIT_BUF_INIT;
git_diff *diff;
cl_git_pass(git_diff_from_buffer(&diff, patch, strlen(patch)));
cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
cl_assert_equal_s(patch, buf.ptr);
git_diff_free(diff);
git_buf_free(&buf);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment