Skip to content

Commit 5e9e04a

Browse files
pks-tgitster
authored andcommitted
remote: fix leaks when matching refspecs
In `match_explicit()`, we try to match a source ref with a destination ref according to a refspec item. This matching sometimes requires us to allocate a new source spec so that it looks like we expect. And while we in some end up assigning this allocated ref as `peer_ref`, which hands over ownership of it to the caller, in other cases we don't. We neither free it though, causing a memory leak. Fix the leak by creating a common exit path where we can easily free the source ref in case it is allocated and hasn't been handed over to the caller. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f5ccb53 commit 5e9e04a

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

remote.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,18 +1344,21 @@ static int match_explicit(struct ref *src, struct ref *dst,
13441344
struct ref ***dst_tail,
13451345
struct refspec_item *rs)
13461346
{
1347-
struct ref *matched_src, *matched_dst;
1348-
int allocated_src;
1347+
struct ref *matched_src = NULL, *matched_dst = NULL;
1348+
int allocated_src = 0, ret;
13491349

13501350
const char *dst_value = rs->dst;
13511351
char *dst_guess;
13521352

1353-
if (rs->pattern || rs->matching || rs->negative)
1354-
return 0;
1353+
if (rs->pattern || rs->matching || rs->negative) {
1354+
ret = 0;
1355+
goto out;
1356+
}
13551357

1356-
matched_src = matched_dst = NULL;
1357-
if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0)
1358-
return -1;
1358+
if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0) {
1359+
ret = -1;
1360+
goto out;
1361+
}
13591362

13601363
if (!dst_value) {
13611364
int flag;
@@ -1394,18 +1397,30 @@ static int match_explicit(struct ref *src, struct ref *dst,
13941397
dst_value);
13951398
break;
13961399
}
1397-
if (!matched_dst)
1398-
return -1;
1399-
if (matched_dst->peer_ref)
1400-
return error(_("dst ref %s receives from more than one src"),
1401-
matched_dst->name);
1402-
else {
1400+
1401+
if (!matched_dst) {
1402+
ret = -1;
1403+
goto out;
1404+
}
1405+
1406+
if (matched_dst->peer_ref) {
1407+
ret = error(_("dst ref %s receives from more than one src"),
1408+
matched_dst->name);
1409+
goto out;
1410+
} else {
14031411
matched_dst->peer_ref = allocated_src ?
14041412
matched_src :
14051413
copy_ref(matched_src);
14061414
matched_dst->force = rs->force;
1415+
matched_src = NULL;
14071416
}
1408-
return 0;
1417+
1418+
ret = 0;
1419+
1420+
out:
1421+
if (allocated_src)
1422+
free_one_ref(matched_src);
1423+
return ret;
14091424
}
14101425

14111426
static int match_explicit_refs(struct ref *src, struct ref *dst,

t/t5505-remote.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
test_description='git remote porcelain-ish'
44

5+
TEST_PASSES_SANITIZE_LEAK=true
56
. ./test-lib.sh
67

78
setup_repository () {

0 commit comments

Comments
 (0)