From 57f7dd48d79302a095b56fa4019b537b4f4fd60d Mon Sep 17 00:00:00 2001 From: Troels Thomsen Date: Sat, 27 Dec 2025 15:40:14 +0000 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- builtin/receive-pack.c | 9 ++++++--- t/t5509-fetch-push-namespaces.sh | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index c9288a9c7e..cfb17f9352 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -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); } diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh index 095df1a753..3c333ccc5f 100755 --- a/t/t5509-fetch-push-namespaces.sh +++ b/t/t5509-fetch-push-namespaces.sh @@ -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