From: Jeff King <peff@peff.net>
To: git@vger.kernel.org
Cc: Harald Nordgren <haraldnordgren@gmail.com>
Subject: [PATCH 4/4] remote: always allocate branch.push_tracking_ref
Date: Mon, 19 Jan 2026 00:23:20 -0500 [thread overview]
Message-ID: <20260119052320.GD1991523@coredump.intra.peff.net> (raw)
In-Reply-To: <20260119051858.GA1991308@coredump.intra.peff.net>
In branch_get_push(), we usually allocate a new string for the @{push}
ref, but will not do so in push.default=upstream mode, where we just
pass back the result of branch_get_upstream() directly.
This led to a hacky memory management scheme in e291c75a95 (remote.c:
add branch_get_push, 2015-05-21): we store the result in the
push_tracking_ref field of a "struct branch", under the assumption that
the branch struct will last until the end of the program. So even though
the struct doesn't know if it has an allocated string or not, it doesn't
matter because we hold on to it either way.
But that assumption was violated by f5ccb535cc (remote: fix leaking
config strings, 2024-08-22), which added a function to free branch
structs. Any struct which is fed to branch_release() is at risk of
leaking its push_tracking_ref member.
I don't think this can actually be triggered in practice. We rarely
actually free the branch structs, and we only fill in the
push_tracking_ref string lazily when it is needed. So triggering the
leak would require a code path that does both, and I couldn't find one.
Still, this is an ugly trap that may eventually spring on us. Since
there is only one code path in branch_get_push() that doesn't allocate,
let's just have it copy the string. And then we know that
push_tracking_ref is always allocated, and we can free it in
branch_release().
Signed-off-by: Jeff King <peff@peff.net>
---
remote.c | 7 ++++---
remote.h | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/remote.c b/remote.c
index e191b0ff6e..3e9d9b3e1f 100644
--- a/remote.c
+++ b/remote.c
@@ -272,6 +272,7 @@ static void branch_release(struct branch *branch)
free((char *)branch->refname);
free(branch->remote_name);
free(branch->pushremote_name);
+ free(branch->push_tracking_ref);
merge_clear(branch);
}
@@ -1883,8 +1884,8 @@ static char *tracking_for_push_dest(struct remote *remote,
return ret;
}
-static const char *branch_get_push_1(struct repository *repo,
- struct branch *branch, struct strbuf *err)
+static char *branch_get_push_1(struct repository *repo,
+ struct branch *branch, struct strbuf *err)
{
struct remote_state *remote_state = repo->remote_state;
struct remote *remote;
@@ -1924,7 +1925,7 @@ static const char *branch_get_push_1(struct repository *repo,
return tracking_for_push_dest(remote, branch->refname, err);
case PUSH_DEFAULT_UPSTREAM:
- return branch_get_upstream(branch, err);
+ return xstrdup_or_null(branch_get_upstream(branch, err));
case PUSH_DEFAULT_UNSPECIFIED:
case PUSH_DEFAULT_SIMPLE:
diff --git a/remote.h b/remote.h
index 0ca399e183..fc052945ee 100644
--- a/remote.h
+++ b/remote.h
@@ -331,7 +331,7 @@ struct branch {
int merge_alloc;
- const char *push_tracking_ref;
+ char *push_tracking_ref;
};
struct branch *branch_get(const char *name);
--
2.53.0.rc0.338.g08aa8a9473
next prev parent reply other threads:[~2026-01-19 5:23 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-19 5:18 [PATCH 0/4] memory leaks in remote.c Jeff King
2026-01-19 5:19 ` [PATCH 1/4] remote: return non-const pointer from error_buf() Jeff King
2026-01-19 6:33 ` Patrick Steinhardt
2026-01-20 0:28 ` Junio C Hamano
2026-01-20 19:38 ` Jeff King
2026-01-20 20:18 ` Junio C Hamano
2026-01-19 5:20 ` [PATCH 2/4] remote: drop const return of tracking_for_push_dest() Jeff King
2026-01-19 6:34 ` Patrick Steinhardt
2026-01-19 5:22 ` [PATCH 3/4] remote: fix leak in branch_get_push_1() with invalid "simple" config Jeff King
2026-01-19 6:34 ` Patrick Steinhardt
2026-01-19 5:23 ` Jeff King [this message]
2026-01-19 6:34 ` [PATCH 4/4] remote: always allocate branch.push_tracking_ref Patrick Steinhardt
2026-01-19 15:04 ` Triangular workflow Harald Nordgren
2026-01-20 19:40 ` Jeff King
2026-01-20 0:31 ` [PATCH 0/4] memory leaks in remote.c Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260119052320.GD1991523@coredump.intra.peff.net \
--to=peff@peff.net \
--cc=git@vger.kernel.org \
--cc=haraldnordgren@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox