receive-pack: fix crash on out-of-namespace symref

`check_aliased_update_internal()` detects when a symbolic ref and its
target are being updated in the same push. It does this by building a
list of ref names without the optional namespace prefix. When a symbolic
ref within a namespace points to a ref outside the namespace,
`strip_namespace()` returns NULL which leads to a segfault.

A NULL check preventing this particular issue was repurposed in
ded8393610. Rather than reintroducing it, we can instead build a list of
fully qualified ref names. This prevents the crash, preserves the
consistency check from da3efdb17b, and allows updates to all symbolic
refs.

Signed-off-by: Troels Thomsen <troels@thomsen.io>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Troels Thomsen 2025-12-27 15:40:14 +00:00 committed by Junio C Hamano
parent 9a2fb147f2
commit 57f7dd48d7
2 changed files with 19 additions and 3 deletions

View File

@ -1685,7 +1685,6 @@ static void check_aliased_update_internal(struct command *cmd,
cmd->error_string = "broken symref";
return;
}
dst_name = strip_namespace(dst_name);
if (!(item = string_list_lookup(list, dst_name)))
return;
@ -1730,10 +1729,13 @@ static void check_aliased_updates(struct command *commands)
{
struct command *cmd;
struct string_list ref_list = STRING_LIST_INIT_NODUP;
struct strbuf ref_name = STRBUF_INIT;
for (cmd = commands; cmd; cmd = cmd->next) {
struct string_list_item *item =
string_list_append(&ref_list, cmd->ref_name);
struct string_list_item *item;
strbuf_reset(&ref_name);
strbuf_addf(&ref_name, "%s%s", get_git_namespace(), cmd->ref_name);
item = string_list_append(&ref_list, ref_name.buf);
item->util = (void *)cmd;
}
string_list_sort(&ref_list);
@ -1743,6 +1745,7 @@ static void check_aliased_updates(struct command *commands)
check_aliased_update(cmd, &ref_list);
}
strbuf_release(&ref_name);
string_list_clear(&ref_list, 0);
}

View File

@ -175,4 +175,17 @@ test_expect_success 'denyCurrentBranch and unborn branch with ref namespace' '
)
'
test_expect_success 'pushing to symref pointing outside the namespace' '
(
cd pushee &&
git symbolic-ref refs/namespaces/namespace/refs/heads/main refs/heads/main &&
cd ../original &&
git push pushee-namespaced main &&
git ls-remote pushee-unnamespaced refs/heads/main >actual &&
printf "$commit1\trefs/heads/main\n" >expected &&
printf "$commit1\trefs/namespaces/namespace/refs/heads/main\n" >>expected &&
test_cmp expected actual
)
'
test_done