Skip to content

Commit b3cba8f

Browse files
authored
Merge pull request libgit2#6475 from jorio/fix_diff_empty_untracked_file
diff_file: Fix crash when freeing a patch representing an empty untracked file
2 parents d9d45fb + b755b7d commit b3cba8f

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

src/libgit2/diff_file.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ static int diff_file_content_load_workdir_file(
348348
goto cleanup;
349349
}
350350

351+
/* if file is empty, don't attempt to mmap or readbuffer */
352+
if (fc->file->size == 0) {
353+
fc->map.len = 0;
354+
fc->map.data = git_str__initstr;
355+
goto cleanup;
356+
}
357+
351358
if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 &&
352359
diff_file_content_binary_by_size(fc))
353360
goto cleanup;

tests/libgit2/diff/workdir.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,42 @@ void test_diff_workdir__checks_options_version(void)
12321232
cl_assert_equal_i(GIT_ERROR_INVALID, err->klass);
12331233
}
12341234

1235+
void test_diff_workdir__can_diff_empty_untracked_file(void)
1236+
{
1237+
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
1238+
git_diff *diff = NULL;
1239+
git_patch *patch = NULL;
1240+
1241+
g_repo = cl_git_sandbox_init("empty_standard_repo");
1242+
1243+
cl_git_mkfile("empty_standard_repo/emptyfile.txt", "");
1244+
1245+
opts.context_lines = 3;
1246+
opts.interhunk_lines = 1;
1247+
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT;
1248+
1249+
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
1250+
1251+
/* without filters */
1252+
git_patch_from_diff(&patch, diff, 0);
1253+
cl_assert(NULL != patch);
1254+
cl_assert(0 == git_patch_get_delta(patch)->new_file.size);
1255+
cl_assert(0 == strcmp("emptyfile.txt", git_patch_get_delta(patch)->new_file.path));
1256+
git_patch_free(patch);
1257+
patch = NULL;
1258+
1259+
/* with a filter */
1260+
cl_repo_set_bool(g_repo, "core.autocrlf", true); /* install some filter */
1261+
git_patch_from_diff(&patch, diff, 0);
1262+
cl_assert(NULL != patch);
1263+
cl_assert(0 == git_patch_get_delta(patch)->new_file.size);
1264+
cl_assert(0 == strcmp("emptyfile.txt", git_patch_get_delta(patch)->new_file.path));
1265+
git_patch_free(patch);
1266+
patch = NULL;
1267+
1268+
git_diff_free(diff);
1269+
}
1270+
12351271
void test_diff_workdir__can_diff_empty_file(void)
12361272
{
12371273
git_diff *diff;

0 commit comments

Comments
 (0)