Skip to content

Commit

Permalink
Merge pull request #1701 from yorah/fix/gh-1698
Browse files Browse the repository at this point in the history
Fix segfault in git_status_foreach_ext()
  • Loading branch information
arrbee committed Jul 3, 2013
2 parents 6bb7bff + 9b6075b commit 4ae2905
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,7 @@ int git_diff__paired_foreach(
git_vector_sort(&idx2wd->deltas);
}
}
else if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE)
else if (head2idx != NULL && head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE)
strcomp = git__strcasecmp;

for (i = 0, j = 0; i < i_max || j < j_max; ) {
Expand Down
12 changes: 7 additions & 5 deletions src/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ int git_status_list_new(
opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
int error = 0;
unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS;
git_diff_list *head2idx = NULL;

assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);

Expand Down Expand Up @@ -307,8 +308,10 @@ int git_status_list_new(
&status->head2idx, repo, head, NULL, &diffopt)) < 0)
goto done;

head2idx = status->head2idx;

if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 &&
(error = git_diff_find_similar(status->head2idx, NULL)) < 0)
(error = git_diff_find_similar(head2idx, NULL)) < 0)
goto done;
}

Expand All @@ -324,15 +327,14 @@ int git_status_list_new(

if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) {
if ((error = git_diff__paired_foreach(
status->head2idx, NULL, status_collect, status)) < 0)
head2idx, NULL, status_collect, status)) < 0)
goto done;

git_diff_list_free(status->head2idx);
status->head2idx = NULL;
head2idx = NULL;
}

if ((error = git_diff__paired_foreach(
status->head2idx, status->idx2wd, status_collect, status)) < 0)
head2idx, status->idx2wd, status_collect, status)) < 0)
goto done;

if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY)
Expand Down
127 changes: 127 additions & 0 deletions tests-clar/status/status_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,130 @@ static const unsigned int entry_statuses4[] = {
};

static const int entry_count4 = 23;


/* entries for a copy of tests/resources/status with options
* passed to the status call in order to only get the differences
* between the HEAD and the index (changes to be committed)
*/

static const char *entry_paths5[] = {
"staged_changes",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_file_deleted",
"staged_delete_modified_file",
"staged_new_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
};

static const unsigned int entry_statuses5[] = {
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_INDEX_NEW,
};

static const int entry_count5 = 8;


/* entries for a copy of tests/resources/status with options
* passed to the status call in order to only get the differences
* between the workdir and the index (changes not staged, untracked files)
*/

static const char *entry_paths6[] = {
"file_deleted",
"ignored_file",
"modified_file",
"new_file",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_modified_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
"subdir/deleted_file",
"subdir/modified_file",
"subdir/new_file",
"\xe8\xbf\x99",
};

static const unsigned int entry_statuses6[] = {
GIT_STATUS_WT_DELETED,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
};

static const int entry_count6 = 13;


/* entries for a copy of tests/resources/status with options
* passed to the status call in order to get the differences
* between the HEAD and the index and then between the workdir
* and the index.
*/

static const char *entry_paths7[] = {
"staged_changes",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_file_deleted",
"staged_delete_modified_file",
"staged_new_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
"file_deleted",
"ignored_file",
"modified_file",
"new_file",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_modified_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
"subdir/deleted_file",
"subdir/modified_file",
"subdir/new_file",
"\xe8\xbf\x99",
};

static const unsigned int entry_statuses7[] = {
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
};

static const int entry_count7 = 21;
48 changes: 48 additions & 0 deletions tests-clar/status/worktree.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,54 @@ void test_status_worktree__whole_repository(void)
cl_assert_equal_i(0, counts.wrong_sorted_path);
}

void assert_show(const int entry_counts, const char *entry_paths[],
const unsigned int entry_statuses[], git_status_show_t show)
{
status_entry_counts counts;
git_repository *repo = cl_git_sandbox_init("status");
git_status_options opts = GIT_STATUS_OPTIONS_INIT;

memset(&counts, 0x0, sizeof(status_entry_counts));
counts.expected_entry_count = entry_counts;
counts.expected_paths = entry_paths;
counts.expected_statuses = entry_statuses;

opts.flags = GIT_STATUS_OPT_DEFAULTS;
opts.show = show;

cl_git_pass(
git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)
);

cl_assert_equal_i(counts.expected_entry_count, counts.entry_count);
cl_assert_equal_i(0, counts.wrong_status_flags_count);
cl_assert_equal_i(0, counts.wrong_sorted_path);
}

void test_status_worktree__show_index_and_workdir(void)
{
assert_show(entry_count0, entry_paths0, entry_statuses0,
GIT_STATUS_SHOW_INDEX_AND_WORKDIR);
}

void test_status_worktree__show_index_only(void)
{
assert_show(entry_count5, entry_paths5, entry_statuses5,
GIT_STATUS_SHOW_INDEX_ONLY);
}

void test_status_worktree__show_workdir_only(void)
{
assert_show(entry_count6, entry_paths6, entry_statuses6,
GIT_STATUS_SHOW_WORKDIR_ONLY);
}

void test_status_worktree__show_index_then_workdir_only(void)
{
assert_show(entry_count7, entry_paths7, entry_statuses7,
GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
}

/* this test is equivalent to t18-status.c:statuscb1 */
void test_status_worktree__empty_repository(void)
{
Expand Down

0 comments on commit 4ae2905

Please sign in to comment.