Merge branch 'ps/leakfixes-part-4'

More leak fixes.

* ps/leakfixes-part-4: (22 commits)
  builtin/diff: free symmetric diff members
  diff: free state populated via options
  builtin/log: fix leak when showing converted blob contents
  userdiff: fix leaking memory for configured diff drivers
  builtin/format-patch: fix various trivial memory leaks
  diff: fix leak when parsing invalid ignore regex option
  unpack-trees: clear index when not propagating it
  sequencer: release todo list on error paths
  merge-ort: unconditionally release attributes index
  builtin/fast-export: plug leaking tag names
  builtin/fast-export: fix leaking diff options
  builtin/fast-import: plug trivial memory leaks
  builtin/notes: fix leaking `struct notes_tree` when merging notes
  builtin/rebase: fix leaking `commit.gpgsign` value
  config: fix leaking comment character config
  submodule-config: fix leaking name entry when traversing submodules
  read-cache: fix leaking hashfile when writing index fails
  bulk-checkin: fix leaking state TODO
  object-name: fix leaking symlink paths in object context
  object-file: fix memory leak when reading corrupted headers
  ...
This commit is contained in:
Junio C Hamano 2024-08-23 09:02:33 -07:00
commit 1b6b2bfae5
58 changed files with 265 additions and 142 deletions

View File

@ -684,7 +684,9 @@ static void adjust_comment_line_char(const struct strbuf *sb)
const char *p;
if (!memchr(sb->buf, candidates[0], sb->len)) {
comment_line_str = xstrfmt("%c", candidates[0]);
free(comment_line_str_to_free);
comment_line_str = comment_line_str_to_free =
xstrfmt("%c", candidates[0]);
return;
}
@ -705,7 +707,8 @@ static void adjust_comment_line_char(const struct strbuf *sb)
if (!*p)
die(_("unable to select a comment character that is not used\n"
"in the current commit message"));
comment_line_str = xstrfmt("%c", *p);
free(comment_line_str_to_free);
comment_line_str = comment_line_str_to_free = xstrfmt("%c", *p);
}
static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,

View File

@ -388,6 +388,11 @@ static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym)
sym->skip = map;
}
static void symdiff_release(struct symdiff *sdiff)
{
bitmap_free(sdiff->skip);
}
int cmd_diff(int argc, const char **argv, const char *prefix)
{
int i;
@ -619,6 +624,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
refresh_index_quietly();
release_revisions(&rev);
object_array_clear(&ent);
symdiff_release(&sdiff);
UNLEAK(blob);
return result;
}

View File

@ -42,8 +42,8 @@ static int full_tree;
static int reference_excluded_commits;
static int show_original_ids;
static int mark_tags;
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
static struct string_list extra_refs = STRING_LIST_INIT_DUP;
static struct string_list tag_refs = STRING_LIST_INIT_DUP;
static struct refspec refspecs = REFSPEC_INIT_FETCH;
static int anonymize;
static struct hashmap anonymized_seeds;
@ -901,7 +901,7 @@ static void handle_tag(const char *name, struct tag *tag)
free(buf);
}
static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
static struct commit *get_commit(struct rev_cmdline_entry *e, const char *full_name)
{
switch (e->item->type) {
case OBJ_COMMIT:
@ -932,14 +932,16 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
struct rev_cmdline_entry *e = info->rev + i;
struct object_id oid;
struct commit *commit;
char *full_name;
char *full_name = NULL;
if (e->flags & UNINTERESTING)
continue;
if (repo_dwim_ref(the_repository, e->name, strlen(e->name),
&oid, &full_name, 0) != 1)
&oid, &full_name, 0) != 1) {
free(full_name);
continue;
}
if (refspecs.nr) {
char *private;
@ -955,6 +957,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
warning("%s: Unexpected object of type %s, skipping.",
e->name,
type_name(e->item->type));
free(full_name);
continue;
}
@ -963,10 +966,12 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
break;
case OBJ_BLOB:
export_blob(&commit->object.oid);
free(full_name);
continue;
default: /* OBJ_TAG (nested tags) is already handled */
warning("Tag points to object of unexpected type %s, skipping.",
type_name(commit->object.type));
free(full_name);
continue;
}
@ -979,6 +984,8 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
if (!*revision_sources_at(&revision_sources, commit))
*revision_sources_at(&revision_sources, commit) = full_name;
else
free(full_name);
}
string_list_sort(&extra_refs);
@ -1278,9 +1285,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
revs.diffopt.format_callback = show_filemodify;
revs.diffopt.format_callback_data = &paths_of_changed_objects;
revs.diffopt.flags.recursive = 1;
revs.diffopt.no_free = 1;
while ((commit = get_revision(&revs)))
handle_commit(commit, &revs, &paths_of_changed_objects);
revs.diffopt.no_free = 0;
handle_tags_and_duplicates(&extra_refs);
handle_tags_and_duplicates(&tag_refs);

View File

@ -206,8 +206,8 @@ static unsigned int object_entry_alloc = 5000;
static struct object_entry_pool *blocks;
static struct hashmap object_table;
static struct mark_set *marks;
static const char *export_marks_file;
static const char *import_marks_file;
static char *export_marks_file;
static char *import_marks_file;
static int import_marks_file_from_stream;
static int import_marks_file_ignore_missing;
static int import_marks_file_done;
@ -3274,6 +3274,7 @@ static void option_import_marks(const char *marks,
read_marks();
}
free(import_marks_file);
import_marks_file = make_fast_import_path(marks);
import_marks_file_from_stream = from_stream;
import_marks_file_ignore_missing = ignore_missing;
@ -3316,6 +3317,7 @@ static void option_active_branches(const char *branches)
static void option_export_marks(const char *marks)
{
free(export_marks_file);
export_marks_file = make_fast_import_path(marks);
}
@ -3357,6 +3359,8 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list)
free(f);
string_list_insert(list, s)->util = ms;
free(s);
}
static int parse_one_option(const char *option)

View File

@ -707,6 +707,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
write_or_die(1, buf, size);
object_context_release(&obj_context);
free(buf);
return 0;
}
@ -1827,12 +1828,14 @@ static struct commit *get_base_commit(const struct format_config *cfg,
if (die_on_failure) {
die(_("failed to find exact merge base"));
} else {
free_commit_list(merge_base);
free(rev);
return NULL;
}
}
rev[i] = merge_base->item;
free_commit_list(merge_base);
}
if (rev_nr % 2)
@ -2023,6 +2026,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
const char *rfc = NULL;
int creation_factor = -1;
const char *signature = git_version_string;
char *signature_to_free = NULL;
char *signature_file_arg = NULL;
struct keep_callback_data keep_callback_data = {
.cfg = &cfg,
@ -2443,7 +2447,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (strbuf_read_file(&buf, signature_file, 128) < 0)
die_errno(_("unable to read signature file '%s'"), signature_file);
signature = strbuf_detach(&buf, NULL);
signature = signature_to_free = strbuf_detach(&buf, NULL);
} else if (cfg.signature) {
signature = cfg.signature;
}
@ -2548,12 +2552,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
else
print_signature(signature, rev.diffopt.file);
}
if (output_directory)
if (output_directory) {
fclose(rev.diffopt.file);
rev.diffopt.file = NULL;
}
}
stop_progress(&progress);
free(list);
free(branch_name);
if (ignore_if_in_upstream)
free_patch_ids(&ids);
@ -2565,11 +2570,14 @@ done:
strbuf_release(&rdiff_title);
free(description_file);
free(signature_file_arg);
free(signature_to_free);
free(branch_name);
free(to_free);
free(rev.message_id);
if (rev.ref_message_ids)
string_list_clear(rev.ref_message_ids, 0);
free(rev.ref_message_ids);
rev.diffopt.no_free = 0;
release_revisions(&rev);
format_config_release(&cfg);
return 0;

View File

@ -805,7 +805,7 @@ static int merge_commit(struct notes_merge_options *o)
{
struct strbuf msg = STRBUF_INIT;
struct object_id oid, parent_oid;
struct notes_tree *t;
struct notes_tree t = {0};
struct commit *partial;
struct pretty_print_context pretty_ctx;
void *local_ref_to_free;
@ -828,8 +828,7 @@ static int merge_commit(struct notes_merge_options *o)
else
oidclr(&parent_oid, the_repository->hash_algo);
CALLOC_ARRAY(t, 1);
init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
init_notes(&t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
o->local_ref = local_ref_to_free =
refs_resolve_refdup(get_main_ref_store(the_repository),
@ -837,7 +836,7 @@ static int merge_commit(struct notes_merge_options *o)
if (!o->local_ref)
die(_("failed to resolve NOTES_MERGE_REF"));
if (notes_merge_commit(o, t, partial, &oid))
if (notes_merge_commit(o, &t, partial, &oid))
die(_("failed to finalize notes merge"));
/* Reuse existing commit message in reflog message */
@ -851,7 +850,7 @@ static int merge_commit(struct notes_merge_options *o)
is_null_oid(&parent_oid) ? NULL : &parent_oid,
0, UPDATE_REFS_DIE_ON_ERR);
free_notes(t);
free_notes(&t);
strbuf_release(&msg);
ret = merge_abort(o);
free(local_ref_to_free);

View File

@ -186,6 +186,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
replay.committer_date_is_author_date =
opts->committer_date_is_author_date;
replay.ignore_date = opts->ignore_date;
free(replay.gpg_sign);
replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
replay.reflog_action = xstrdup(opts->reflog_action);
if (opts->strategy)

View File

@ -61,6 +61,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
if (state->nr_written == 0) {
close(state->f->fd);
free_hashfile(state->f);
unlink(state->pack_tmp_name);
goto clear_exit;
} else if (state->nr_written == 1) {
@ -83,6 +84,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
free(state->written[i]);
clear_exit:
free(state->pack_tmp_name);
free(state->written);
memset(state, 0, sizeof(*state));

View File

@ -1596,7 +1596,8 @@ static int git_default_core_config(const char *var, const char *value,
else if (value[0]) {
if (strchr(value, '\n'))
return error(_("%s cannot contain newline"), var);
comment_line_str = xstrdup(value);
comment_line_str = value;
FREE_AND_NULL(comment_line_str_to_free);
auto_comment_line_char = 0;
} else
return error(_("%s must have at least one character"), var);

View File

@ -56,7 +56,7 @@ void hashflush(struct hashfile *f)
}
}
static void free_hashfile(struct hashfile *f)
void free_hashfile(struct hashfile *f)
{
free(f->buffer);
free(f->check_buffer);

View File

@ -46,6 +46,16 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
struct hashfile *hashfd(int fd, const char *name);
struct hashfile *hashfd_check(const char *name);
struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
/*
* Free the hashfile without flushing its contents to disk. This only
* needs to be called when not calling `finalize_hashfile()`.
*/
void free_hashfile(struct hashfile *f);
/*
* Finalize the hashfile by flushing data to disk and free'ing it.
*/
int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int);
void discard_hashfile(struct hashfile *);
void hashwrite(struct hashfile *, const void *, unsigned int);

16
diff.c
View File

@ -5464,9 +5464,13 @@ static int diff_opt_ignore_regex(const struct option *opt,
regex_t *regex;
BUG_ON_OPT_NEG(unset);
regex = xmalloc(sizeof(*regex));
if (regcomp(regex, arg, REG_EXTENDED | REG_NEWLINE))
if (regcomp(regex, arg, REG_EXTENDED | REG_NEWLINE)) {
free(regex);
return error(_("invalid regex given to -I: '%s'"), arg);
}
ALLOC_GROW(options->ignore_regex, options->ignore_regex_nr + 1,
options->ignore_regex_alloc);
options->ignore_regex[options->ignore_regex_nr++] = regex;
@ -6713,6 +6717,16 @@ void diff_free(struct diff_options *options)
if (options->no_free)
return;
if (options->objfind) {
oidset_clear(options->objfind);
FREE_AND_NULL(options->objfind);
}
for (size_t i = 0; i < options->anchors_nr; i++)
free(options->anchors[i]);
FREE_AND_NULL(options->anchors);
options->anchors_nr = options->anchors_alloc = 0;
diff_free_file(options);
diff_free_ignore_regex(options);
clear_pathspec(&options->pathspec);

View File

@ -114,6 +114,7 @@ int protect_ntfs = PROTECT_NTFS_DEFAULT;
* that is subject to stripspace.
*/
const char *comment_line_str = "#";
char *comment_line_str_to_free;
int auto_comment_line_char;
/* Parallel index stat data preload? */

View File

@ -9,6 +9,7 @@ struct strvec;
* that is subject to stripspace.
*/
extern const char *comment_line_str;
extern char *comment_line_str_to_free;
extern int auto_comment_line_char;
/*

13
git.c
View File

@ -143,6 +143,13 @@ void setup_auto_pager(const char *cmd, int def)
commit_pager_choice();
}
static void print_system_path(const char *path)
{
char *s_path = system_path(path);
puts(s_path);
free(s_path);
}
static int handle_options(const char ***argv, int *argc, int *envchanged)
{
const char **orig_argv = *argv;
@ -173,15 +180,15 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
exit(0);
}
} else if (!strcmp(cmd, "--html-path")) {
puts(system_path(GIT_HTML_PATH));
print_system_path(GIT_HTML_PATH);
trace2_cmd_name("_query_");
exit(0);
} else if (!strcmp(cmd, "--man-path")) {
puts(system_path(GIT_MAN_PATH));
print_system_path(GIT_MAN_PATH);
trace2_cmd_name("_query_");
exit(0);
} else if (!strcmp(cmd, "--info-path")) {
puts(system_path(GIT_INFO_PATH));
print_system_path(GIT_INFO_PATH);
trace2_cmd_name("_query_");
exit(0);
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {

View File

@ -689,8 +689,7 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
*/
strmap_clear_func(&opti->conflicted, 0);
if (opti->attr_index.cache_nr) /* true iff opt->renormalize */
discard_index(&opti->attr_index);
discard_index(&opti->attr_index);
/* Free memory used by various renames maps */
for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) {

View File

@ -2953,6 +2953,7 @@ int read_loose_object(const char *path,
if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
NULL) != ULHR_OK) {
error(_("unable to unpack header of %s"), path);
git_inflate_end(&stream);
goto out;
}

View File

@ -1772,6 +1772,7 @@ int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
void object_context_release(struct object_context *ctx)
{
free(ctx->path);
strbuf_release(&ctx->symlink_path);
}
/*

View File

@ -450,8 +450,10 @@ static void output_pair_header(struct diff_options *diffopt,
}
static struct userdiff_driver section_headers = {
.funcname = { "^ ## (.*) ##$\n"
"^.?@@ (.*)$", REG_EXTENDED }
.funcname = {
.pattern = "^ ## (.*) ##$\n^.?@@ (.*)$",
.cflags = REG_EXTENDED,
},
};
static struct diff_filespec *get_filespec(const char *name, const char *p)

View File

@ -2840,8 +2840,9 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
int csum_fsync_flag;
int ieot_entries = 1;
struct index_entry_offset_table *ieot = NULL;
int nr, nr_threads;
struct repository *r = istate->repo;
struct strbuf sb = STRBUF_INIT;
int nr, nr_threads, ret;
f = hashfd(tempfile->fd, tempfile->filename.buf);
@ -2962,8 +2963,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
strbuf_release(&previous_name_buf);
if (err) {
free(ieot);
goto cleanup;
ret = err;
goto out;
}
offset = hashfile_total(f);
@ -2985,26 +2986,20 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
* index.
*/
if (ieot) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
write_ieot_extension(&sb, ieot);
err = write_index_ext_header(f, eoie_c, CACHE_EXT_INDEXENTRYOFFSETTABLE, sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
free(ieot);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
if (write_extensions & WRITE_SPLIT_INDEX_EXTENSION &&
istate->split_index) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
if (istate->sparse_index)
die(_("cannot write split index for a sparse index"));
@ -3013,95 +3008,65 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
write_index_ext_header(f, eoie_c, CACHE_EXT_LINK,
sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
/*
* NEEDSWORK: write_link_extension() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
if (write_extensions & WRITE_CACHE_TREE_EXTENSION &&
!drop_cache_tree && istate->cache_tree) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
cache_tree_write(&sb, istate->cache_tree);
err = write_index_ext_header(f, eoie_c, CACHE_EXT_TREE, sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
if (write_extensions & WRITE_RESOLVE_UNDO_EXTENSION &&
istate->resolve_undo) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
resolve_undo_write(&sb, istate->resolve_undo);
err = write_index_ext_header(f, eoie_c, CACHE_EXT_RESOLVE_UNDO,
sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
if (write_extensions & WRITE_UNTRACKED_CACHE_EXTENSION &&
istate->untracked) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
write_untracked_extension(&sb, istate->untracked);
err = write_index_ext_header(f, eoie_c, CACHE_EXT_UNTRACKED,
sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
if (write_extensions & WRITE_FSMONITOR_EXTENSION &&
istate->fsmonitor_last_update) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
write_fsmonitor_extension(&sb, istate);
err = write_index_ext_header(f, eoie_c, CACHE_EXT_FSMONITOR, sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
if (istate->sparse_index) {
err = write_index_ext_header(f, eoie_c, CACHE_EXT_SPARSE_DIRECTORIES, 0);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
if (write_index_ext_header(f, eoie_c, CACHE_EXT_SPARSE_DIRECTORIES, 0) < 0) {
ret = -1;
goto out;
}
}
@ -3112,19 +3077,14 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
* when loading the shared index.
*/
if (eoie_c) {
struct strbuf sb = STRBUF_INIT;
strbuf_reset(&sb);
write_eoie_extension(&sb, eoie_c, offset);
err = write_index_ext_header(f, NULL, CACHE_EXT_ENDOFINDEXENTRIES, sb.len) < 0;
hashwrite(f, sb.buf, sb.len);
strbuf_release(&sb);
/*
* NEEDSWORK: write_index_ext_header() never returns a failure,
* and this part may want to be simplified.
*/
if (err) {
err = -1;
goto cleanup;
ret = -1;
goto out;
}
}
@ -3137,12 +3097,12 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
f = NULL;
if (close_tempfile_gently(tempfile)) {
err = error(_("could not close '%s'"), get_tempfile_path(tempfile));
goto cleanup;
ret = error(_("could not close '%s'"), get_tempfile_path(tempfile));
goto out;
}
if (stat(get_tempfile_path(tempfile), &st)) {
err = error_errno(_("could not stat '%s'"), get_tempfile_path(tempfile));
goto cleanup;
ret = -1;
goto out;
}
istate->timestamp.sec = (unsigned int)st.st_mtime;
istate->timestamp.nsec = ST_MTIME_NSEC(st);
@ -3157,12 +3117,14 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
trace2_data_intmax("index", the_repository, "write/cache_nr",
istate->cache_nr);
return 0;
ret = 0;
cleanup:
out:
if (f)
discard_hashfile(f);
return err;
free_hashfile(f);
strbuf_release(&sb);
free(ieot);
return ret;
}
void set_alternate_index_output(const char *name)

View File

@ -499,6 +499,7 @@ static void alias_all_urls(struct remote_state *remote_state)
if (alias)
strvec_replace(&remote_state->remotes[i]->pushurl,
j, alias);
free(alias);
}
add_pushurl_aliases = remote_state->remotes[i]->pushurl.nr == 0;
for (j = 0; j < remote_state->remotes[i]->url.nr; j++) {
@ -512,6 +513,7 @@ static void alias_all_urls(struct remote_state *remote_state)
if (alias)
strvec_replace(&remote_state->remotes[i]->url,
j, alias);
free(alias);
}
}
}

View File

@ -303,6 +303,7 @@ static int git_sequencer_config(const char *k, const char *v,
}
if (!strcmp(k, "commit.gpgsign")) {
free(opts->gpg_sign);
opts->gpg_sign = git_config_bool(k, v) ? xstrdup("") : NULL;
return 0;
}
@ -5489,8 +5490,10 @@ int sequencer_pick_revisions(struct repository *r,
int i, res;
assert(opts->revs);
if (read_and_refresh_cache(r, opts))
return -1;
if (read_and_refresh_cache(r, opts)) {
res = -1;
goto out;
}
for (i = 0; i < opts->revs->pending.nr; i++) {
struct object_id oid;
@ -5505,11 +5508,14 @@ int sequencer_pick_revisions(struct repository *r,
enum object_type type = oid_object_info(r,
&oid,
NULL);
return error(_("%s: can't cherry-pick a %s"),
name, type_name(type));
res = error(_("%s: can't cherry-pick a %s"),
name, type_name(type));
goto out;
}
} else
return error(_("%s: bad revision"), name);
} else {
res = error(_("%s: bad revision"), name);
goto out;
}
}
/*
@ -5524,14 +5530,23 @@ int sequencer_pick_revisions(struct repository *r,
opts->revs->no_walk &&
!opts->revs->cmdline.rev->flags) {
struct commit *cmit;
if (prepare_revision_walk(opts->revs))
return error(_("revision walk setup failed"));
if (prepare_revision_walk(opts->revs)) {
res = error(_("revision walk setup failed"));
goto out;
}
cmit = get_revision(opts->revs);
if (!cmit)
return error(_("empty commit set passed"));
if (!cmit) {
res = error(_("empty commit set passed"));
goto out;
}
if (get_revision(opts->revs))
BUG("unexpected extra commit from walk");
return single_pick(r, cmit, opts);
res = single_pick(r, cmit, opts);
goto out;
}
/*
@ -5541,16 +5556,30 @@ int sequencer_pick_revisions(struct repository *r,
*/
if (walk_revs_populate_todo(&todo_list, opts) ||
create_seq_dir(r) < 0)
return -1;
if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT))
return error(_("can't revert as initial commit"));
if (save_head(oid_to_hex(&oid)))
return -1;
if (save_opts(opts))
return -1;
create_seq_dir(r) < 0) {
res = -1;
goto out;
}
if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT)) {
res = error(_("can't revert as initial commit"));
goto out;
}
if (save_head(oid_to_hex(&oid))) {
res = -1;
goto out;
}
if (save_opts(opts)) {
res = -1;
goto out;
}
update_abort_safety_file();
res = pick_commits(r, &todo_list, opts);
out:
todo_list_release(&todo_list);
return res;
}

View File

@ -899,27 +899,25 @@ static void traverse_tree_submodules(struct repository *r,
{
struct tree_desc tree;
struct submodule_tree_entry *st_entry;
struct name_entry *name_entry;
struct name_entry name_entry;
char *tree_path = NULL;
name_entry = xmalloc(sizeof(*name_entry));
fill_tree_descriptor(r, &tree, treeish_name);
while (tree_entry(&tree, name_entry)) {
while (tree_entry(&tree, &name_entry)) {
if (prefix)
tree_path =
mkpathdup("%s/%s", prefix, name_entry->path);
mkpathdup("%s/%s", prefix, name_entry.path);
else
tree_path = xstrdup(name_entry->path);
tree_path = xstrdup(name_entry.path);
if (S_ISGITLINK(name_entry->mode) &&
if (S_ISGITLINK(name_entry.mode) &&
is_tree_submodule_active(r, root_tree, tree_path)) {
ALLOC_GROW(out->entries, out->entry_nr + 1,
out->entry_alloc);
st_entry = &out->entries[out->entry_nr++];
st_entry->name_entry = xmalloc(sizeof(*st_entry->name_entry));
*st_entry->name_entry = *name_entry;
*st_entry->name_entry = name_entry;
st_entry->submodule =
submodule_from_path(r, root_tree, tree_path);
st_entry->repo = xmalloc(sizeof(*st_entry->repo));
@ -927,9 +925,9 @@ static void traverse_tree_submodules(struct repository *r,
root_tree))
FREE_AND_NULL(st_entry->repo);
} else if (S_ISDIR(name_entry->mode))
} else if (S_ISDIR(name_entry.mode))
traverse_tree_submodules(r, root_tree, tree_path,
&name_entry->oid, out);
&name_entry.oid, out);
free(tree_path);
}
}

View File

@ -2,7 +2,7 @@
test_description='test trace2 facility (normal target)'
TEST_PASSES_SANITIZE_LEAK=false
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Turn off any inherited trace2 settings for this test.

View File

@ -2,6 +2,7 @@
test_description='git cat-file'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_cmdmode_usage () {

View File

@ -3,6 +3,7 @@
test_description='adding and checking out large blobs'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'core.bigFileThreshold must be non-negative' '

View File

@ -6,6 +6,7 @@ test_description='git fsck random collection of tests
* (main) A
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='test handling of bogus index entries'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create tree with null sha1' '

View File

@ -5,6 +5,7 @@
test_description='Test notes merging with manual conflict resolution'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Set up a notes merge scenario with different kinds of conflicts

View File

@ -5,6 +5,7 @@
test_description='Test notes merging at various fanout levels'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
verify_notes () {

View File

@ -26,6 +26,7 @@ Initial setup:
touch file "conflict".
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh

View File

@ -8,6 +8,7 @@ test_description='test rebase --[no-]gpg-sign'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-rebase.sh"
. "$TEST_DIRECTORY/lib-gpg.sh"

View File

@ -13,6 +13,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pristine_detach () {

View File

@ -12,6 +12,7 @@ test_description='Test cherry-pick continuation features
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Repeat first match 10 times

View File

@ -2,6 +2,7 @@
test_description='git add in sparse checked out working trees'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
SPARSE_ENTRY_BLOB=""

View File

@ -8,6 +8,7 @@ test_description='Various diff formatting options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh

View File

@ -8,6 +8,7 @@ test_description='various format-patch tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh

View File

@ -5,6 +5,7 @@
test_description='Test custom diff function name patterns'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff.*.textconv tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
find_diff() {

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='test textconv caching'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >helper <<'EOF'

View File

@ -4,6 +4,7 @@ test_description='combined and merge diff handle binary files and textconv'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup binary merge conflict' '

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='test finding specific blobs in the revision walking'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup ' '

View File

@ -2,6 +2,7 @@
test_description='anchored diff algorithm'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success '--anchored' '

View File

@ -5,6 +5,7 @@ test_description='behavior of diff with symmetric-diff setups and --merge-base'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# build these situations:

View File

@ -2,6 +2,7 @@
test_description='remerge-diff handling'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This test is ort-specific

View File

@ -5,6 +5,7 @@ test_description='git apply --3way'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
print_sanitized_conflicted_diff () {

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='log --grep/--author/--regexp-ignore-case/-S/-G'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_log () {

View File

@ -26,6 +26,7 @@ test_description="limiting blob downloads when merging with partial clones"
# underscore notation is to differentiate different
# files that might be renamed into each other's paths.)
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh

View File

@ -22,6 +22,7 @@ test_description="merge cases"
# underscore notation is to differentiate different
# files that might be renamed into each other's paths.)
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh

View File

@ -2,6 +2,7 @@
test_description='filter-branch removal of trees with null sha1'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: base commits' '

View File

@ -4,6 +4,7 @@ test_description='signed tag tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"

View File

@ -33,6 +33,7 @@ should leave the following structure in the working tree:
But note that sub2 should have the SKIP_WORKTREE bit set.
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View File

@ -7,6 +7,7 @@ test_description='test git fast-import utility'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='test exotic situations with marks'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup dump of basic history' '

View File

@ -4,6 +4,7 @@ test_description='basic tests for fast-export --anonymize'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup simple repo' '

View File

@ -210,6 +210,7 @@ void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
{
strvec_clear(&opts->internal.msgs_to_free);
memset(opts->internal.msgs, 0, sizeof(opts->internal.msgs));
discard_index(&opts->internal.result);
}
static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
@ -2082,6 +2083,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
o->internal.result.updated_workdir = 1;
discard_index(o->dst_index);
*o->dst_index = o->internal.result;
memset(&o->internal.result, 0, sizeof(o->internal.result));
} else {
discard_index(&o->internal.result);
}

View File

@ -399,8 +399,11 @@ static struct userdiff_driver *userdiff_find_by_namelen(const char *name, size_t
static int parse_funcname(struct userdiff_funcname *f, const char *k,
const char *v, int cflags)
{
if (git_config_string((char **) &f->pattern, k, v) < 0)
f->pattern = NULL;
FREE_AND_NULL(f->pattern_owned);
if (git_config_string(&f->pattern_owned, k, v) < 0)
return -1;
f->pattern = f->pattern_owned;
f->cflags = cflags;
return 0;
}
@ -444,20 +447,37 @@ int userdiff_config(const char *k, const char *v)
return parse_funcname(&drv->funcname, k, v, REG_EXTENDED);
if (!strcmp(type, "binary"))
return parse_tristate(&drv->binary, k, v);
if (!strcmp(type, "command"))
return git_config_string((char **) &drv->external.cmd, k, v);
if (!strcmp(type, "command")) {
FREE_AND_NULL(drv->external.cmd);
return git_config_string(&drv->external.cmd, k, v);
}
if (!strcmp(type, "trustexitcode")) {
drv->external.trust_exit_code = git_config_bool(k, v);
return 0;
}
if (!strcmp(type, "textconv"))
return git_config_string((char **) &drv->textconv, k, v);
if (!strcmp(type, "textconv")) {
int ret;
FREE_AND_NULL(drv->textconv_owned);
ret = git_config_string(&drv->textconv_owned, k, v);
drv->textconv = drv->textconv_owned;
return ret;
}
if (!strcmp(type, "cachetextconv"))
return parse_bool(&drv->textconv_want_cache, k, v);
if (!strcmp(type, "wordregex"))
return git_config_string((char **) &drv->word_regex, k, v);
if (!strcmp(type, "algorithm"))
return git_config_string((char **) &drv->algorithm, k, v);
if (!strcmp(type, "wordregex")) {
int ret;
FREE_AND_NULL(drv->word_regex_owned);
ret = git_config_string(&drv->word_regex_owned, k, v);
drv->word_regex = drv->word_regex_owned;
return ret;
}
if (!strcmp(type, "algorithm")) {
int ret;
FREE_AND_NULL(drv->algorithm_owned);
ret = git_config_string(&drv->algorithm_owned, k, v);
drv->algorithm = drv->algorithm_owned;
return ret;
}
return 0;
}

View File

@ -8,6 +8,7 @@ struct repository;
struct userdiff_funcname {
const char *pattern;
char *pattern_owned;
int cflags;
};
@ -20,11 +21,14 @@ struct userdiff_driver {
const char *name;
struct external_diff external;
const char *algorithm;
char *algorithm_owned;
int binary;
struct userdiff_funcname funcname;
const char *word_regex;
char *word_regex_owned;
const char *word_regex_multi_byte;
const char *textconv;
char *textconv_owned;
struct notes_cache *textconv_cache;
int textconv_want_cache;
};