Skip to content

Commit 4110fc8

Browse files
authored
Merge pull request libgit2#4285 from pks-t/pks/patches-with-whitespace
patch_parse: fix parsing unquoted filenames with spaces
2 parents d734466 + 80226b5 commit 4110fc8

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

src/patch_parse.c

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,9 @@ static int header_path_len(git_patch_parse_ctx *ctx)
5353
return len;
5454
}
5555

56-
static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx)
56+
static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx, size_t path_len)
5757
{
58-
int path_len, error = 0;
59-
60-
path_len = header_path_len(ctx);
58+
int error;
6159

6260
if ((error = git_buf_put(path, ctx->parse_ctx.line, path_len)) < 0)
6361
goto done;
@@ -81,7 +79,7 @@ static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx)
8179
static int parse_header_path(char **out, git_patch_parse_ctx *ctx)
8280
{
8381
git_buf path = GIT_BUF_INIT;
84-
int error = parse_header_path_buf(&path, ctx);
82+
int error = parse_header_path_buf(&path, ctx, header_path_len(ctx));
8583

8684
*out = git_buf_detach(&path);
8785

@@ -91,13 +89,33 @@ static int parse_header_path(char **out, git_patch_parse_ctx *ctx)
9189
static int parse_header_git_oldpath(
9290
git_patch_parsed *patch, git_patch_parse_ctx *ctx)
9391
{
94-
return parse_header_path(&patch->old_path, ctx);
92+
git_buf old_path = GIT_BUF_INIT;
93+
int error;
94+
95+
if ((error = parse_header_path_buf(&old_path, ctx, ctx->parse_ctx.line_len - 1)) < 0)
96+
goto out;
97+
98+
patch->old_path = git_buf_detach(&old_path);
99+
100+
out:
101+
git_buf_free(&old_path);
102+
return error;
95103
}
96104

97105
static int parse_header_git_newpath(
98106
git_patch_parsed *patch, git_patch_parse_ctx *ctx)
99107
{
100-
return parse_header_path(&patch->new_path, ctx);
108+
git_buf new_path = GIT_BUF_INIT;
109+
int error;
110+
111+
if ((error = parse_header_path_buf(&new_path, ctx, ctx->parse_ctx.line_len - 1)) < 0)
112+
goto out;
113+
114+
patch->new_path = git_buf_detach(&new_path);
115+
116+
out:
117+
git_buf_free(&new_path);
118+
return error;
101119
}
102120

103121
static int parse_header_mode(uint16_t *mode, git_patch_parse_ctx *ctx)
@@ -213,7 +231,7 @@ static int parse_header_rename(
213231
{
214232
git_buf path = GIT_BUF_INIT;
215233

216-
if (parse_header_path_buf(&path, ctx) < 0)
234+
if (parse_header_path_buf(&path, ctx, header_path_len(ctx)) < 0)
217235
return -1;
218236

219237
/* Note: the `rename from` and `rename to` lines include the literal
@@ -303,6 +321,22 @@ static int parse_header_start(git_patch_parsed *patch, git_patch_parse_ctx *ctx)
303321
return git_parse_err("corrupt new path in git diff header at line %"PRIuZ,
304322
ctx->parse_ctx.line_num);
305323

324+
/*
325+
* We cannot expect to be able to always parse paths correctly at this
326+
* point. Due to the possibility of unquoted names, whitespaces in
327+
* filenames and custom prefixes we have to allow that, though, and just
328+
* proceeed here. We then hope for the "---" and "+++" lines to fix that
329+
* for us.
330+
*/
331+
if (!git_parse_ctx_contains(&ctx->parse_ctx, "\n", 1)) {
332+
git_parse_advance_chars(&ctx->parse_ctx, ctx->parse_ctx.line_len - 1);
333+
334+
git__free(patch->header_old_path);
335+
patch->header_old_path = NULL;
336+
git__free(patch->header_new_path);
337+
patch->header_new_path = NULL;
338+
}
339+
306340
return 0;
307341
}
308342

tests/patch/parse.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,9 @@ void test_patch_parse__invalid_patches_fails(void)
102102
strlen(PATCH_CORRUPT_MISSING_HUNK_HEADER), NULL));
103103
}
104104

105+
void test_patch_parse__files_with_whitespaces_succeeds(void)
106+
{
107+
git_patch *patch;
108+
cl_git_pass(git_patch_from_buffer(&patch, PATCH_NAME_WHITESPACE, strlen(PATCH_NAME_WHITESPACE), NULL));
109+
git_patch_free(patch);
110+
}

tests/patch/patch_common.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,16 @@
575575
"+added line with no nl\n" \
576576
"\\ No newline at end of file\n"
577577

578+
#define PATCH_NAME_WHITESPACE \
579+
"diff --git a/file with spaces.txt b/file with spaces.txt\n" \
580+
"index 9432026..83759c0 100644\n" \
581+
"--- a/file with spaces.txt\n" \
582+
"+++ b/file with spaces.txt\n" \
583+
"@@ -0,3 +0,2 @@\n" \
584+
" and this\n" \
585+
"-is additional context\n" \
586+
" below it!\n" \
587+
578588
#define PATCH_CORRUPT_GIT_HEADER \
579589
"diff --git a/file.txt\n" \
580590
"index 9432026..0f39b9a 100644\n" \

0 commit comments

Comments
 (0)