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
  ...
This commit is contained in:
Junio C Hamano
2024-09-20 11:16:30 -07:00
42 changed files with 178 additions and 72 deletions

View File

@ -67,6 +67,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
return ret; return ret;
write_in_full(STDOUT_FILENO, output.buf, output.len); write_in_full(STDOUT_FILENO, output.buf, output.len);
strbuf_release(&input);
strbuf_release(&output);
free(inpath); free(inpath);
return 0; return 0;
} }

View File

@ -1133,6 +1133,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
&oid, &oc)) { &oid, &oc)) {
if (seen_dashdash) if (seen_dashdash)
die(_("unable to resolve revision: %s"), arg); die(_("unable to resolve revision: %s"), arg);
object_context_release(&oc);
break; break;
} }

View File

@ -4669,6 +4669,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
cleanup: cleanup:
clear_packing_data(&to_pack); clear_packing_data(&to_pack);
list_objects_filter_release(&filter_options); list_objects_filter_release(&filter_options);
string_list_clear(&keep_pack_list, 0);
strvec_clear(&rp); strvec_clear(&rp);
return 0; return 0;

View File

@ -72,13 +72,15 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref,
const char *branch_name; const char *branch_name;
if (remote->push.nr) { if (remote->push.nr) {
struct refspec_item query; struct refspec_item query = {
memset(&query, 0, sizeof(struct refspec_item)); .src = matched->name,
query.src = matched->name; };
if (!query_refspecs(&remote->push, &query) && query.dst) { if (!query_refspecs(&remote->push, &query) && query.dst) {
refspec_appendf(refspec, "%s%s:%s", refspec_appendf(refspec, "%s%s:%s",
query.force ? "+" : "", query.force ? "+" : "",
query.src, query.dst); query.src, query.dst);
free(query.dst);
return; return;
} }
} }

View File

@ -425,9 +425,11 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
free(promisor_name); free(promisor_name);
} }
fclose(out); fclose(out);
if (finish_command(&cmd)) if (finish_command(&cmd))
die(_("could not finish pack-objects to repack promisor objects")); die(_("could not finish pack-objects to repack promisor objects"));
strbuf_release(&line);
} }
struct pack_geometry { struct pack_geometry {
@ -1541,6 +1543,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
} }
cleanup: cleanup:
string_list_clear(&keep_pack_list, 0);
string_list_clear(&names, 1); string_list_clear(&names, 1);
existing_packs_release(&existing); existing_packs_release(&existing);
free_pack_geometry(&geometry); free_pack_geometry(&geometry);

View File

@ -2958,7 +2958,9 @@ static int push_check(int argc, const char **argv, const char *prefix UNUSED)
rs->src); rs->src);
} }
} }
refspec_clear(&refspec); refspec_clear(&refspec);
free_refs(local_refs);
} }
free(head); free(head);

View File

@ -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; const struct git_hash_algo *compat = the_repository->compat_hash_algo;
struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT; struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT;
struct strbuf compat_buf = STRBUF_INIT; struct strbuf compat_buf = STRBUF_INIT;
const char *keyid = get_signing_key(); char *keyid = get_signing_key();
int ret = -1; int ret = -1;
if (sign_buffer(buffer, &sig, keyid)) if (sign_buffer(buffer, &sig, keyid))
@ -190,6 +190,7 @@ out:
strbuf_release(&sig); strbuf_release(&sig);
strbuf_release(&compat_sig); strbuf_release(&compat_sig);
strbuf_release(&compat_buf); strbuf_release(&compat_buf);
free(keyid);
return ret; return ret;
} }

View File

@ -183,7 +183,7 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid)
commit_graft_oid_access); 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); 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; 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 { struct commit_buffer {
void *buffer; void *buffer;
unsigned long size; 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) 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) if (!keyid || !*keyid)
keyid = get_signing_key(); keyid = keyid_to_free = get_signing_key();
if (sign_buffer(buf, sig, keyid)) if (sign_buffer(buf, sig, keyid))
return -1; ret = -1;
return 0; free(keyid_to_free);
return ret;
} }
int parse_signed_commit(const struct commit *commit, int parse_signed_commit(const struct commit *commit,

View File

@ -110,6 +110,8 @@ static inline int repo_parse_commit_no_graph(struct repository *r,
void parse_commit_or_die(struct commit *item); 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;
struct buffer_slab *allocate_commit_buffer_slab(void); struct buffer_slab *allocate_commit_buffer_slab(void);
void free_commit_buffer_slab(struct buffer_slab *bs); 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); int register_commit_graft(struct repository *r, struct commit_graft *, int);
void prepare_commit_graft(struct repository *r); void prepare_commit_graft(struct repository *r);
struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid); 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); struct commit *get_fork_point(const char *refname, struct commit *commit);

View File

@ -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_region_leave("fetch-pack", "negotiate_using_fetch", the_repository);
trace2_data_intmax("negotiate_using_fetch", the_repository, trace2_data_intmax("negotiate_using_fetch", the_repository,
"total_rounds", negotiation_round); "total_rounds", negotiation_round);
clear_common_flag(acked_commits); clear_common_flag(acked_commits);
object_array_clear(&nt_object_array);
negotiator.release(&negotiator);
strbuf_release(&req_buf); strbuf_release(&req_buf);
} }

View File

@ -45,8 +45,8 @@ struct gpg_format {
size_t signature_size); size_t signature_size);
int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature, int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key); const char *signing_key);
const char *(*get_default_key)(void); char *(*get_default_key)(void);
const char *(*get_key_id)(void); char *(*get_key_id)(void);
}; };
static const char *openpgp_verify_args[] = { 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, static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key); 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[] = { 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 */ /* 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; struct child_process ssh_default_key = CHILD_PROCESS_INIT;
int ret = -1; int ret = -1;
@ -899,12 +899,16 @@ static const char *get_default_ssh_signing_key(void)
return default_key; return default_key;
} }
static const char *get_ssh_key_id(void) { static char *get_ssh_key_id(void)
return get_ssh_key_fingerprint(get_signing_key()); {
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 */ /* 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(); gpg_interface_lazy_init();
@ -916,17 +920,17 @@ const char *get_signing_key_id(void)
return get_signing_key(); return get_signing_key();
} }
const char *get_signing_key(void) char *get_signing_key(void)
{ {
gpg_interface_lazy_init(); gpg_interface_lazy_init();
if (configured_signing_key) if (configured_signing_key)
return configured_signing_key; return xstrdup(configured_signing_key);
if (use_format->get_default_key) { if (use_format->get_default_key) {
return 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) const char *gpg_trust_level_to_str(enum signature_trust_level level)

View File

@ -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); const char *gpg_trust_level_to_str(enum signature_trust_level level);
void set_signing_key(const char *); 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 * Returns a textual unique representation of the signing key in use
* Either a GPG KeyID or a SSH Key Fingerprint * 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, int check_signature(struct signature_check *sigc,
const char *signature, size_t slen); const char *signature, size_t slen);
void print_signature_buffer(const struct signature_check *sigc, void print_signature_buffer(const struct signature_check *sigc,

View File

@ -294,18 +294,22 @@ void shift_tree(struct repository *r,
unsigned short mode; unsigned short mode;
if (!*del_prefix) if (!*del_prefix)
return; goto out;
if (get_tree_entry(r, hash2, del_prefix, shifted, &mode)) if (get_tree_entry(r, hash2, del_prefix, shifted, &mode))
die("cannot find path %s in tree %s", die("cannot find path %s in tree %s",
del_prefix, oid_to_hex(hash2)); del_prefix, oid_to_hex(hash2));
return; goto out;
} }
if (!*add_prefix) if (!*add_prefix)
return; goto out;
splice_tree(hash1, add_prefix, hash2, shifted); splice_tree(hash1, add_prefix, hash2, shifted);
out:
free(add_prefix);
free(del_prefix);
} }
/* /*

View File

@ -2710,7 +2710,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
struct conflict_info *dir_ci; struct conflict_info *dir_ci;
char *cur_dir = dirs_to_insert.items[i].string; 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; dir_ci->merged.directory_name = parent_name;
len = strlen(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. * Finally, record the new location.
*/ */
pair->two->path = new_path; pair->two->path = new_path;
string_list_clear(&dirs_to_insert, 0);
} }
/*** Function Grouping: functions related to regular rename detection ***/ /*** Function Grouping: functions related to regular rename detection ***/

View File

@ -247,8 +247,11 @@ static int ack(struct fetch_negotiator *n, struct commit *c)
static void release(struct fetch_negotiator *n) static void release(struct fetch_negotiator *n)
{ {
clear_prio_queue(&((struct data *)n->data)->rev_list); struct data *data = n->data;
FREE_AND_NULL(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) void skipping_negotiator_init(struct fetch_negotiator *negotiator)

View File

@ -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)); struct parsed_object_pool *o = xmalloc(sizeof(*o));
memset(o, 0, sizeof(*o)); memset(o, 0, sizeof(*o));
o->repo = repo;
o->blob_state = allocate_alloc_state(); o->blob_state = allocate_alloc_state();
o->tree_state = allocate_alloc_state(); o->tree_state = allocate_alloc_state();
o->commit_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); 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) 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); free_commit_buffer_slab(o->buffer_slab);
o->buffer_slab = NULL; o->buffer_slab = NULL;
parsed_object_pool_reset_commit_grafts(o);
clear_alloc_state(o->blob_state); clear_alloc_state(o->blob_state);
clear_alloc_state(o->tree_state); clear_alloc_state(o->tree_state);
clear_alloc_state(o->commit_state); clear_alloc_state(o->commit_state);

View File

@ -7,6 +7,7 @@ struct buffer_slab;
struct repository; struct repository;
struct parsed_object_pool { struct parsed_object_pool {
struct repository *repo;
struct object **obj_hash; struct object **obj_hash;
int nr_objs, obj_hash_size; int nr_objs, obj_hash_size;
@ -31,8 +32,9 @@ struct parsed_object_pool {
struct buffer_slab *buffer_slab; 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_clear(struct parsed_object_pool *o);
void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o);
struct object_list { struct object_list {
struct object *item; struct object *item;

View File

@ -1123,6 +1123,7 @@ void free_one_ref(struct ref *ref)
return; return;
free_one_ref(ref->peer_ref); free_one_ref(ref->peer_ref);
free(ref->remote_status); free(ref->remote_status);
free(ref->tracking_ref);
free(ref->symref); free(ref->symref);
free(ref); free(ref);
} }
@ -2620,8 +2621,10 @@ static int remote_tracking(struct remote *remote, const char *refname,
dst = apply_refspecs(&remote->fetch, refname); dst = apply_refspecs(&remote->fetch, refname);
if (!dst) if (!dst)
return -1; /* no tracking ref for refname at remote */ 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 */ return -1; /* we know what the tracking ref is but we cannot read it */
}
*dst_refname = dst; *dst_refname = dst;
return 0; return 0;
@ -2771,6 +2774,7 @@ static void check_if_includes_upstream(struct ref *remote)
if (is_reachable_in_reflog(local->name, remote) <= 0) if (is_reachable_in_reflog(local->name, remote) <= 0)
remote->unreachable = 1; remote->unreachable = 1;
free_one_ref(local);
} }
static void apply_cas(struct push_cas_option *cas, static void apply_cas(struct push_cas_option *cas,

View File

@ -54,7 +54,7 @@ void initialize_repository(struct repository *repo)
{ {
repo->objects = raw_object_store_new(); repo->objects = raw_object_store_new();
repo->remote_state = remote_state_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); ALLOC_ARRAY(repo->index, 1);
index_state_init(repo->index, repo); index_state_init(repo->index, repo);

View File

@ -353,7 +353,8 @@ static int generate_push_cert(struct strbuf *req_buf,
{ {
const struct ref *ref; const struct ref *ref;
struct string_list_item *item; 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; const char *cp, *np;
struct strbuf cert = STRBUF_INIT; struct strbuf cert = STRBUF_INIT;
int update_seen = 0; int update_seen = 0;
@ -386,7 +387,7 @@ static int generate_push_cert(struct strbuf *req_buf,
if (!update_seen) if (!update_seen)
goto free_return; 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")); die(_("failed to sign the push certificate"));
packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string); 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_return:
free(signing_key_id); free(signing_key_id);
free(signing_key);
strbuf_release(&cert); strbuf_release(&cert);
return update_seen; return update_seen;
} }
@ -506,14 +508,15 @@ int send_pack(struct send_pack_args *args,
unsigned cmds_sent = 0; unsigned cmds_sent = 0;
int ret; int ret;
struct async demux; struct async demux;
const char *push_cert_nonce = NULL; char *push_cert_nonce = NULL;
struct packet_reader reader; struct packet_reader reader;
int use_bitmaps; int use_bitmaps;
if (!remote_refs) { if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n" fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
"Perhaps you should specify a branch.\n"); "Perhaps you should specify a branch.\n");
return 0; ret = 0;
goto out;
} }
git_config_get_bool("push.negotiate", &push_negotiate); 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) { if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
size_t len; size_t len;
push_cert_nonce = server_feature_value("push-cert", &len); const char *nonce = server_feature_value("push-cert", &len);
if (push_cert_nonce) {
reject_invalid_nonce(push_cert_nonce, len); if (nonce) {
push_cert_nonce = xmemdupz(push_cert_nonce, len); reject_invalid_nonce(nonce, len);
push_cert_nonce = xmemdupz(nonce, len);
} else if (args->push_cert == SEND_PACK_PUSH_CERT_ALWAYS) { } else if (args->push_cert == SEND_PACK_PUSH_CERT_ALWAYS) {
die(_("the receiving end does not support --signed push")); die(_("the receiving end does not support --signed push"));
} else if (args->push_cert == SEND_PACK_PUSH_CERT_IF_ASKED) { } 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. * atomically, abort the whole operation.
*/ */
if (use_atomic) { if (use_atomic) {
strbuf_release(&req_buf);
strbuf_release(&cap_buf);
reject_atomic_push(remote_refs, args->send_mirror); reject_atomic_push(remote_refs, args->send_mirror);
error("atomic push failed for ref %s. status: %d", error("atomic push failed for ref %s. status: %d",
ref->name, ref->status); ref->name, ref->status);
return args->porcelain ? 0 : -1; ret = args->porcelain ? 0 : -1;
goto out;
} }
/* else fallthrough */ /* else fallthrough */
default: default:
@ -692,8 +695,6 @@ int send_pack(struct send_pack_args *args,
write_or_die(out, req_buf.buf, req_buf.len); write_or_die(out, req_buf.buf, req_buf.len);
packet_flush(out); packet_flush(out);
} }
strbuf_release(&req_buf);
strbuf_release(&cap_buf);
if (use_sideband && cmds_sent) { if (use_sideband && cmds_sent) {
memset(&demux, 0, sizeof(demux)); memset(&demux, 0, sizeof(demux));
@ -731,7 +732,9 @@ int send_pack(struct send_pack_args *args,
finish_async(&demux); finish_async(&demux);
} }
fd[1] = -1; fd[1] = -1;
return -1;
ret = -1;
goto out;
} }
if (!args->stateless_rpc) if (!args->stateless_rpc)
/* Closed by pack_objects() via start_command() */ /* Closed by pack_objects() via start_command() */
@ -756,10 +759,12 @@ int send_pack(struct send_pack_args *args,
} }
if (ret < 0) if (ret < 0)
return ret; goto out;
if (args->porcelain) if (args->porcelain) {
return 0; ret = 0;
goto out;
}
for (ref = remote_refs; ref; ref = ref->next) { for (ref = remote_refs; ref; ref = ref->next) {
switch (ref->status) { switch (ref->status) {
@ -768,8 +773,17 @@ int send_pack(struct send_pack_args *args,
case REF_STATUS_OK: case REF_STATUS_OK:
break; break;
default: 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;
} }

View File

@ -51,10 +51,12 @@ int unregister_shallow(const struct object_id *oid)
int pos = commit_graft_pos(the_repository, oid); int pos = commit_graft_pos(the_repository, oid);
if (pos < 0) if (pos < 0)
return -1; 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, MOVE_ARRAY(the_repository->parsed_objects->grafts + pos,
the_repository->parsed_objects->grafts + pos + 1, the_repository->parsed_objects->grafts + pos + 1,
the_repository->parsed_objects->grafts_nr - pos - 1); the_repository->parsed_objects->grafts_nr - pos - 1);
}
the_repository->parsed_objects->grafts_nr--; the_repository->parsed_objects->grafts_nr--;
return 0; return 0;
} }
@ -97,7 +99,7 @@ static void reset_repository_shallow(struct repository *r)
{ {
r->parsed_objects->is_shallow = -1; r->parsed_objects->is_shallow = -1;
stat_validity_clear(r->parsed_objects->shallow_stat); 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) 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) 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->ours);
free(info->theirs); free(info->theirs);
} }

View File

@ -1883,6 +1883,8 @@ int fetch_submodules(struct repository *r,
out: out:
free_submodules_data(&spf.changed_submodule_names); free_submodules_data(&spf.changed_submodule_names);
string_list_clear(&spf.seen_submodule_names, 0); string_list_clear(&spf.seen_submodule_names, 0);
strbuf_release(&spf.submodules_with_errors);
free(spf.oid_fetch_tasks);
return spf.result; return spf.result;
} }

View File

@ -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 will run to completion faster, and result in the same failing
tests. 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' GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
default to n. default to n.

View File

@ -19,6 +19,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1 TEST_CREATE_REPO_NO_TEMPLATE=1
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
D=$(pwd) D=$(pwd)

View File

@ -6,6 +6,7 @@ test_description='Recursive "git fetch" for submodules'
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
pwd=$(pwd) pwd=$(pwd)

View File

@ -8,6 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success setup ' test_expect_success setup '

View File

@ -5,6 +5,7 @@ test_description='compare & swap push force/delete safety'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
setup_srcdst_basic () { setup_srcdst_basic () {

View File

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

View File

@ -5,6 +5,7 @@ test_description='fetch/clone from a shallow clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
commit() { commit() {

View File

@ -5,6 +5,7 @@ test_description='push from/to a shallow clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
commit() { commit() {

View File

@ -5,6 +5,7 @@ test_description='fetch/push functionality using the HTTP protocol'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh . "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd start_httpd

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='test skipping fetch negotiator' test_description='test skipping fetch negotiator'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'fetch.negotiationalgorithm config' ' test_expect_success 'fetch.negotiationalgorithm config' '

View File

@ -5,6 +5,7 @@ test_description='git partial clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# create a normal "src" repo where we can later create new commits. # create a normal "src" repo where we can later create new commits.

View File

@ -2,6 +2,7 @@
test_description='test case exclude pathspec' test_description='test case exclude pathspec'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='test labels in pathspecs' test_description='test labels in pathspecs'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup a tree' ' test_expect_success 'setup a tree' '

View File

@ -8,6 +8,7 @@ test_description='fmt-merge-msg test'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh" . "$TEST_DIRECTORY/lib-gpg.sh"

View File

@ -5,6 +5,7 @@ test_description='subtree merge strategy'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success setup ' test_expect_success setup '

View File

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

View File

@ -3,6 +3,7 @@
test_description='basic git gc tests test_description='basic git gc tests
' '
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh . "$TEST_DIRECTORY"/lib-terminal.sh

View File

@ -2,6 +2,7 @@
test_description='git repack --geometric works correctly' test_description='git repack --geometric works correctly'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
GIT_TEST_MULTI_PACK_INDEX=0 GIT_TEST_MULTI_PACK_INDEX=0

View File

@ -1558,8 +1558,16 @@ then
passes_sanitize_leak=t passes_sanitize_leak=t
fi 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 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 sanitize_leak_check=t
if test -n "$invert_exit_code" if test -n "$invert_exit_code"
then then
@ -1597,6 +1605,7 @@ then
export LSAN_OPTIONS export LSAN_OPTIONS
elif test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" || 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 test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
then then
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true" BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true"

View File

@ -709,10 +709,13 @@ static int get_reachable_list(struct upload_pack_data *data,
struct object *o; struct object *o;
char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */ char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
const unsigned hexsz = the_hash_algo->hexsz; const unsigned hexsz = the_hash_algo->hexsz;
int ret;
if (do_reachable_revlist(&cmd, &data->shallows, reachable, if (do_reachable_revlist(&cmd, &data->shallows, reachable,
data->allow_uor) < 0) data->allow_uor) < 0) {
return -1; ret = -1;
goto out;
}
while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) { while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
struct object_id oid; struct object_id oid;
@ -736,10 +739,16 @@ static int get_reachable_list(struct upload_pack_data *data,
} }
close(cmd.out); close(cmd.out);
if (finish_command(&cmd)) if (finish_command(&cmd)) {
return -1; 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) 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; int i;
if (do_reachable_revlist(&cmd, src, NULL, allow_uor) < 0) 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 * 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: error:
if (cmd.out >= 0) if (cmd.out >= 0)
close(cmd.out); close(cmd.out);
child_process_clear(&cmd);
return 1; return 1;
} }