Merge branch 'ab/plug-leak-in-revisions'

Plug the memory leaks from the trickiest API of all, the revision
walker.

* ab/plug-leak-in-revisions: (27 commits)
  revisions API: add a TODO for diff_free(&revs->diffopt)
  revisions API: have release_revisions() release "topo_walk_info"
  revisions API: have release_revisions() release "date_mode"
  revisions API: call diff_free(&revs->pruning) in revisions_release()
  revisions API: release "reflog_info" in release revisions()
  revisions API: clear "boundary_commits" in release_revisions()
  revisions API: have release_revisions() release "prune_data"
  revisions API: have release_revisions() release "grep_filter"
  revisions API: have release_revisions() release "filter"
  revisions API: have release_revisions() release "cmdline"
  revisions API: have release_revisions() release "mailmap"
  revisions API: have release_revisions() release "commits"
  revisions API users: use release_revisions() for "prune_data" users
  revisions API users: use release_revisions() with UNLEAK()
  revisions API users: use release_revisions() in builtin/log.c
  revisions API users: use release_revisions() in http-push.c
  revisions API users: add "goto cleanup" for release_revisions()
  stash: always have the owner of "stash_info" free it
  revisions API users: use release_revisions() needing REV_INFO_INIT
  revision.[ch]: document and move code declared around "init"
  ...
This commit is contained in:
Junio C Hamano
2022-06-07 14:10:56 -07:00
117 changed files with 500 additions and 190 deletions

View File

@ -606,6 +606,10 @@ static struct commit *one_relevant_parent(const struct rev_info *revs,
*
* 2. We saw anything except REV_TREE_NEW.
*/
#define REV_TREE_SAME 0
#define REV_TREE_NEW 1 /* Only new files */
#define REV_TREE_OLD 2 /* Only files removed */
#define REV_TREE_DIFFERENT 3 /* Mixed changes */
static int tree_difference = REV_TREE_SAME;
static void file_add_remove(struct diff_options *options,
@ -1459,10 +1463,9 @@ static int limit_list(struct rev_info *revs)
if (revs->left_only || revs->right_only)
limit_left_right(newlist, revs);
if (bottom) {
if (bottom)
limit_to_ancestry(bottom, newlist);
free_commit_list(bottom);
}
free_commit_list(bottom);
/*
* Check if any commits have become TREESAME by some of their parents
@ -2930,6 +2933,42 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
return left;
}
static void release_revisions_cmdline(struct rev_cmdline_info *cmdline)
{
unsigned int i;
for (i = 0; i < cmdline->nr; i++)
free((char *)cmdline->rev[i].name);
free(cmdline->rev);
}
static void release_revisions_mailmap(struct string_list *mailmap)
{
if (!mailmap)
return;
clear_mailmap(mailmap);
free(mailmap);
}
static void release_revisions_topo_walk_info(struct topo_walk_info *info);
void release_revisions(struct rev_info *revs)
{
free_commit_list(revs->commits);
object_array_clear(&revs->pending);
object_array_clear(&revs->boundary_commits);
release_revisions_cmdline(&revs->cmdline);
list_objects_filter_release(&revs->filter);
clear_pathspec(&revs->prune_data);
date_mode_release(&revs->date_mode);
release_revisions_mailmap(revs->mailmap);
free_grep_patterns(&revs->grep_filter);
/* TODO (need to handle "no_free"): diff_free(&revs->diffopt) */
diff_free(&revs->pruning);
reflog_walk_info_release(revs->reflog_info);
release_revisions_topo_walk_info(revs->topo_walk_info);
}
static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
{
struct commit_list *l = xcalloc(1, sizeof(*l));
@ -3440,17 +3479,22 @@ static void compute_indegrees_to_depth(struct rev_info *revs,
indegree_walk_step(revs);
}
static void reset_topo_walk(struct rev_info *revs)
static void release_revisions_topo_walk_info(struct topo_walk_info *info)
{
struct topo_walk_info *info = revs->topo_walk_info;
if (!info)
return;
clear_prio_queue(&info->explore_queue);
clear_prio_queue(&info->indegree_queue);
clear_prio_queue(&info->topo_queue);
clear_indegree_slab(&info->indegree);
clear_author_date_slab(&info->author_date);
free(info);
}
FREE_AND_NULL(revs->topo_walk_info);
static void reset_topo_walk(struct rev_info *revs)
{
release_revisions_topo_walk_info(revs->topo_walk_info);
revs->topo_walk_info = NULL;
}
static void init_topo_walk(struct rev_info *revs)
@ -4090,10 +4134,8 @@ static void create_boundary_commit_list(struct rev_info *revs)
* boundary commits anyway. (This is what the code has always
* done.)
*/
if (revs->commits) {
free_commit_list(revs->commits);
revs->commits = NULL;
}
free_commit_list(revs->commits);
revs->commits = NULL;
/*
* Put all of the actual boundary commits from revs->boundary_commits
@ -4230,10 +4272,8 @@ struct commit *get_revision(struct rev_info *revs)
graph_update(revs->graph, c);
if (!c) {
free_saved_parents(revs);
if (revs->previous_parents) {
free_commit_list(revs->previous_parents);
revs->previous_parents = NULL;
}
free_commit_list(revs->previous_parents);
revs->previous_parents = NULL;
}
return c;
}