summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2024-08-23 18:02:33 +0200
committerJunio C Hamano <gitster@pobox.com>2024-08-23 18:02:33 +0200
commit1b6b2bfae582e1e5a9b9ad2ef15985f69ade0fce (patch)
treee92ce38ee06174dcff67406f37a9a5f2c6566053
parentThe seventh batch (diff)
parentbuiltin/diff: free symmetric diff members (diff)
downloadgit-1b6b2bfae582e1e5a9b9ad2ef15985f69ade0fce.tar.xz
git-1b6b2bfae582e1e5a9b9ad2ef15985f69ade0fce.zip
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 ...
-rw-r--r--builtin/commit.c7
-rw-r--r--builtin/diff.c6
-rw-r--r--builtin/fast-export.c19
-rw-r--r--builtin/fast-import.c8
-rw-r--r--builtin/log.c14
-rw-r--r--builtin/notes.c9
-rw-r--r--builtin/rebase.c1
-rw-r--r--bulk-checkin.c2
-rw-r--r--config.c3
-rw-r--r--csum-file.c2
-rw-r--r--csum-file.h10
-rw-r--r--diff.c16
-rw-r--r--environment.c1
-rw-r--r--environment.h1
-rw-r--r--git.c13
-rw-r--r--merge-ort.c3
-rw-r--r--object-file.c1
-rw-r--r--object-name.c1
-rw-r--r--range-diff.c6
-rw-r--r--read-cache.c114
-rw-r--r--remote.c2
-rw-r--r--sequencer.c67
-rw-r--r--submodule-config.c18
-rwxr-xr-xt/t0210-trace2-normal.sh2
-rwxr-xr-xt/t1006-cat-file.sh1
-rwxr-xr-xt/t1050-large.sh1
-rwxr-xr-xt/t1450-fsck.sh1
-rwxr-xr-xt/t1601-index-bogus.sh2
-rwxr-xr-xt/t3310-notes-merge-manual-resolve.sh1
-rwxr-xr-xt/t3311-notes-merge-fanout.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh1
-rwxr-xr-xt/t3435-rebase-gpg-sign.sh1
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh1
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh1
-rwxr-xr-xt/t3705-add-sparse-checkout.sh1
-rwxr-xr-xt/t4013-diff-various.sh1
-rwxr-xr-xt/t4014-format-patch.sh1
-rwxr-xr-xt/t4018-diff-funcname.sh1
-rwxr-xr-xt/t4030-diff-textconv.sh2
-rwxr-xr-xt/t4042-diff-textconv-caching.sh2
-rwxr-xr-xt/t4048-diff-combined-binary.sh1
-rwxr-xr-xt/t4064-diff-oidfind.sh2
-rwxr-xr-xt/t4065-diff-anchored.sh1
-rwxr-xr-xt/t4068-diff-symmetric-merge-base.sh1
-rwxr-xr-xt/t4069-remerge-diff.sh1
-rwxr-xr-xt/t4108-apply-threeway.sh1
-rwxr-xr-xt/t4209-log-pickaxe.sh2
-rwxr-xr-xt/t6421-merge-partial-clone.sh1
-rwxr-xr-xt/t6428-merge-conflicts-sparse.sh1
-rwxr-xr-xt/t7008-filter-branch-null-sha1.sh1
-rwxr-xr-xt/t7030-verify-tag.sh1
-rwxr-xr-xt/t7817-grep-sparse-checkout.sh1
-rwxr-xr-xt/t9300-fast-import.sh1
-rwxr-xr-xt/t9304-fast-import-marks.sh2
-rwxr-xr-xt/t9351-fast-export-anonymize.sh1
-rw-r--r--unpack-trees.c2
-rw-r--r--userdiff.c38
-rw-r--r--userdiff.h4
58 files changed, 265 insertions, 142 deletions
diff --git a/builtin/commit.c b/builtin/commit.c
index 66427ba82d..b2033c4887 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -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,
diff --git a/builtin/diff.c b/builtin/diff.c
index 9b6cdabe15..6eac445579 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -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;
}
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 4b6e8c6832..f253b79322 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -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);
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index d21c4053a7..6dfeb01665 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -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)
diff --git a/builtin/log.c b/builtin/log.c
index a73a767606..36769bab3b 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -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;
diff --git a/builtin/notes.c b/builtin/notes.c
index 4cc5bfedc3..5af2068075 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -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);
diff --git a/builtin/rebase.c b/builtin/rebase.c
index e3a8e74cfc..2f01d5d3a6 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -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)
diff --git a/bulk-checkin.c b/bulk-checkin.c
index da8673199b..9089c214fa 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -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));
diff --git a/config.c b/config.c
index 05f369ec0d..0cf847266e 100644
--- a/config.c
+++ b/config.c
@@ -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);
diff --git a/csum-file.c b/csum-file.c
index 2131ee6b12..bf82ad8f9f 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -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);
diff --git a/csum-file.h b/csum-file.h
index 36c7c5585f..7c73da0a40 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -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);
diff --git a/diff.c b/diff.c
index ebb7538e04..4035a9374d 100644
--- a/diff.c
+++ b/diff.c
@@ -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);
diff --git a/environment.c b/environment.c
index 5cea2c9f54..1d6c48b52d 100644
--- a/environment.c
+++ b/environment.c
@@ -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? */
diff --git a/environment.h b/environment.h
index e9f01d4d11..0148738ed6 100644
--- a/environment.h
+++ b/environment.h
@@ -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;
/*
diff --git a/git.c b/git.c
index e35af9b0e5..9a618a2740 100644
--- a/git.c
+++ b/git.c
@@ -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")) {
diff --git a/merge-ort.c b/merge-ort.c
index e9d01ac7f7..3752c7e595 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -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) {
diff --git a/object-file.c b/object-file.c
index 05ac6ebed6..c5994202ba 100644
--- a/object-file.c
+++ b/object-file.c
@@ -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;
}
diff --git a/object-name.c b/object-name.c
index f340b740c5..09c1bd93a3 100644
--- a/object-name.c
+++ b/object-name.c
@@ -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);
}
/*
diff --git a/range-diff.c b/range-diff.c
index 5f01605550..bbb0952264 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -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)
diff --git a/read-cache.c b/read-cache.c
index 1f67bb755b..36821fe5b5 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -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)
diff --git a/remote.c b/remote.c
index 4a1269a47a..7d5b8f750d 100644
--- a/remote.c
+++ b/remote.c
@@ -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);
}
}
}
diff --git a/sequencer.c b/sequencer.c
index 0291920f0b..ea559c31f1 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -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;
}
diff --git a/submodule-config.c b/submodule-config.c
index 9b0bb0b9f4..c8f2bb2bdd 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -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);
}
}
diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh
index c312657a12..b9adc94aab 100755
--- a/t/t0210-trace2-normal.sh
+++ b/t/t0210-trace2-normal.sh
@@ -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.
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index ff9bf213aa..d36cd7c086 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -2,6 +2,7 @@
test_description='git cat-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_cmdmode_usage () {
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index c71932b024..ed638f6644 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -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' '
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 8a456b1142..280cbf3e03 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -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 '
diff --git a/t/t1601-index-bogus.sh b/t/t1601-index-bogus.sh
index 4171f1e141..5dcc101882 100755
--- a/t/t1601-index-bogus.sh
+++ b/t/t1601-index-bogus.sh
@@ -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' '
diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh
index 597df5ebc0..04866b89be 100755
--- a/t/t3310-notes-merge-manual-resolve.sh
+++ b/t/t3310-notes-merge-manual-resolve.sh
@@ -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
diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh
index 5b675417e9..ce4144db0f 100755
--- a/t/t3311-notes-merge-fanout.sh
+++ b/t/t3311-notes-merge-fanout.sh
@@ -5,6 +5,7 @@
test_description='Test notes merging at various fanout levels'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
verify_notes () {
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index f92baad138..f171af3061 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -26,6 +26,7 @@ Initial setup:
touch file "conflict".
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3435-rebase-gpg-sign.sh b/t/t3435-rebase-gpg-sign.sh
index 6aa2aeb628..6e329fea7c 100755
--- a/t/t3435-rebase-gpg-sign.sh
+++ b/t/t3435-rebase-gpg-sign.sh
@@ -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"
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index f3947b400a..10e9c91dbb 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -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 () {
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 7eb52b12ed..93c725bac3 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -12,6 +12,7 @@ test_description='Test cherry-pick continuation features
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Repeat first match 10 times
diff --git a/t/t3705-add-sparse-checkout.sh b/t/t3705-add-sparse-checkout.sh
index 2bade9e804..6ae45a788d 100755
--- a/t/t3705-add-sparse-checkout.sh
+++ b/t/t3705-add-sparse-checkout.sh
@@ -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=""
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 3855d68dbc..87d248d034 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -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
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 884f83fb8a..1c46e963e4 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -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
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index e026fac1f4..8128c30e7f 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -5,6 +5,7 @@
test_description='Test custom diff function name patterns'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
index a39a626664..29f6d610c2 100755
--- a/t/t4030-diff-textconv.sh
+++ b/t/t4030-diff-textconv.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff.*.textconv tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
find_diff() {
diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh
index 8ebfa3c1be..a179205394 100755
--- a/t/t4042-diff-textconv-caching.sh
+++ b/t/t4042-diff-textconv-caching.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test textconv caching'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >helper <<'EOF'
diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh
index 0260cf64f5..f399484bce 100755
--- a/t/t4048-diff-combined-binary.sh
+++ b/t/t4048-diff-combined-binary.sh
@@ -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' '
diff --git a/t/t4064-diff-oidfind.sh b/t/t4064-diff-oidfind.sh
index 6d8c8986fc..846f285f77 100755
--- a/t/t4064-diff-oidfind.sh
+++ b/t/t4064-diff-oidfind.sh
@@ -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 ' '
diff --git a/t/t4065-diff-anchored.sh b/t/t4065-diff-anchored.sh
index b3f510f040..647537c12e 100755
--- a/t/t4065-diff-anchored.sh
+++ b/t/t4065-diff-anchored.sh
@@ -2,6 +2,7 @@
test_description='anchored diff algorithm'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success '--anchored' '
diff --git a/t/t4068-diff-symmetric-merge-base.sh b/t/t4068-diff-symmetric-merge-base.sh
index eff63c16b0..4d6565e728 100755
--- a/t/t4068-diff-symmetric-merge-base.sh
+++ b/t/t4068-diff-symmetric-merge-base.sh
@@ -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:
diff --git a/t/t4069-remerge-diff.sh b/t/t4069-remerge-diff.sh
index ca8f999cab..df342850a0 100755
--- a/t/t4069-remerge-diff.sh
+++ b/t/t4069-remerge-diff.sh
@@ -2,6 +2,7 @@
test_description='remerge-diff handling'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This test is ort-specific
diff --git a/t/t4108-apply-threeway.sh b/t/t4108-apply-threeway.sh
index c558282bc0..3211e1e65f 100755
--- a/t/t4108-apply-threeway.sh
+++ b/t/t4108-apply-threeway.sh
@@ -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 () {
diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh
index 64e1623733..b42fdc54fc 100755
--- a/t/t4209-log-pickaxe.sh
+++ b/t/t4209-log-pickaxe.sh
@@ -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 () {
diff --git a/t/t6421-merge-partial-clone.sh b/t/t6421-merge-partial-clone.sh
index b99f29ef9b..30349a466e 100755
--- a/t/t6421-merge-partial-clone.sh
+++ b/t/t6421-merge-partial-clone.sh
@@ -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
diff --git a/t/t6428-merge-conflicts-sparse.sh b/t/t6428-merge-conflicts-sparse.sh
index 9919c3fa7c..8a79bc2e92 100755
--- a/t/t6428-merge-conflicts-sparse.sh
+++ b/t/t6428-merge-conflicts-sparse.sh
@@ -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
diff --git a/t/t7008-filter-branch-null-sha1.sh b/t/t7008-filter-branch-null-sha1.sh
index 93fbc92b8d..0ce8fd2c89 100755
--- a/t/t7008-filter-branch-null-sha1.sh
+++ b/t/t7008-filter-branch-null-sha1.sh
@@ -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' '
diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh
index 6f526c37c2..effa826744 100755
--- a/t/t7030-verify-tag.sh
+++ b/t/t7030-verify-tag.sh
@@ -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"
diff --git a/t/t7817-grep-sparse-checkout.sh b/t/t7817-grep-sparse-checkout.sh
index eb59564565..0ba7817fb7 100755
--- a/t/t7817-grep-sparse-checkout.sh
+++ b/t/t7817-grep-sparse-checkout.sh
@@ -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' '
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 1e68426852..3b3c371740 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -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
diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh
index 410a871c52..1f776a80f3 100755
--- a/t/t9304-fast-import-marks.sh
+++ b/t/t9304-fast-import-marks.sh
@@ -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' '
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 156a647484..c0d9d7be75 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -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' '
diff --git a/unpack-trees.c b/unpack-trees.c
index 7dc884fafd..9a55cb6204 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -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);
}
diff --git a/userdiff.c b/userdiff.c
index c4ebb9ff73..989629149f 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -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;
}
diff --git a/userdiff.h b/userdiff.h
index 7565930337..827361b0bc 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -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;
};