aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2024-09-20 11:16:30 -0700
committerJunio C Hamano <gitster@pobox.com>2024-09-20 11:16:30 -0700
commit16c0906e8cd9b32b95dfe68058bcdaad3e4458e4 (patch)
tree5eb2fce820151a347514e6a60c9162c10184256e
parent2b800ec45e53051c41a85900009430704bfdf031 (diff)
parent46f6ca2a68e02dd68132ed0b64cd55a8b6569e29 (diff)
downloadgit-16c0906e8cd9b32b95dfe68058bcdaad3e4458e4.tar.gz
Merge branch 'ps/leakfixes-part-6'
More leakfixes. * ps/leakfixes-part-6: (22 commits) builtin/repack: fix leaking keep-pack list merge-ort: fix two leaks when handling directory rename modifications match-trees: fix leaking prefixes in `shift_tree()` builtin/fmt-merge-msg: fix leaking buffers builtin/grep: fix leaking object context builtin/pack-objects: plug leaking list of keep-packs builtin/repack: fix leaking line buffer when packing promisors negotiator/skipping: fix leaking commit entries shallow: fix leaking members of `struct shallow_info` shallow: free grafts when unregistering them object: clear grafts when clearing parsed object pool gpg-interface: fix misdesigned signing key interfaces send-pack: fix leaking push cert nonce remote: fix leak in reachability check of a remote-tracking ref remote: fix leaking tracking refs builtin/submodule--helper: fix leaking refs on push-check submodule: fix leaking fetch task data upload-pack: fix leaking child process data on reachability checks builtin/push: fix leaking refspec query result send-pack: fix leaking common object IDs ...
-rw-r--r--builtin/fmt-merge-msg.c2
-rw-r--r--builtin/grep.c1
-rw-r--r--builtin/pack-objects.c1
-rw-r--r--builtin/push.c8
-rw-r--r--builtin/repack.c3
-rw-r--r--builtin/submodule--helper.c2
-rw-r--r--builtin/tag.c3
-rw-r--r--commit.c23
-rw-r--r--commit.h3
-rw-r--r--fetch-pack.c3
-rw-r--r--gpg-interface.c26
-rw-r--r--gpg-interface.h4
-rw-r--r--match-trees.c10
-rw-r--r--merge-ort.c4
-rw-r--r--negotiator/skipping.c7
-rw-r--r--object.c14
-rw-r--r--object.h4
-rw-r--r--remote.c6
-rw-r--r--repository.c2
-rw-r--r--send-pack.c52
-rw-r--r--shallow.c15
-rw-r--r--submodule.c2
-rw-r--r--t/README3
-rwxr-xr-xt/t5516-fetch-push.sh1
-rwxr-xr-xt/t5526-fetch-submodules.sh1
-rwxr-xr-xt/t5531-deep-submodule-push.sh1
-rwxr-xr-xt/t5533-push-cas.sh1
-rwxr-xr-xt/t5534-push-signed.sh1
-rwxr-xr-xt/t5537-fetch-shallow.sh1
-rwxr-xr-xt/t5538-push-shallow.sh1
-rwxr-xr-xt/t5549-fetch-push-http.sh1
-rwxr-xr-xt/t5552-skipping-fetch-negotiator.sh2
-rwxr-xr-xt/t5616-partial-clone.sh1
-rwxr-xr-xt/t6132-pathspec-exclude.sh1
-rwxr-xr-xt/t6135-pathspec-with-attrs.sh2
-rwxr-xr-xt/t6200-fmt-merge-msg.sh1
-rwxr-xr-xt/t6409-merge-subtree.sh1
-rwxr-xr-xt/t6423-merge-rename-directories.sh1
-rwxr-xr-xt/t6500-gc.sh1
-rwxr-xr-xt/t7703-repack-geometric.sh1
-rw-r--r--t/test-lib.sh11
-rw-r--r--upload-pack.c22
42 files changed, 178 insertions, 72 deletions
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 957786d1b3..0b162f8fab 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -67,6 +67,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
return ret;
write_in_full(STDOUT_FILENO, output.buf, output.len);
+ strbuf_release(&input);
+ strbuf_release(&output);
free(inpath);
return 0;
}
diff --git a/builtin/grep.c b/builtin/grep.c
index dfc3c3e8bd..dda4582d64 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1133,6 +1133,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
&oid, &oc)) {
if (seen_dashdash)
die(_("unable to resolve revision: %s"), arg);
+ object_context_release(&oc);
break;
}
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index c6e2852d3c..01479a9ccc 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -4669,6 +4669,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
cleanup:
clear_packing_data(&to_pack);
list_objects_filter_release(&filter_options);
+ string_list_clear(&keep_pack_list, 0);
strvec_clear(&rp);
return 0;
diff --git a/builtin/push.c b/builtin/push.c
index 7a67398124..0b123eb9c1 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -72,13 +72,15 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref,
const char *branch_name;
if (remote->push.nr) {
- struct refspec_item query;
- memset(&query, 0, sizeof(struct refspec_item));
- query.src = matched->name;
+ struct refspec_item query = {
+ .src = matched->name,
+ };
+
if (!query_refspecs(&remote->push, &query) && query.dst) {
refspec_appendf(refspec, "%s%s:%s",
query.force ? "+" : "",
query.src, query.dst);
+ free(query.dst);
return;
}
}
diff --git a/builtin/repack.c b/builtin/repack.c
index 8bb875532b..3ee8cfa732 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -425,9 +425,11 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
free(promisor_name);
}
+
fclose(out);
if (finish_command(&cmd))
die(_("could not finish pack-objects to repack promisor objects"));
+ strbuf_release(&line);
}
struct pack_geometry {
@@ -1541,6 +1543,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
}
cleanup:
+ string_list_clear(&keep_pack_list, 0);
string_list_clear(&names, 1);
existing_packs_release(&existing);
free_pack_geometry(&geometry);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3e0b6c45c0..e5ba05ab8c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2958,7 +2958,9 @@ static int push_check(int argc, const char **argv, const char *prefix UNUSED)
rs->src);
}
}
+
refspec_clear(&refspec);
+ free_refs(local_refs);
}
free(head);
diff --git a/builtin/tag.c b/builtin/tag.c
index 607e48e311..59829aa26d 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -160,7 +160,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
const struct git_hash_algo *compat = the_repository->compat_hash_algo;
struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT;
struct strbuf compat_buf = STRBUF_INIT;
- const char *keyid = get_signing_key();
+ char *keyid = get_signing_key();
int ret = -1;
if (sign_buffer(buffer, &sig, keyid))
@@ -190,6 +190,7 @@ out:
strbuf_release(&sig);
strbuf_release(&compat_sig);
strbuf_release(&compat_buf);
+ free(keyid);
return ret;
}
diff --git a/commit.c b/commit.c
index 3238772f52..34cac0e302 100644
--- a/commit.c
+++ b/commit.c
@@ -183,7 +183,7 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid)
commit_graft_oid_access);
}
-static void unparse_commit(struct repository *r, const struct object_id *oid)
+void unparse_commit(struct repository *r, const struct object_id *oid)
{
struct commit *c = lookup_commit(r, oid);
@@ -324,18 +324,6 @@ int for_each_commit_graft(each_commit_graft_fn fn, void *cb_data)
return ret;
}
-void reset_commit_grafts(struct repository *r)
-{
- int i;
-
- for (i = 0; i < r->parsed_objects->grafts_nr; i++) {
- unparse_commit(r, &r->parsed_objects->grafts[i]->oid);
- free(r->parsed_objects->grafts[i]);
- }
- r->parsed_objects->grafts_nr = 0;
- r->parsed_objects->commit_graft_prepared = 0;
-}
-
struct commit_buffer {
void *buffer;
unsigned long size;
@@ -1156,11 +1144,14 @@ int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct gi
static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid)
{
+ char *keyid_to_free = NULL;
+ int ret = 0;
if (!keyid || !*keyid)
- keyid = get_signing_key();
+ keyid = keyid_to_free = get_signing_key();
if (sign_buffer(buf, sig, keyid))
- return -1;
- return 0;
+ ret = -1;
+ free(keyid_to_free);
+ return ret;
}
int parse_signed_commit(const struct commit *commit,
diff --git a/commit.h b/commit.h
index 0e5fce543c..13098422c5 100644
--- a/commit.h
+++ b/commit.h
@@ -110,6 +110,8 @@ static inline int repo_parse_commit_no_graph(struct repository *r,
void parse_commit_or_die(struct commit *item);
+void unparse_commit(struct repository *r, const struct object_id *oid);
+
struct buffer_slab;
struct buffer_slab *allocate_commit_buffer_slab(void);
void free_commit_buffer_slab(struct buffer_slab *bs);
@@ -242,7 +244,6 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid);
int register_commit_graft(struct repository *r, struct commit_graft *, int);
void prepare_commit_graft(struct repository *r);
struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid);
-void reset_commit_grafts(struct repository *r);
struct commit *get_fork_point(const char *refname, struct commit *commit);
diff --git a/fetch-pack.c b/fetch-pack.c
index 983c560785..2c76bcad40 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -2227,7 +2227,10 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
trace2_region_leave("fetch-pack", "negotiate_using_fetch", the_repository);
trace2_data_intmax("negotiate_using_fetch", the_repository,
"total_rounds", negotiation_round);
+
clear_common_flag(acked_commits);
+ object_array_clear(&nt_object_array);
+ negotiator.release(&negotiator);
strbuf_release(&req_buf);
}
diff --git a/gpg-interface.c b/gpg-interface.c
index 6587085cd1..cf6126b5aa 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -45,8 +45,8 @@ struct gpg_format {
size_t signature_size);
int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key);
- const char *(*get_default_key)(void);
- const char *(*get_key_id)(void);
+ char *(*get_default_key)(void);
+ char *(*get_key_id)(void);
};
static const char *openpgp_verify_args[] = {
@@ -86,9 +86,9 @@ static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key);
-static const char *get_default_ssh_signing_key(void);
+static char *get_default_ssh_signing_key(void);
-static const char *get_ssh_key_id(void);
+static char *get_ssh_key_id(void);
static struct gpg_format gpg_format[] = {
{
@@ -847,7 +847,7 @@ static char *get_ssh_key_fingerprint(const char *signing_key)
}
/* Returns the first public key from an ssh-agent to use for signing */
-static const char *get_default_ssh_signing_key(void)
+static char *get_default_ssh_signing_key(void)
{
struct child_process ssh_default_key = CHILD_PROCESS_INIT;
int ret = -1;
@@ -899,12 +899,16 @@ static const char *get_default_ssh_signing_key(void)
return default_key;
}
-static const char *get_ssh_key_id(void) {
- return get_ssh_key_fingerprint(get_signing_key());
+static char *get_ssh_key_id(void)
+{
+ char *signing_key = get_signing_key();
+ char *key_id = get_ssh_key_fingerprint(signing_key);
+ free(signing_key);
+ return key_id;
}
/* Returns a textual but unique representation of the signing key */
-const char *get_signing_key_id(void)
+char *get_signing_key_id(void)
{
gpg_interface_lazy_init();
@@ -916,17 +920,17 @@ const char *get_signing_key_id(void)
return get_signing_key();
}
-const char *get_signing_key(void)
+char *get_signing_key(void)
{
gpg_interface_lazy_init();
if (configured_signing_key)
- return configured_signing_key;
+ return xstrdup(configured_signing_key);
if (use_format->get_default_key) {
return use_format->get_default_key();
}
- return git_committer_info(IDENT_STRICT | IDENT_NO_DATE);
+ return xstrdup(git_committer_info(IDENT_STRICT | IDENT_NO_DATE));
}
const char *gpg_trust_level_to_str(enum signature_trust_level level)
diff --git a/gpg-interface.h b/gpg-interface.h
index 7cd98161f7..e09f12e8d0 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -80,13 +80,13 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
const char *gpg_trust_level_to_str(enum signature_trust_level level);
void set_signing_key(const char *);
-const char *get_signing_key(void);
+char *get_signing_key(void);
/*
* Returns a textual unique representation of the signing key in use
* Either a GPG KeyID or a SSH Key Fingerprint
*/
-const char *get_signing_key_id(void);
+char *get_signing_key_id(void);
int check_signature(struct signature_check *sigc,
const char *signature, size_t slen);
void print_signature_buffer(const struct signature_check *sigc,
diff --git a/match-trees.c b/match-trees.c
index f17c74d483..147b03abf1 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -294,18 +294,22 @@ void shift_tree(struct repository *r,
unsigned short mode;
if (!*del_prefix)
- return;
+ goto out;
if (get_tree_entry(r, hash2, del_prefix, shifted, &mode))
die("cannot find path %s in tree %s",
del_prefix, oid_to_hex(hash2));
- return;
+ goto out;
}
if (!*add_prefix)
- return;
+ goto out;
splice_tree(hash1, add_prefix, hash2, shifted);
+
+out:
+ free(add_prefix);
+ free(del_prefix);
}
/*
diff --git a/merge-ort.c b/merge-ort.c
index 3752c7e595..0ed3cd06b1 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -2710,7 +2710,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
struct conflict_info *dir_ci;
char *cur_dir = dirs_to_insert.items[i].string;
- CALLOC_ARRAY(dir_ci, 1);
+ dir_ci = mem_pool_calloc(&opt->priv->pool, 1, sizeof(*dir_ci));
dir_ci->merged.directory_name = parent_name;
len = strlen(parent_name);
@@ -2838,6 +2838,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
* Finally, record the new location.
*/
pair->two->path = new_path;
+
+ string_list_clear(&dirs_to_insert, 0);
}
/*** Function Grouping: functions related to regular rename detection ***/
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index 6e61b3c5f1..abedb70a48 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -247,8 +247,11 @@ static int ack(struct fetch_negotiator *n, struct commit *c)
static void release(struct fetch_negotiator *n)
{
- clear_prio_queue(&((struct data *)n->data)->rev_list);
- FREE_AND_NULL(n->data);
+ struct data *data = n->data;
+ for (int i = 0; i < data->rev_list.nr; i++)
+ free(data->rev_list.array[i].data);
+ clear_prio_queue(&data->rev_list);
+ FREE_AND_NULL(data);
}
void skipping_negotiator_init(struct fetch_negotiator *negotiator)
diff --git a/object.c b/object.c
index d756c7f2ea..94ea8fb8d2 100644
--- a/object.c
+++ b/object.c
@@ -545,11 +545,12 @@ void repo_clear_commit_marks(struct repository *r, unsigned int flags)
}
}
-struct parsed_object_pool *parsed_object_pool_new(void)
+struct parsed_object_pool *parsed_object_pool_new(struct repository *repo)
{
struct parsed_object_pool *o = xmalloc(sizeof(*o));
memset(o, 0, sizeof(*o));
+ o->repo = repo;
o->blob_state = allocate_alloc_state();
o->tree_state = allocate_alloc_state();
o->commit_state = allocate_alloc_state();
@@ -628,6 +629,16 @@ void raw_object_store_clear(struct raw_object_store *o)
hashmap_clear(&o->pack_map);
}
+void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o)
+{
+ for (int i = 0; i < o->grafts_nr; i++) {
+ unparse_commit(o->repo, &o->grafts[i]->oid);
+ free(o->grafts[i]);
+ }
+ o->grafts_nr = 0;
+ o->commit_graft_prepared = 0;
+}
+
void parsed_object_pool_clear(struct parsed_object_pool *o)
{
/*
@@ -659,6 +670,7 @@ void parsed_object_pool_clear(struct parsed_object_pool *o)
free_commit_buffer_slab(o->buffer_slab);
o->buffer_slab = NULL;
+ parsed_object_pool_reset_commit_grafts(o);
clear_alloc_state(o->blob_state);
clear_alloc_state(o->tree_state);
clear_alloc_state(o->commit_state);
diff --git a/object.h b/object.h
index 05691486eb..17f32f1103 100644
--- a/object.h
+++ b/object.h
@@ -7,6 +7,7 @@ struct buffer_slab;
struct repository;
struct parsed_object_pool {
+ struct repository *repo;
struct object **obj_hash;
int nr_objs, obj_hash_size;
@@ -31,8 +32,9 @@ struct parsed_object_pool {
struct buffer_slab *buffer_slab;
};
-struct parsed_object_pool *parsed_object_pool_new(void);
+struct parsed_object_pool *parsed_object_pool_new(struct repository *repo);
void parsed_object_pool_clear(struct parsed_object_pool *o);
+void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o);
struct object_list {
struct object *item;
diff --git a/remote.c b/remote.c
index 539e5ceae3..390a03c264 100644
--- a/remote.c
+++ b/remote.c
@@ -1123,6 +1123,7 @@ void free_one_ref(struct ref *ref)
return;
free_one_ref(ref->peer_ref);
free(ref->remote_status);
+ free(ref->tracking_ref);
free(ref->symref);
free(ref);
}
@@ -2620,8 +2621,10 @@ static int remote_tracking(struct remote *remote, const char *refname,
dst = apply_refspecs(&remote->fetch, refname);
if (!dst)
return -1; /* no tracking ref for refname at remote */
- if (refs_read_ref(get_main_ref_store(the_repository), dst, oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), dst, oid)) {
+ free(dst);
return -1; /* we know what the tracking ref is but we cannot read it */
+ }
*dst_refname = dst;
return 0;
@@ -2771,6 +2774,7 @@ static void check_if_includes_upstream(struct ref *remote)
if (is_reachable_in_reflog(local->name, remote) <= 0)
remote->unreachable = 1;
+ free_one_ref(local);
}
static void apply_cas(struct push_cas_option *cas,
diff --git a/repository.c b/repository.c
index 9825a30899..e6fc2c6aa9 100644
--- a/repository.c
+++ b/repository.c
@@ -54,7 +54,7 @@ void initialize_repository(struct repository *repo)
{
repo->objects = raw_object_store_new();
repo->remote_state = remote_state_new();
- repo->parsed_objects = parsed_object_pool_new();
+ repo->parsed_objects = parsed_object_pool_new(repo);
ALLOC_ARRAY(repo->index, 1);
index_state_init(repo->index, repo);
diff --git a/send-pack.c b/send-pack.c
index 5d0c23772a..6677c44e8a 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -353,7 +353,8 @@ static int generate_push_cert(struct strbuf *req_buf,
{
const struct ref *ref;
struct string_list_item *item;
- char *signing_key_id = xstrdup(get_signing_key_id());
+ char *signing_key_id = get_signing_key_id();
+ char *signing_key = get_signing_key();
const char *cp, *np;
struct strbuf cert = STRBUF_INIT;
int update_seen = 0;
@@ -386,7 +387,7 @@ static int generate_push_cert(struct strbuf *req_buf,
if (!update_seen)
goto free_return;
- if (sign_buffer(&cert, &cert, get_signing_key()))
+ if (sign_buffer(&cert, &cert, signing_key))
die(_("failed to sign the push certificate"));
packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string);
@@ -399,6 +400,7 @@ static int generate_push_cert(struct strbuf *req_buf,
free_return:
free(signing_key_id);
+ free(signing_key);
strbuf_release(&cert);
return update_seen;
}
@@ -506,14 +508,15 @@ int send_pack(struct send_pack_args *args,
unsigned cmds_sent = 0;
int ret;
struct async demux;
- const char *push_cert_nonce = NULL;
+ char *push_cert_nonce = NULL;
struct packet_reader reader;
int use_bitmaps;
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
"Perhaps you should specify a branch.\n");
- return 0;
+ ret = 0;
+ goto out;
}
git_config_get_bool("push.negotiate", &push_negotiate);
@@ -557,10 +560,11 @@ int send_pack(struct send_pack_args *args,
if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
size_t len;
- push_cert_nonce = server_feature_value("push-cert", &len);
- if (push_cert_nonce) {
- reject_invalid_nonce(push_cert_nonce, len);
- push_cert_nonce = xmemdupz(push_cert_nonce, len);
+ const char *nonce = server_feature_value("push-cert", &len);
+
+ if (nonce) {
+ reject_invalid_nonce(nonce, len);
+ push_cert_nonce = xmemdupz(nonce, len);
} else if (args->push_cert == SEND_PACK_PUSH_CERT_ALWAYS) {
die(_("the receiving end does not support --signed push"));
} else if (args->push_cert == SEND_PACK_PUSH_CERT_IF_ASKED) {
@@ -623,12 +627,11 @@ int send_pack(struct send_pack_args *args,
* atomically, abort the whole operation.
*/
if (use_atomic) {
- strbuf_release(&req_buf);
- strbuf_release(&cap_buf);
reject_atomic_push(remote_refs, args->send_mirror);
error("atomic push failed for ref %s. status: %d",
ref->name, ref->status);
- return args->porcelain ? 0 : -1;
+ ret = args->porcelain ? 0 : -1;
+ goto out;
}
/* else fallthrough */
default:
@@ -692,8 +695,6 @@ int send_pack(struct send_pack_args *args,
write_or_die(out, req_buf.buf, req_buf.len);
packet_flush(out);
}
- strbuf_release(&req_buf);
- strbuf_release(&cap_buf);
if (use_sideband && cmds_sent) {
memset(&demux, 0, sizeof(demux));
@@ -731,7 +732,9 @@ int send_pack(struct send_pack_args *args,
finish_async(&demux);
}
fd[1] = -1;
- return -1;
+
+ ret = -1;
+ goto out;
}
if (!args->stateless_rpc)
/* Closed by pack_objects() via start_command() */
@@ -756,10 +759,12 @@ int send_pack(struct send_pack_args *args,
}
if (ret < 0)
- return ret;
+ goto out;
- if (args->porcelain)
- return 0;
+ if (args->porcelain) {
+ ret = 0;
+ goto out;
+ }
for (ref = remote_refs; ref; ref = ref->next) {
switch (ref->status) {
@@ -768,8 +773,17 @@ int send_pack(struct send_pack_args *args,
case REF_STATUS_OK:
break;
default:
- return -1;
+ ret = -1;
+ goto out;
}
}
- return 0;
+
+ ret = 0;
+
+out:
+ oid_array_clear(&commons);
+ strbuf_release(&req_buf);
+ strbuf_release(&cap_buf);
+ free(push_cert_nonce);
+ return ret;
}
diff --git a/shallow.c b/shallow.c
index b8cd051e3b..dcebc263d7 100644
--- a/shallow.c
+++ b/shallow.c
@@ -51,10 +51,12 @@ int unregister_shallow(const struct object_id *oid)
int pos = commit_graft_pos(the_repository, oid);
if (pos < 0)
return -1;
- if (pos + 1 < the_repository->parsed_objects->grafts_nr)
+ if (pos + 1 < the_repository->parsed_objects->grafts_nr) {
+ free(the_repository->parsed_objects->grafts[pos]);
MOVE_ARRAY(the_repository->parsed_objects->grafts + pos,
the_repository->parsed_objects->grafts + pos + 1,
the_repository->parsed_objects->grafts_nr - pos - 1);
+ }
the_repository->parsed_objects->grafts_nr--;
return 0;
}
@@ -97,7 +99,7 @@ static void reset_repository_shallow(struct repository *r)
{
r->parsed_objects->is_shallow = -1;
stat_validity_clear(r->parsed_objects->shallow_stat);
- reset_commit_grafts(r);
+ parsed_object_pool_reset_commit_grafts(r->parsed_objects);
}
int commit_shallow_file(struct repository *r, struct shallow_lock *lk)
@@ -487,6 +489,15 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa)
void clear_shallow_info(struct shallow_info *info)
{
+ if (info->used_shallow) {
+ for (size_t i = 0; i < info->shallow->nr; i++)
+ free(info->used_shallow[i]);
+ free(info->used_shallow);
+ }
+
+ free(info->need_reachability_test);
+ free(info->reachable);
+ free(info->shallow_ref);
free(info->ours);
free(info->theirs);
}
diff --git a/submodule.c b/submodule.c
index 97516b0fec..97d0d47b56 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1883,6 +1883,8 @@ int fetch_submodules(struct repository *r,
out:
free_submodules_data(&spf.changed_submodule_names);
string_list_clear(&spf.seen_submodule_names, 0);
+ strbuf_release(&spf.submodules_with_errors);
+ free(spf.oid_fetch_tasks);
return spf.result;
}
diff --git a/t/README b/t/README
index 44c02d8129..8dcb778e26 100644
--- a/t/README
+++ b/t/README
@@ -386,6 +386,9 @@ GIT_TEST_PASSING_SANITIZE_LEAK=check when combined with "--immediate"
will run to completion faster, and result in the same failing
tests.
+GIT_TEST_PASSING_SANITIZE_LEAK=check-failing behaves the same as "check",
+but skips all tests which are already marked as leak-free.
+
GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
default to n.
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 9d693eb57f..331778bd42 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -19,6 +19,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
D=$(pwd)
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 5e566205ba..2cfb5bd6bb 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -6,6 +6,7 @@ test_description='Recursive "git fetch" for submodules'
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pwd=$(pwd)
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index f3fff55744..135823630a 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -8,6 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh
index cba26a872d..6365d99777 100755
--- a/t/t5533-push-cas.sh
+++ b/t/t5533-push-cas.sh
@@ -5,6 +5,7 @@ test_description='compare & swap push force/delete safety'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
setup_srcdst_basic () {
diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh
index c91a62b77a..d43aee0c32 100755
--- a/t/t5534-push-signed.sh
+++ b/t/t5534-push-signed.sh
@@ -5,6 +5,7 @@ test_description='signed push'
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/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
index 37f7547a4c..cae4d400f3 100755
--- a/t/t5537-fetch-shallow.sh
+++ b/t/t5537-fetch-shallow.sh
@@ -5,6 +5,7 @@ test_description='fetch/clone from a shallow clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
commit() {
diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh
index e91fcc173e..6adc3a20a4 100755
--- a/t/t5538-push-shallow.sh
+++ b/t/t5538-push-shallow.sh
@@ -5,6 +5,7 @@ test_description='push from/to a shallow clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
commit() {
diff --git a/t/t5549-fetch-push-http.sh b/t/t5549-fetch-push-http.sh
index 2cdebcb735..6377fb6d99 100755
--- a/t/t5549-fetch-push-http.sh
+++ b/t/t5549-fetch-push-http.sh
@@ -5,6 +5,7 @@ test_description='fetch/push functionality using the HTTP protocol'
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-httpd.sh
start_httpd
diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh
index b55a9f65e6..4f2e5ae8df 100755
--- a/t/t5552-skipping-fetch-negotiator.sh
+++ b/t/t5552-skipping-fetch-negotiator.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test skipping fetch negotiator'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'fetch.negotiationalgorithm config' '
diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh
index 8415884754..c53e93be2f 100755
--- a/t/t5616-partial-clone.sh
+++ b/t/t5616-partial-clone.sh
@@ -5,6 +5,7 @@ test_description='git partial clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# create a normal "src" repo where we can later create new commits.
diff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh
index 9fdafeb1e9..f31c09c056 100755
--- a/t/t6132-pathspec-exclude.sh
+++ b/t/t6132-pathspec-exclude.sh
@@ -2,6 +2,7 @@
test_description='test case exclude pathspec'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t6135-pathspec-with-attrs.sh b/t/t6135-pathspec-with-attrs.sh
index 120dcd74a5..794bc7daf0 100755
--- a/t/t6135-pathspec-with-attrs.sh
+++ b/t/t6135-pathspec-with-attrs.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test labels in pathspecs'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a tree' '
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index 5a221f8ef1..ac57b0e4ae 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -8,6 +8,7 @@ test_description='fmt-merge-msg test'
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/t6409-merge-subtree.sh b/t/t6409-merge-subtree.sh
index e9ba6f1690..528615b981 100755
--- a/t/t6409-merge-subtree.sh
+++ b/t/t6409-merge-subtree.sh
@@ -5,6 +5,7 @@ test_description='subtree merge strategy'
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 '
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index 88d1cf2cde..4aaaf38be6 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -25,6 +25,7 @@ test_description="recursive merge with directory renames"
# 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/t6500-gc.sh b/t/t6500-gc.sh
index 5378455968..ee074b99b7 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -3,6 +3,7 @@
test_description='basic git gc tests
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh
index 9fc1626fbf..8877aea98b 100755
--- a/t/t7703-repack-geometric.sh
+++ b/t/t7703-repack-geometric.sh
@@ -2,6 +2,7 @@
test_description='git repack --geometric works correctly'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GIT_TEST_MULTI_PACK_INDEX=0
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 278d1215f1..e718efe4c6 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1558,8 +1558,16 @@ then
passes_sanitize_leak=t
fi
- if test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check"
+ if test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" ||
+ test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check-failing"
then
+ if test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check-failing" &&
+ test -n "$passes_sanitize_leak"
+ then
+ skip_all="skipping leak-free $this_test under GIT_TEST_PASSING_SANITIZE_LEAK=check-failing"
+ test_done
+ fi
+
sanitize_leak_check=t
if test -n "$invert_exit_code"
then
@@ -1597,6 +1605,7 @@ then
export LSAN_OPTIONS
elif test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" ||
+ test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check-failing" ||
test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
then
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true"
diff --git a/upload-pack.c b/upload-pack.c
index f03ba3e98b..c84c3c3b1f 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -709,10 +709,13 @@ static int get_reachable_list(struct upload_pack_data *data,
struct object *o;
char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
const unsigned hexsz = the_hash_algo->hexsz;
+ int ret;
if (do_reachable_revlist(&cmd, &data->shallows, reachable,
- data->allow_uor) < 0)
- return -1;
+ data->allow_uor) < 0) {
+ ret = -1;
+ goto out;
+ }
while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
struct object_id oid;
@@ -736,10 +739,16 @@ static int get_reachable_list(struct upload_pack_data *data,
}
close(cmd.out);
- if (finish_command(&cmd))
- return -1;
+ if (finish_command(&cmd)) {
+ ret = -1;
+ goto out;
+ }
- return 0;
+ ret = 0;
+
+out:
+ child_process_clear(&cmd);
+ return ret;
}
static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
@@ -749,7 +758,7 @@ static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
int i;
if (do_reachable_revlist(&cmd, src, NULL, allow_uor) < 0)
- return 1;
+ goto error;
/*
* The commits out of the rev-list are not ancestors of
@@ -775,6 +784,7 @@ static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
error:
if (cmd.out >= 0)
close(cmd.out);
+ child_process_clear(&cmd);
return 1;
}