Merge branch 'ps/leakfixes-part-10' into ps/bisect-double-free-fix
* ps/leakfixes-part-10: (27 commits) t: remove TEST_PASSES_SANITIZE_LEAK annotations test-lib: unconditionally enable leak checking t: remove unneeded !SANITIZE_LEAK prerequisites t: mark some tests as leak free t5601: work around leak sanitizer issue git-compat-util: drop now-unused `UNLEAK()` macro global: drop `UNLEAK()` annotation t/helper: fix leaking commit graph in "read-graph" subcommand builtin/branch: fix leaking sorting options builtin/init-db: fix leaking directory paths builtin/help: fix leaks in `check_git_cmd()` help: fix leaking return value from `help_unknown_cmd()` help: fix leaking `struct cmdnames` help: refactor to not use globals for reading config builtin/sparse-checkout: fix leaking sanitized patterns split-index: fix memory leak in `move_cache_to_base_index()` git: refactor builtin handling to use a `struct strvec` git: refactor alias handling to use a `struct strvec` strvec: introduce new `strvec_splice()` function line-log: fix leak when rewriting commit parents ...
This commit is contained in:
@ -1216,12 +1216,6 @@ parse_done:
|
||||
output_option &= ~(OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR);
|
||||
|
||||
output(&sb, output_option);
|
||||
free((void *)sb.final_buf);
|
||||
for (ent = sb.ent; ent; ) {
|
||||
struct blame_entry *e = ent->next;
|
||||
free(ent);
|
||||
ent = e;
|
||||
}
|
||||
|
||||
if (show_stats) {
|
||||
printf("num read blob: %d\n", sb.num_read_blob);
|
||||
@ -1230,6 +1224,12 @@ parse_done:
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (ent = sb.ent; ent; ) {
|
||||
struct blame_entry *e = ent->next;
|
||||
free(ent);
|
||||
ent = e;
|
||||
}
|
||||
|
||||
free(path);
|
||||
cleanup_scoreboard(&sb);
|
||||
release_revisions(&revs);
|
||||
|
@ -722,6 +722,7 @@ int cmd_branch(int argc,
|
||||
static struct ref_sorting *sorting;
|
||||
struct string_list sorting_options = STRING_LIST_INIT_DUP;
|
||||
struct ref_format format = REF_FORMAT_INIT;
|
||||
int ret;
|
||||
|
||||
struct option options[] = {
|
||||
OPT_GROUP(N_("Generic options")),
|
||||
@ -851,15 +852,15 @@ int cmd_branch(int argc,
|
||||
if (list)
|
||||
setup_auto_pager("branch", 1);
|
||||
|
||||
UNLEAK(sorting_options);
|
||||
|
||||
if (delete) {
|
||||
if (!argc)
|
||||
die(_("branch name required"));
|
||||
return delete_branches(argc, argv, delete > 1, filter.kind, quiet);
|
||||
ret = delete_branches(argc, argv, delete > 1, filter.kind, quiet);
|
||||
goto out;
|
||||
} else if (show_current) {
|
||||
print_current_branch_name();
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else if (list) {
|
||||
/* git branch --list also shows HEAD when it is detached */
|
||||
if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached)
|
||||
@ -882,12 +883,13 @@ int cmd_branch(int argc,
|
||||
ref_sorting_release(sorting);
|
||||
ref_filter_clear(&filter);
|
||||
ref_format_clear(&format);
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else if (edit_description) {
|
||||
const char *branch_name;
|
||||
struct strbuf branch_ref = STRBUF_INIT;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret = 1; /* assume failure */
|
||||
|
||||
if (!argc) {
|
||||
if (filter.detached)
|
||||
@ -901,18 +903,22 @@ int cmd_branch(int argc,
|
||||
}
|
||||
|
||||
strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
|
||||
if (!refs_ref_exists(get_main_ref_store(the_repository), branch_ref.buf))
|
||||
if (!refs_ref_exists(get_main_ref_store(the_repository), branch_ref.buf)) {
|
||||
error((!argc || branch_checked_out(branch_ref.buf))
|
||||
? _("no commit on branch '%s' yet")
|
||||
: _("no branch named '%s'"),
|
||||
branch_name);
|
||||
else if (!edit_branch_description(branch_name))
|
||||
ret = 1;
|
||||
} else if (!edit_branch_description(branch_name)) {
|
||||
ret = 0; /* happy */
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
strbuf_release(&branch_ref);
|
||||
strbuf_release(&buf);
|
||||
|
||||
return ret;
|
||||
goto out;
|
||||
} else if (copy || rename) {
|
||||
if (!argc)
|
||||
die(_("branch name required"));
|
||||
@ -1000,12 +1006,17 @@ int cmd_branch(int argc,
|
||||
create_branches_recursively(the_repository, branch_name,
|
||||
start_name, NULL, force,
|
||||
reflog, quiet, track, 0);
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
create_branch(the_repository, branch_name, start_name, force, 0,
|
||||
reflog, quiet, track, 0);
|
||||
} else
|
||||
usage_with_options(builtin_branch_usage, options);
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
string_list_clear(&sorting_options, 0);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1586,7 +1586,6 @@ int cmd_clone(int argc,
|
||||
free(dir);
|
||||
free(path);
|
||||
free(repo_to_free);
|
||||
UNLEAK(repo);
|
||||
junk_mode = JUNK_LEAVE_ALL;
|
||||
|
||||
transport_ls_refs_options_release(&transport_ls_refs_options);
|
||||
|
@ -628,6 +628,5 @@ int cmd_diff(int argc,
|
||||
release_revisions(&rev);
|
||||
object_array_clear(&ent);
|
||||
symdiff_release(&sdiff);
|
||||
UNLEAK(blob);
|
||||
return result;
|
||||
}
|
||||
|
@ -551,12 +551,12 @@ static void show_html_page(const char *page)
|
||||
open_html(page_path.buf);
|
||||
}
|
||||
|
||||
static const char *check_git_cmd(const char* cmd)
|
||||
static char *check_git_cmd(const char *cmd)
|
||||
{
|
||||
char *alias;
|
||||
|
||||
if (is_git_command(cmd))
|
||||
return cmd;
|
||||
return xstrdup(cmd);
|
||||
|
||||
alias = alias_lookup(cmd);
|
||||
if (alias) {
|
||||
@ -589,14 +589,13 @@ static const char *check_git_cmd(const char* cmd)
|
||||
die(_("bad alias.%s string: %s"), cmd,
|
||||
split_cmdline_strerror(count));
|
||||
free(argv);
|
||||
UNLEAK(alias);
|
||||
return alias;
|
||||
}
|
||||
|
||||
if (exclude_guides)
|
||||
return help_unknown_cmd(cmd);
|
||||
|
||||
return cmd;
|
||||
return xstrdup(cmd);
|
||||
}
|
||||
|
||||
static void no_help_format(const char *opt_mode, enum help_format fmt)
|
||||
@ -642,6 +641,7 @@ int cmd_help(int argc,
|
||||
{
|
||||
int nongit;
|
||||
enum help_format parsed_help_format;
|
||||
char *command = NULL;
|
||||
const char *page;
|
||||
|
||||
argc = parse_options(argc, argv, prefix, builtin_help_options,
|
||||
@ -713,9 +713,9 @@ int cmd_help(int argc,
|
||||
if (help_format == HELP_FORMAT_NONE)
|
||||
help_format = parse_help_format(DEFAULT_HELP_FORMAT);
|
||||
|
||||
argv[0] = check_git_cmd(argv[0]);
|
||||
command = check_git_cmd(argv[0]);
|
||||
|
||||
page = cmd_to_page(argv[0]);
|
||||
page = cmd_to_page(command);
|
||||
switch (help_format) {
|
||||
case HELP_FORMAT_NONE:
|
||||
case HELP_FORMAT_MAN:
|
||||
@ -729,5 +729,6 @@ int cmd_help(int argc,
|
||||
break;
|
||||
}
|
||||
|
||||
free(command);
|
||||
return 0;
|
||||
}
|
||||
|
@ -75,10 +75,12 @@ int cmd_init_db(int argc,
|
||||
const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
{
|
||||
const char *git_dir;
|
||||
char *git_dir;
|
||||
const char *real_git_dir = NULL;
|
||||
const char *work_tree;
|
||||
char *real_git_dir_to_free = NULL;
|
||||
char *work_tree = NULL;
|
||||
const char *template_dir = NULL;
|
||||
char *template_dir_to_free = NULL;
|
||||
unsigned int flags = 0;
|
||||
const char *object_format = NULL;
|
||||
const char *ref_format = NULL;
|
||||
@ -106,6 +108,7 @@ int cmd_init_db(int argc,
|
||||
N_("specify the reference format to use")),
|
||||
OPT_END()
|
||||
};
|
||||
int ret;
|
||||
|
||||
argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
|
||||
|
||||
@ -113,12 +116,10 @@ int cmd_init_db(int argc,
|
||||
die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
|
||||
|
||||
if (real_git_dir && !is_absolute_path(real_git_dir))
|
||||
real_git_dir = real_pathdup(real_git_dir, 1);
|
||||
real_git_dir = real_git_dir_to_free = real_pathdup(real_git_dir, 1);
|
||||
|
||||
if (template_dir && *template_dir && !is_absolute_path(template_dir)) {
|
||||
template_dir = absolute_pathdup(template_dir);
|
||||
UNLEAK(template_dir);
|
||||
}
|
||||
if (template_dir && *template_dir && !is_absolute_path(template_dir))
|
||||
template_dir = template_dir_to_free = absolute_pathdup(template_dir);
|
||||
|
||||
if (argc == 1) {
|
||||
int mkdir_tried = 0;
|
||||
@ -192,7 +193,7 @@ int cmd_init_db(int argc,
|
||||
* Set up the default .git directory contents
|
||||
*/
|
||||
if (!git_dir)
|
||||
git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
|
||||
git_dir = xstrdup(DEFAULT_GIT_DIR_ENVIRONMENT);
|
||||
|
||||
/*
|
||||
* When --separate-git-dir is used inside a linked worktree, take
|
||||
@ -213,6 +214,7 @@ int cmd_init_db(int argc,
|
||||
if (chdir(mainwt.buf) < 0)
|
||||
die_errno(_("cannot chdir to %s"), mainwt.buf);
|
||||
strbuf_release(&mainwt);
|
||||
free(git_dir);
|
||||
git_dir = strbuf_detach(&sb, NULL);
|
||||
}
|
||||
strbuf_release(&sb);
|
||||
@ -245,12 +247,14 @@ int cmd_init_db(int argc,
|
||||
set_git_work_tree(work_tree);
|
||||
}
|
||||
|
||||
UNLEAK(real_git_dir);
|
||||
UNLEAK(git_dir);
|
||||
UNLEAK(work_tree);
|
||||
|
||||
flags |= INIT_DB_EXIST_OK;
|
||||
return init_db(git_dir, real_git_dir, template_dir, hash_algo,
|
||||
ref_storage_format, initial_branch,
|
||||
init_shared_repository, flags);
|
||||
ret = init_db(git_dir, real_git_dir, template_dir, hash_algo,
|
||||
ref_storage_format, initial_branch,
|
||||
init_shared_repository, flags);
|
||||
|
||||
free(template_dir_to_free);
|
||||
free(real_git_dir_to_free);
|
||||
free(work_tree);
|
||||
free(git_dir);
|
||||
return ret;
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ static void add_patterns_literal(int argc, const char **argv,
|
||||
add_patterns_from_input(pl, argc, argv, use_stdin ? stdin : NULL);
|
||||
}
|
||||
|
||||
static int modify_pattern_list(int argc, const char **argv, int use_stdin,
|
||||
static int modify_pattern_list(struct strvec *args, int use_stdin,
|
||||
enum modify_type m)
|
||||
{
|
||||
int result;
|
||||
@ -679,13 +679,13 @@ static int modify_pattern_list(int argc, const char **argv, int use_stdin,
|
||||
switch (m) {
|
||||
case ADD:
|
||||
if (core_sparse_checkout_cone)
|
||||
add_patterns_cone_mode(argc, argv, pl, use_stdin);
|
||||
add_patterns_cone_mode(args->nr, args->v, pl, use_stdin);
|
||||
else
|
||||
add_patterns_literal(argc, argv, pl, use_stdin);
|
||||
add_patterns_literal(args->nr, args->v, pl, use_stdin);
|
||||
break;
|
||||
|
||||
case REPLACE:
|
||||
add_patterns_from_input(pl, argc, argv,
|
||||
add_patterns_from_input(pl, args->nr, args->v,
|
||||
use_stdin ? stdin : NULL);
|
||||
break;
|
||||
}
|
||||
@ -706,12 +706,12 @@ static int modify_pattern_list(int argc, const char **argv, int use_stdin,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void sanitize_paths(int argc, const char **argv,
|
||||
static void sanitize_paths(struct strvec *args,
|
||||
const char *prefix, int skip_checks)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!argc)
|
||||
if (!args->nr)
|
||||
return;
|
||||
|
||||
if (prefix && *prefix && core_sparse_checkout_cone) {
|
||||
@ -721,8 +721,11 @@ static void sanitize_paths(int argc, const char **argv,
|
||||
*/
|
||||
int prefix_len = strlen(prefix);
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
argv[i] = prefix_path(prefix, prefix_len, argv[i]);
|
||||
for (i = 0; i < args->nr; i++) {
|
||||
char *prefixed_path = prefix_path(prefix, prefix_len, args->v[i]);
|
||||
strvec_replace(args, i, prefixed_path);
|
||||
free(prefixed_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_checks)
|
||||
@ -732,20 +735,20 @@ static void sanitize_paths(int argc, const char **argv,
|
||||
die(_("please run from the toplevel directory in non-cone mode"));
|
||||
|
||||
if (core_sparse_checkout_cone) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i][0] == '/')
|
||||
for (i = 0; i < args->nr; i++) {
|
||||
if (args->v[i][0] == '/')
|
||||
die(_("specify directories rather than patterns (no leading slash)"));
|
||||
if (argv[i][0] == '!')
|
||||
if (args->v[i][0] == '!')
|
||||
die(_("specify directories rather than patterns. If your directory starts with a '!', pass --skip-checks"));
|
||||
if (strpbrk(argv[i], "*?[]"))
|
||||
if (strpbrk(args->v[i], "*?[]"))
|
||||
die(_("specify directories rather than patterns. If your directory really has any of '*?[]\\' in it, pass --skip-checks"));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
for (i = 0; i < args->nr; i++) {
|
||||
struct cache_entry *ce;
|
||||
struct index_state *index = the_repository->index;
|
||||
int pos = index_name_pos(index, argv[i], strlen(argv[i]));
|
||||
int pos = index_name_pos(index, args->v[i], strlen(args->v[i]));
|
||||
|
||||
if (pos < 0)
|
||||
continue;
|
||||
@ -754,9 +757,9 @@ static void sanitize_paths(int argc, const char **argv,
|
||||
continue;
|
||||
|
||||
if (core_sparse_checkout_cone)
|
||||
die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), argv[i]);
|
||||
die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), args->v[i]);
|
||||
else
|
||||
warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), argv[i]);
|
||||
warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), args->v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -780,6 +783,8 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix)
|
||||
N_("read patterns from standard in")),
|
||||
OPT_END(),
|
||||
};
|
||||
struct strvec patterns = STRVEC_INIT;
|
||||
int ret;
|
||||
|
||||
setup_work_tree();
|
||||
if (!core_apply_sparse_checkout)
|
||||
@ -791,9 +796,14 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix)
|
||||
builtin_sparse_checkout_add_options,
|
||||
builtin_sparse_checkout_add_usage, 0);
|
||||
|
||||
sanitize_paths(argc, argv, prefix, add_opts.skip_checks);
|
||||
for (int i = 0; i < argc; i++)
|
||||
strvec_push(&patterns, argv[i]);
|
||||
sanitize_paths(&patterns, prefix, add_opts.skip_checks);
|
||||
|
||||
return modify_pattern_list(argc, argv, add_opts.use_stdin, ADD);
|
||||
ret = modify_pattern_list(&patterns, add_opts.use_stdin, ADD);
|
||||
|
||||
strvec_clear(&patterns);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char const * const builtin_sparse_checkout_set_usage[] = {
|
||||
@ -826,6 +836,8 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
|
||||
PARSE_OPT_NONEG),
|
||||
OPT_END(),
|
||||
};
|
||||
struct strvec patterns = STRVEC_INIT;
|
||||
int ret;
|
||||
|
||||
setup_work_tree();
|
||||
repo_read_index(the_repository);
|
||||
@ -846,13 +858,18 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
|
||||
* top-level directory (much as 'init' would do).
|
||||
*/
|
||||
if (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {
|
||||
argv = default_patterns;
|
||||
argc = default_patterns_nr;
|
||||
for (int i = 0; i < default_patterns_nr; i++)
|
||||
strvec_push(&patterns, default_patterns[i]);
|
||||
} else {
|
||||
sanitize_paths(argc, argv, prefix, set_opts.skip_checks);
|
||||
for (int i = 0; i < argc; i++)
|
||||
strvec_push(&patterns, argv[i]);
|
||||
sanitize_paths(&patterns, prefix, set_opts.skip_checks);
|
||||
}
|
||||
|
||||
return modify_pattern_list(argc, argv, set_opts.use_stdin, REPLACE);
|
||||
ret = modify_pattern_list(&patterns, set_opts.use_stdin, REPLACE);
|
||||
|
||||
strvec_clear(&patterns);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char const * const builtin_sparse_checkout_reapply_usage[] = {
|
||||
|
Reference in New Issue
Block a user