]> git.proxmox.com Git - libgit2.git/commitdiff
Fix diff crash when last item is untracked dir
authorRussell Belfer <rb@github.com>
Wed, 15 May 2013 21:50:05 +0000 (14:50 -0700)
committerRussell Belfer <rb@github.com>
Wed, 15 May 2013 21:50:05 +0000 (14:50 -0700)
When the last item in a diff was an untracked directory that only
contained ignored items, the loop to scan the contents would run
off the end of the iterator and dereference a NULL pointer.  This
includes a test that reproduces the problem and a fix.

src/diff.c
tests-clar/diff/workdir.c

index f466546bbc32853ce825004a903289ff69c594f7..d93506984d5fdc0310d59693f847b4ef63e39adc 100644 (file)
@@ -747,7 +747,8 @@ static int diff_scan_inside_untracked_dir(
        }
 
        /* look for actual untracked file */
-       while (!diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
+       while (info->nitem != NULL &&
+                  !diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
                is_ignored = git_iterator_current_is_ignored(info->new_iter);
 
                /* need to recurse into non-ignored directories */
@@ -769,7 +770,8 @@ static int diff_scan_inside_untracked_dir(
        }
 
        /* finish off scan */
-       while (!diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
+       while (info->nitem != NULL &&
+                  !diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
                if ((error = git_iterator_advance(&info->nitem, info->new_iter)) < 0)
                        break;
        }
index 94fd7165d11253e7b80db69ae9c7ab975ca65c48..18182ea965e83994855a73919f41f559b1677c8e 100644 (file)
@@ -1220,3 +1220,28 @@ void test_diff_workdir__untracked_directory_scenarios(void)
 
        git_diff_list_free(diff);
 }
+
+
+void test_diff_workdir__untracked_directory_comes_last(void)
+{
+       git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+       git_diff_list *diff = NULL;
+
+       g_repo = cl_git_sandbox_init("renames");
+
+       cl_git_mkfile("renames/.gitignore", "*.ign\n");
+       cl_git_pass(p_mkdir("renames/zzz_untracked", 0777));
+       cl_git_mkfile("renames/zzz_untracked/an.ign", "ignore me please");
+       cl_git_mkfile("renames/zzz_untracked/skip.ign", "ignore me really");
+       cl_git_mkfile("renames/zzz_untracked/test.ign", "ignore me now");
+
+       opts.context_lines = 3;
+       opts.interhunk_lines = 1;
+       opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
+
+       cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+       cl_assert(diff != NULL);
+
+       git_diff_list_free(diff);
+}