Unverified Commit 4d3392dd by Edward Thomson Committed by GitHub

Merge pull request #5214 from pks-t/pks/diff-iterator-allocation-fixes

Memory allocation fixes for diff generator
parents 39028eb6 699de9c5
...@@ -1262,29 +1262,31 @@ cleanup: ...@@ -1262,29 +1262,31 @@ cleanup:
return error; return error;
} }
#define DIFF_FROM_ITERATORS(MAKE_FIRST, FLAGS_FIRST, MAKE_SECOND, FLAGS_SECOND) do { \ static int diff_prepare_iterator_opts(char **prefix, git_iterator_options *a, int aflags,
git_iterator *a = NULL, *b = NULL; \ git_iterator_options *b, int bflags,
char *pfx = (opts && !(opts->flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH)) ? \ const git_diff_options *opts)
git_pathspec_prefix(&opts->pathspec) : NULL; \ {
git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, \ GIT_ERROR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options");
b_opts = GIT_ITERATOR_OPTIONS_INIT; \
a_opts.flags = FLAGS_FIRST; \ *prefix = NULL;
a_opts.start = pfx; \
a_opts.end = pfx; \ if (opts && (opts->flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH)) {
b_opts.flags = FLAGS_SECOND; \ a->pathlist.strings = opts->pathspec.strings;
b_opts.start = pfx; \ a->pathlist.count = opts->pathspec.count;
b_opts.end = pfx; \ b->pathlist.strings = opts->pathspec.strings;
GIT_ERROR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \ b->pathlist.count = opts->pathspec.count;
if (opts && (opts->flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH)) { \ } else if (opts) {
a_opts.pathlist.strings = opts->pathspec.strings; \ *prefix = git_pathspec_prefix(&opts->pathspec);
a_opts.pathlist.count = opts->pathspec.count; \ GIT_ERROR_CHECK_ALLOC(prefix);
b_opts.pathlist.strings = opts->pathspec.strings; \ }
b_opts.pathlist.count = opts->pathspec.count; \
} \ a->flags = aflags;
if (!error && !(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \ b->flags = bflags;
error = git_diff__from_iterators(&diff, repo, a, b, opts); \ a->start = b->start = *prefix;
git__free(pfx); git_iterator_free(a); git_iterator_free(b); \ a->end = b->end = *prefix;
} while (0)
return 0;
}
int git_diff_tree_to_tree( int git_diff_tree_to_tree(
git_diff **out, git_diff **out,
...@@ -1293,8 +1295,12 @@ int git_diff_tree_to_tree( ...@@ -1293,8 +1295,12 @@ int git_diff_tree_to_tree(
git_tree *new_tree, git_tree *new_tree,
const git_diff_options *opts) const git_diff_options *opts)
{ {
git_diff *diff = NULL;
git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE; git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE;
git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT,
b_opts = GIT_ITERATOR_OPTIONS_INIT;
git_iterator *a = NULL, *b = NULL;
git_diff *diff = NULL;
char *prefix = NULL;
int error = 0; int error = 0;
assert(out && repo); assert(out && repo);
...@@ -1308,13 +1314,19 @@ int git_diff_tree_to_tree( ...@@ -1308,13 +1314,19 @@ int git_diff_tree_to_tree(
if (opts && (opts->flags & GIT_DIFF_IGNORE_CASE) != 0) if (opts && (opts->flags & GIT_DIFF_IGNORE_CASE) != 0)
iflag = GIT_ITERATOR_IGNORE_CASE; iflag = GIT_ITERATOR_IGNORE_CASE;
DIFF_FROM_ITERATORS( if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, iflag, &b_opts, iflag, opts)) < 0 ||
git_iterator_for_tree(&a, old_tree, &a_opts), iflag, (error = git_iterator_for_tree(&a, old_tree, &a_opts)) < 0 ||
git_iterator_for_tree(&b, new_tree, &b_opts), iflag (error = git_iterator_for_tree(&b, new_tree, &b_opts)) < 0 ||
); (error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0)
goto out;
if (!error)
*out = diff; *out = diff;
diff = NULL;
out:
git_iterator_free(a);
git_iterator_free(b);
git_diff_free(diff);
git__free(prefix);
return error; return error;
} }
...@@ -1337,9 +1349,13 @@ int git_diff_tree_to_index( ...@@ -1337,9 +1349,13 @@ int git_diff_tree_to_index(
git_index *index, git_index *index,
const git_diff_options *opts) const git_diff_options *opts)
{ {
git_diff *diff = NULL;
git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE | git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE |
GIT_ITERATOR_INCLUDE_CONFLICTS; GIT_ITERATOR_INCLUDE_CONFLICTS;
git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT,
b_opts = GIT_ITERATOR_OPTIONS_INIT;
git_iterator *a = NULL, *b = NULL;
git_diff *diff = NULL;
char *prefix = NULL;
bool index_ignore_case = false; bool index_ignore_case = false;
int error = 0; int error = 0;
...@@ -1352,17 +1368,23 @@ int git_diff_tree_to_index( ...@@ -1352,17 +1368,23 @@ int git_diff_tree_to_index(
index_ignore_case = index->ignore_case; index_ignore_case = index->ignore_case;
DIFF_FROM_ITERATORS( if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, iflag, &b_opts, iflag, opts)) < 0 ||
git_iterator_for_tree(&a, old_tree, &a_opts), iflag, (error = git_iterator_for_tree(&a, old_tree, &a_opts)) < 0 ||
git_iterator_for_index(&b, repo, index, &b_opts), iflag (error = git_iterator_for_index(&b, repo, index, &b_opts)) < 0 ||
); (error = git_diff__from_iterators(&diff, repo, a, b, opts) < 0))
goto out;
/* if index is in case-insensitive order, re-sort deltas to match */ /* if index is in case-insensitive order, re-sort deltas to match */
if (!error && index_ignore_case) if (index_ignore_case)
git_diff__set_ignore_case(diff, true); git_diff__set_ignore_case(diff, true);
if (!error)
*out = diff; *out = diff;
diff = NULL;
out:
git_iterator_free(a);
git_iterator_free(b);
git_diff_free(diff);
git__free(prefix);
return error; return error;
} }
...@@ -1373,7 +1395,11 @@ int git_diff_index_to_workdir( ...@@ -1373,7 +1395,11 @@ int git_diff_index_to_workdir(
git_index *index, git_index *index,
const git_diff_options *opts) const git_diff_options *opts)
{ {
git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT,
b_opts = GIT_ITERATOR_OPTIONS_INIT;
git_iterator *a = NULL, *b = NULL;
git_diff *diff = NULL; git_diff *diff = NULL;
char *prefix = NULL;
int error = 0; int error = 0;
assert(out && repo); assert(out && repo);
...@@ -1383,20 +1409,24 @@ int git_diff_index_to_workdir( ...@@ -1383,20 +1409,24 @@ int git_diff_index_to_workdir(
if (!index && (error = diff_load_index(&index, repo)) < 0) if (!index && (error = diff_load_index(&index, repo)) < 0)
return error; return error;
DIFF_FROM_ITERATORS( if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, GIT_ITERATOR_INCLUDE_CONFLICTS,
git_iterator_for_index(&a, repo, index, &a_opts), &b_opts, GIT_ITERATOR_DONT_AUTOEXPAND, opts)) < 0 ||
GIT_ITERATOR_INCLUDE_CONFLICTS, (error = git_iterator_for_index(&a, repo, index, &a_opts)) < 0 ||
(error = git_iterator_for_workdir(&b, repo, index, NULL, &b_opts)) < 0 ||
(error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0)
goto out;
git_iterator_for_workdir(&b, repo, index, NULL, &b_opts), if ((diff->opts.flags & GIT_DIFF_UPDATE_INDEX) && ((git_diff_generated *)diff)->index_updated)
GIT_ITERATOR_DONT_AUTOEXPAND if ((error = git_index_write(index)) < 0)
); goto out;
if (!error && (diff->opts.flags & GIT_DIFF_UPDATE_INDEX) != 0 &&
((git_diff_generated *)diff)->index_updated)
error = git_index_write(index);
if (!error)
*out = diff; *out = diff;
diff = NULL;
out:
git_iterator_free(a);
git_iterator_free(b);
git_diff_free(diff);
git__free(prefix);
return error; return error;
} }
...@@ -1407,24 +1437,33 @@ int git_diff_tree_to_workdir( ...@@ -1407,24 +1437,33 @@ int git_diff_tree_to_workdir(
git_tree *old_tree, git_tree *old_tree,
const git_diff_options *opts) const git_diff_options *opts)
{ {
git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT,
b_opts = GIT_ITERATOR_OPTIONS_INIT;
git_iterator *a = NULL, *b = NULL;
git_diff *diff = NULL; git_diff *diff = NULL;
char *prefix = NULL;
git_index *index; git_index *index;
int error = 0; int error;
assert(out && repo); assert(out && repo);
*out = NULL; *out = NULL;
if ((error = git_repository_index__weakptr(&index, repo))) if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, 0,
return error; &b_opts, GIT_ITERATOR_DONT_AUTOEXPAND, opts) < 0) ||
(error = git_repository_index__weakptr(&index, repo)) < 0 ||
(error = git_iterator_for_tree(&a, old_tree, &a_opts)) < 0 ||
(error = git_iterator_for_workdir(&b, repo, index, old_tree, &b_opts)) < 0 ||
(error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0)
goto out;
DIFF_FROM_ITERATORS(
git_iterator_for_tree(&a, old_tree, &a_opts), 0,
git_iterator_for_workdir(&b, repo, index, old_tree, &b_opts), GIT_ITERATOR_DONT_AUTOEXPAND
);
if (!error)
*out = diff; *out = diff;
diff = NULL;
out:
git_iterator_free(a);
git_iterator_free(b);
git_diff_free(diff);
git__free(prefix);
return error; return error;
} }
...@@ -1468,24 +1507,35 @@ int git_diff_index_to_index( ...@@ -1468,24 +1507,35 @@ int git_diff_index_to_index(
git_index *new_index, git_index *new_index,
const git_diff_options *opts) const git_diff_options *opts)
{ {
git_diff *diff; git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT,
int error = 0; b_opts = GIT_ITERATOR_OPTIONS_INIT;
git_iterator *a = NULL, *b = NULL;
git_diff *diff = NULL;
char *prefix = NULL;
int error;
assert(out && old_index && new_index); assert(out && old_index && new_index);
*out = NULL; *out = NULL;
DIFF_FROM_ITERATORS( if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, GIT_ITERATOR_DONT_IGNORE_CASE,
git_iterator_for_index(&a, repo, old_index, &a_opts), GIT_ITERATOR_DONT_IGNORE_CASE, &b_opts, GIT_ITERATOR_DONT_IGNORE_CASE, opts) < 0) ||
git_iterator_for_index(&b, repo, new_index, &b_opts), GIT_ITERATOR_DONT_IGNORE_CASE (error = git_iterator_for_index(&a, repo, old_index, &a_opts)) < 0 ||
); (error = git_iterator_for_index(&b, repo, new_index, &b_opts)) < 0 ||
(error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0)
goto out;
/* if index is in case-insensitive order, re-sort deltas to match */ /* if index is in case-insensitive order, re-sort deltas to match */
if (!error && (old_index->ignore_case || new_index->ignore_case)) if (old_index->ignore_case || new_index->ignore_case)
git_diff__set_ignore_case(diff, true); git_diff__set_ignore_case(diff, true);
if (!error)
*out = diff; *out = diff;
diff = NULL;
out:
git_iterator_free(a);
git_iterator_free(b);
git_diff_free(diff);
git__free(prefix);
return error; return error;
} }
......
...@@ -543,8 +543,6 @@ static int tree_iterator_frame_init( ...@@ -543,8 +543,6 @@ static int tree_iterator_frame_init(
new_frame = git_array_alloc(iter->frames); new_frame = git_array_alloc(iter->frames);
GIT_ERROR_CHECK_ALLOC(new_frame); GIT_ERROR_CHECK_ALLOC(new_frame);
memset(new_frame, 0, sizeof(tree_iterator_frame));
if ((error = git_tree_dup(&dup, tree)) < 0) if ((error = git_tree_dup(&dup, tree)) < 0)
goto done; goto done;
...@@ -558,13 +556,16 @@ static int tree_iterator_frame_init( ...@@ -558,13 +556,16 @@ static int tree_iterator_frame_init(
cmp = iterator__ignore_case(&iter->base) ? cmp = iterator__ignore_case(&iter->base) ?
tree_iterator_entry_sort_icase : NULL; tree_iterator_entry_sort_icase : NULL;
if ((error = git_vector_init( if ((error = git_vector_init(&new_frame->entries,
&new_frame->entries, dup->entries.size, cmp)) < 0) dup->entries.size, cmp)) < 0)
goto done; goto done;
git_array_foreach(dup->entries, i, tree_entry) { git_array_foreach(dup->entries, i, tree_entry) {
new_entry = git_pool_malloc(&iter->entry_pool, 1); if ((new_entry = git_pool_malloc(&iter->entry_pool, 1)) == NULL) {
GIT_ERROR_CHECK_ALLOC(new_entry); git_error_set_oom();
error = -1;
goto done;
}
new_entry->tree_entry = tree_entry; new_entry->tree_entry = tree_entry;
new_entry->parent_path = new_frame->path.ptr; new_entry->parent_path = new_frame->path.ptr;
......
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