{"thread":{"id":"65325","subject":"remote-curl: segfault parsing remote.<name>.fetch outside a repository","startedAt":"2026-03-21T19:11:30Z","lastAt":"2026-03-24T04:26:00Z","messageCount":17,"participants":["Jo Liss","K Jayatheerth","Jeff King","brian m. carlson","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"539611","messageId":"CAN=xy38zCRdOAnMtBXtRyUHE=+gtS8J6mwUWFQqxDAaBLAm7dA@mail.gmail.com","threadId":"65325","inReplyTo":null,"subject":"remote-curl: segfault parsing remote.<name>.fetch outside a repository","fromName":"Jo Liss","fromEmail":"joliss42@gmail.com","sentAt":"2026-03-21T19:11:18Z","receivedAt":"2026-03-21T19:11:30Z","isPatch":false,"body":"Hi mailing list,\n\nI ran into a bug and thought I'd report it! The following command\nsegfaults for me (where ~/src/git is my clone):\n\nenv -C / \\\n    GIT_CONFIG_NOSYSTEM=1 \\\n    GIT_CONFIG_GLOBAL=/dev/null \\\n    GIT_CONFIG_COUNT=1 \\\n    GIT_CONFIG_KEY_0=remote.repro.fetch \\\n    GIT_CONFIG_VALUE_0='+refs/tags/*:refs/tags/*' \\\n    ~/src/git/git-remote-http repro\n\nIn other words, this is happening when the shared remote-curl code\n(here, git-remote-http) is called outside of any repository, while\n`remote.<name>.fetch` is set.\n\nI can reproduce this on Ubuntu and macOS, with git master\n(7ff1e8dc1e16) and git 2.51.0.\n\nThe way I actually ran into this was by running `git ls-remote -h\n<url>` outside of a git repository, and my `remote.origin.fetch` is\nglobally set to `+refs/tags/*:refs/tags/*`.\n\nHere's a backtrace:\n\n~/src/git $ make clean && make DEVELOPER=1 CFLAGS='-g -O0 -Wall'\n...\n~/src/git $ env -C / \\\n  GIT_CONFIG_NOSYSTEM=1 \\\n  GIT_CONFIG_GLOBAL=/dev/null \\\n  GIT_CONFIG_COUNT=1 \\\n  GIT_CONFIG_KEY_0=remote.repro.fetch \\\n  GIT_CONFIG_VALUE_0='+refs/tags/*:refs/tags/*' \\\n  gdb -q -batch \\\n  -ex 'set debuginfod enabled off' \\\n  -ex 'set startup-with-shell off' \\\n  -ex run \\\n  -ex 'bt full' \\\n  --args ~/src/git/git-remote-http repro\n[Thread debugging using libthread_db enabled]\nUsing host libthread_db library \"/lib/aarch64-linux-gnu/libthread_db.so.1\".\n\nProgram received signal SIGSEGV, Segmentation fault.\nparse_refspec (item=0xffffffffda88, refspec=0xaaaaaadf0650\n\"+refs/tags/*:refs/tags/*\", fetch=1) at refspec.c:104\n104 else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n#0  parse_refspec (item=0xffffffffda88, refspec=0xaaaaaadf0650\n\"+refs/tags/*:refs/tags/*\", fetch=1) at refspec.c:104\n        unused = {hash = \"\n\\nߪ\\252\\252\\000\\000\\031\\000\\000\\000\\000\\000\\000\\000\n\\332\\377\\377\\377\\377\\000\\000\\300Iʪ\\252\\252\\000\", algo = 2866743840}\n        llen = 11\n        is_glob = 1\n        lhs = 0xaaaaaadf0651 \"refs/tags/*:refs/tags/*\"\n        rhs = 0xaaaaaadf065d \"refs/tags/*\"\n        flags = 3\n#1  0x0000aaaaaaca49dc in refspec_item_init (item=0xffffffffda88,\nrefspec=0xaaaaaadf0650 \"+refs/tags/*:refs/tags/*\", fetch=1) at\nrefspec.c:161\nNo locals.\n#2  0x0000aaaaaaca4a04 in refspec_item_init_fetch\n(item=0xffffffffda88, refspec=0xaaaaaadf0650\n\"+refs/tags/*:refs/tags/*\") at refspec.c:166\nNo locals.\n#3  0x0000aaaaaaca4c08 in refspec_append (rs=0xaaaaaadf0a90,\nrefspec=0xaaaaaadf0650 \"+refs/tags/*:refs/tags/*\") at refspec.c:203\n        item = {force = 1, pattern = 1, matching = 0, exact_sha1 = 0,\nnegative = 0, src = 0xaaaaaadd49d0 \"refs/tags/*\", dst = 0xaaaaaadd4b90\n\"refs/tags/*\", raw = 0xaaaaaadf0b20 \"+refs/tags/*:refs/tags/*\"}\n        ret = 43690\n#4  0x0000aaaaaab64c00 in handle_config (key=0xaaaaaadd4810\n\"remote.repro.fetch\", value=0xaaaaaadf06d0 \"+refs/tags/*:refs/tags/*\",\nctx=0xffffffffdb80, cb=0xaaaaaadeeb70) at remote.c:528\n        v = 0xaaaaaadf0650 \"+refs/tags/*:refs/tags/*\"\n        name = 0xaaaaaadd4817 \"repro.fetch\"\n        namelen = 5\n        subkey = 0xaaaaaadd481d \"fetch\"\n        remote = 0xaaaaaadf0a20\n        branch = 0xaaaaaab98654 <cmp_strmap_entry>\n        remote_state = 0xaaaaaadeeb70\n        kvi = 0xaaaaaadd48f0\n#5  0x0000aaaaaaac12f0 in configset_iter (set=0xaaaaaadeeb20,\nfn=0xaaaaaab645e4 <handle_config>, data=0xaaaaaadeeb70) at\nconfig.c:1639\n        i = 0\n        value_index = 0\n        values = 0xaaaaaadf0698\n        entry = 0xaaaaaadf0680\n        list = 0xaaaaaadeeb58\n        ctx = {kvi = 0xaaaaaadd48f0}\n#6  0x0000aaaaaaac3134 in repo_config (repo=0xaaaaaadc9e70 <the_repo>,\nfn=0xaaaaaab645e4 <handle_config>, data=0xaaaaaadeeb70) at\nconfig.c:2300\nNo locals.\n#7  0x0000aaaaaab6537c in read_config (repo=0xaaaaaadc9e70 <the_repo>,\nearly=0) at remote.c:637\n        flag = 0\n#8  0x0000aaaaaab65b3c in remote_get (name=0xffffffffe465 \"repro\") at\nremote.c:823\nNo locals.\n#9  0x0000aaaaaaab2164 in cmd_main (argc=2, argv=0xffffffffde88) at\nremote-curl.c:1568\n        buf = {alloc = 0, len = 0, buf = 0xaaaaaadca368 <strbuf_slopbuf> \"\"}\n        nongit = 1\n        ret = 1\n#10 0x0000aaaaaaabc688 in main (argc=2, argv=0xffffffffde88) at common-main.c:9\n        result = 65535\n\nIt looks like the immediate crash is in `parse_refspec()`, where\n`the_hash_algo->hexsz` is dereferenced while\n`the_repository->hash_algo` is still NULL.\n\nBest,\nJo\n"},{"id":"539612","messageId":"20260321194653.24513-1-jayatheerthkulkarni2005@gmail.com","threadId":"65325","inReplyTo":"CAN=xy38zCRdOAnMtBXtRyUHE=+gtS8J6mwUWFQqxDAaBLAm7dA@mail.gmail.com","subject":"[PATCH] remote-curl: set fallback hash algorithm outside repo","fromName":"K Jayatheerth","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-21T19:46:53Z","receivedAt":"2026-03-21T19:47:28Z","isPatch":true,"body":"When a remote helper like git-remote-http is invoked outside of a\nrepository (for example, by running `git ls-remote -h <url>` in a\nnon-git directory), setup_git_directory_gently() leaves\nthe_repository->hash_algo as NULL.\n\nIf the user has a global fetch refspec configured, remote-curl\nattempts to parse this refspec during initialization. Inside\nparse_refspec(), it checks whether the LHS of the refspec is an\nexact OID by evaluating `llen == the_hash_algo->hexsz`. Because\nthe_hash_algo is NULL, this results in a segmentation fault.\n\nFix this by mirroring the behavior of Git's main built-ins. If\nremote-curl is operating outside a repository, initialize a\nfallback hash algorithm (SHA-1) so that refspec parsing can\nsafely check hexadecimal lengths.\n\nAlso add a test in t5551 to ensure this regression does not\nhappen again. The test uses GIT_CEILING_DIRECTORIES to ensure\nthe command genuinely runs in a nongit environment without\nfalling back to the test suite's trash directory repository.\n\nReported-by: Jo Liss <joliss@gmail.com>\nSigned-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n---\nWhile the fix was tricky to find\nI believe it is a small one.\nThe debug Jo did here helped me find it faster than I would've.\nI hope the test I added is in the right file, I had multiple options, but\nlooking at other test files this seemed a fair option.\n\n remote-curl.c               |  4 ++++\n t/t5551-http-fetch-smart.sh | 15 +++++++++++++++\n 2 files changed, 19 insertions(+)\n\ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..4c85e6b079 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -1547,6 +1547,10 @@ int cmd_main(int argc, const char **argv)\n \tint ret = 1;\n \n \tsetup_git_directory_gently(&nongit);\n+\n+\tif (nongit && !the_repository->hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (argc < 2) {\n \t\terror(_(\"remote-curl: usage: git remote-curl <remote> [<url>]\"));\n \t\tgoto cleanup;\ndiff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh\nindex 73cf531580..ed81e6b49b 100755\n--- a/t/t5551-http-fetch-smart.sh\n+++ b/t/t5551-http-fetch-smart.sh\n@@ -782,4 +782,19 @@ test_expect_success 'tag following always works over v0 http' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir nongit &&\n+\t(\n+\t\tcd nongit &&\n+\t\tenv GIT_CONFIG_NOSYSTEM=1 \\\n+\t\t\tGIT_CONFIG_GLOBAL=/dev/null \\\n+\t\t\tGIT_CONFIG_COUNT=1 \\\n+\t\t\tGIT_CONFIG_KEY_0=remote.origin.fetch \\\n+\t\t\tGIT_CONFIG_VALUE_0=\"+refs/tags/*:refs/tags/*\" \\\n+\t\t\tgit ls-remote \"$HTTPD_URL/smart/repo.git\"\n+\t)\n+'\n+\n test_done\n-- \n2.53.0\n"},{"id":"539614","messageId":"20260321210602.GA736981@coredump.intra.peff.net","threadId":"65325","inReplyTo":"CAN=xy38zCRdOAnMtBXtRyUHE=+gtS8J6mwUWFQqxDAaBLAm7dA@mail.gmail.com","subject":"Re: remote-curl: segfault parsing remote.<name>.fetch outside a repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-03-21T21:06:02Z","receivedAt":"2026-03-21T21:06:04Z","isPatch":false,"body":"On Sat, Mar 21, 2026 at 07:11:18PM +0000, Jo Liss wrote:\n\n> I ran into a bug and thought I'd report it! The following command\n> segfaults for me (where ~/src/git is my clone):\n> \n> env -C / \\\n>     GIT_CONFIG_NOSYSTEM=1 \\\n>     GIT_CONFIG_GLOBAL=/dev/null \\\n>     GIT_CONFIG_COUNT=1 \\\n>     GIT_CONFIG_KEY_0=remote.repro.fetch \\\n>     GIT_CONFIG_VALUE_0='+refs/tags/*:refs/tags/*' \\\n>     ~/src/git/git-remote-http repro\n> \n> In other words, this is happening when the shared remote-curl code\n> (here, git-remote-http) is called outside of any repository, while\n> `remote.<name>.fetch` is set.\n> \n> I can reproduce this on Ubuntu and macOS, with git master\n> (7ff1e8dc1e16) and git 2.51.0.\n\nThis is another fallout from c8aed5e8da (repository: stop setting SHA1\nas the default object hash, 2024-05-07).\n\nIt's a curious case, though. The crashing code is parse_refspec() does\nthis:\n\n  if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n        item->exact_sha1 = 1; /* ok */\n\nBut what is the correct hash algo to use here when we are outside a\nrepository? Usually remote-curl tries to detect the hash algorithm in\nuse by the other side (based on its info/refs response). But we don't\ncontact the other side until we've run remote_get(), and the refspec\nparsing is happening via that remote_get().\n\nIn this particular case, the origin refspecs are not even going to be\nused, but you can construct a similar one where they are:\n\n  git -C / \\\n      -c remote.foo.url=https://github.com/git/git \\\n      -c remote.foo.fetch=whatever \\\n      ls-remote foo\n\nWe could do this:\n\ndiff --git a/refspec.c b/refspec.c\nindex 0775358d96..e6c29b7dd0 100644\n--- a/refspec.c\n+++ b/refspec.c\n@@ -101,7 +101,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\t/* LHS */\n \t\tif (!*item->src)\n \t\t\t; /* empty is ok; it means \"HEAD\" */\n-\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n+\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n \t\t\titem->exact_sha1 = 1; /* ok */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\n\nto make the segfault go away, but it is mostly papering over the\nproblem. I'm not sure if the exact_sha1 flag would matter when we are\nnot actually fetching (and we cannot fetch when we are not in a local\nrepo). Grepping around, it looks like it does influence the ref prefixes\nwe send to the other side (yet another chicken-and-egg!).\n\n-Peff\n"},{"id":"539620","messageId":"ab8lHBDvjTjatE9s@fruit.crustytoothpaste.net","threadId":"65325","inReplyTo":"20260321194653.24513-1-jayatheerthkulkarni2005@gmail.com","subject":"Re: [PATCH] remote-curl: set fallback hash algorithm outside repo","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-03-21T23:09:16Z","receivedAt":"2026-03-21T23:09:24Z","isPatch":true,"body":"On 2026-03-21 at 19:46:53, K Jayatheerth wrote:\n> diff --git a/remote-curl.c b/remote-curl.c\n> index 92e40bb682..4c85e6b079 100644\n> --- a/remote-curl.c\n> +++ b/remote-curl.c\n> @@ -1547,6 +1547,10 @@ int cmd_main(int argc, const char **argv)\n>  \tint ret = 1;\n>  \n>  \tsetup_git_directory_gently(&nongit);\n> +\n> +\tif (nongit && !the_repository->hash_algo)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n\nThis should be GIT_HASH_DEFAULT, which is whatever the default hash is.\n\nGIT_HASH_SHA1_LEGACY is for places where we assume SHA-1 because the\ndata format doesn't specify (e.g., v1 bundles) and GIT_HASH_SHA1 says,\n“The user or data format specifically chose SHA-1.”  The user didn't\nspecify any particular algorithm here (which is the problem), so we\nshould go with the default (which will change to SHA-256 in 3.0).\n\nThat being said, I also agree with Peff downthread that it might be\nbetter to fix this elsewhere,\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"539623","messageId":"xmqqa4w0acdr.fsf@gitster.g","threadId":"65325","inReplyTo":"20260321210602.GA736981@coredump.intra.peff.net","subject":"Re: remote-curl: segfault parsing remote.<name>.fetch outside a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-22T01:20:16Z","receivedAt":"2026-03-22T01:20:18Z","isPatch":false,"body":"Jeff King <peff@peff.net> writes:\n\n> It's a curious case, though. The crashing code is parse_refspec() does\n> this:\n>\n>   if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n>         item->exact_sha1 = 1; /* ok */\n>\n> But what is the correct hash algo to use here when we are outside a\n> repository?\n\nHmph, who is calling into the transport outside a repository in the\nfirst place?  Even \"git clone\" should create the receiving\nrepository before it calls into the transport, no?  Is this \"git\nls-remote\" or something?\n\n> In this particular case, the origin refspecs are not even going to be\n> used, but you can construct a similar one where they are:\n>\n>   git -C / \\\n>       -c remote.foo.url=https://github.com/git/git \\\n>       -c remote.foo.fetch=whatever \\\n>       ls-remote foo\n\nOK.\n\n> We could do this:\n>\n> diff --git a/refspec.c b/refspec.c\n> index 0775358d96..e6c29b7dd0 100644\n> --- a/refspec.c\n> +++ b/refspec.c\n> @@ -101,7 +101,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n>  \t\t/* LHS */\n>  \t\tif (!*item->src)\n>  \t\t\t; /* empty is ok; it means \"HEAD\" */\n> -\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n> +\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n>  \t\t\titem->exact_sha1 = 1; /* ok */\n>  \t\telse if (!check_refname_format(item->src, flags))\n>  \t\t\t; /* valid looking ref is ok */\n>\n> to make the segfault go away, but it is mostly papering over the\n> problem. I'm not sure if the exact_sha1 flag would matter when we are\n> not actually fetching (and we cannot fetch when we are not in a local\n> repo). Grepping around, it looks like it does influence the ref prefixes\n> we send to the other side (yet another chicken-and-egg!).\n\nYup, I agree with your assessment that exact_sha1 should mostly be\ngarbage if we do not have a repository in the first place.\n"},{"id":"539625","messageId":"20260322013744.GA816455@coredump.intra.peff.net","threadId":"65325","inReplyTo":"xmqqa4w0acdr.fsf@gitster.g","subject":"Re: remote-curl: segfault parsing remote.<name>.fetch outside a repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-03-22T01:37:44Z","receivedAt":"2026-03-22T01:37:46Z","isPatch":false,"body":"On Sat, Mar 21, 2026 at 06:20:16PM -0700, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > It's a curious case, though. The crashing code is parse_refspec() does\n> > this:\n> >\n> >   if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n> >         item->exact_sha1 = 1; /* ok */\n> >\n> > But what is the correct hash algo to use here when we are outside a\n> > repository?\n> \n> Hmph, who is calling into the transport outside a repository in the\n> first place?  Even \"git clone\" should create the receiving\n> repository before it calls into the transport, no?  Is this \"git\n> ls-remote\" or something?\n\nYes, exactly; the real-world case that Jo mentioned is ls-remote.\n\n> > to make the segfault go away, but it is mostly papering over the\n> > problem. I'm not sure if the exact_sha1 flag would matter when we are\n> > not actually fetching (and we cannot fetch when we are not in a local\n> > repo). Grepping around, it looks like it does influence the ref prefixes\n> > we send to the other side (yet another chicken-and-egg!).\n> \n> Yup, I agree with your assessment that exact_sha1 should mostly be\n> garbage if we do not have a repository in the first place.\n\nThere's at least one more instance of the same problem:\n\n          if (item->negative)\n\t\t...\n                  else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n                          return 0; /* negative refpsecs cannot be exact sha1 */\n\nIt might be OK to quietly disable the check outside a repo there, too.\n\n-Peff\n"},{"id":"539629","messageId":"20260322023557.15907-1-jayatheerthkulkarni2005@gmail.com","threadId":"65325","inReplyTo":"20260321194653.24513-1-jayatheerthkulkarni2005@gmail.com","subject":"[PATCH v2] refspec: safely parse refspecs outside a repository","fromName":"K Jayatheerth","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-22T02:35:57Z","receivedAt":"2026-03-22T02:36:25Z","isPatch":true,"body":"When a remote helper like git-remote-http is invoked outside of a\nrepository (for example, by running `git ls-remote -h <url>` in a\nnon-git directory), `the_hash_algo` is left uninitialized (NULL).\n\nIf a user has a global fetch refspec configured, `parse_refspec()`\nattempts to check if the LHS of the refspec is an exact OID by\nevaluating `llen == the_hash_algo->hexsz`. Because `the_hash_algo`\nis NULL, this results in a segmentation fault. This crash occurs for\nboth standard and negative refspecs.\n\nFix this by ensuring `the_hash_algo` is non-NULL before checking\n`the_hash_algo->hexsz` for both standard and negative refspecs.\nWhen operating outside a repository, fetching is impossible,\nso bypassing the exact OID check is the cleanest approach.\n\nAdditionally, while looking into the remote-curl execution path,\ntake the opportunity to remove an unused `#include \"git-curl-compat.h\"`\nfrom `remote-curl.c`.\n\nReported-by: Jo Liss <joliss@gmail.com>\nHelped-by: Jeff King <peff@peff.net>\nSigned-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n---\nChanges in v2:\nInstead of adding a fix by giving a default hash like we did in cmd_apply()\nI understood that it is impossible to fetch here.\nTherefore I picked up whatever Peff suggested here.\nSince I got no feedback on the test, I am assuming it is correct and leaving as is.\n\n refspec.c                   |  4 ++--\n remote-curl.c               |  1 -\n t/t5551-http-fetch-smart.sh | 15 +++++++++++++++\n 3 files changed, 17 insertions(+), 3 deletions(-)\n\ndiff --git a/refspec.c b/refspec.c\nindex 0775358d96..a864a0bac2 100644\n--- a/refspec.c\n+++ b/refspec.c\n@@ -84,7 +84,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\t */\n \t\tif (!*item->src)\n \t\t\treturn 0; /* negative refspecs must not be empty */\n-\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n+\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n \t\t\treturn 0; /* negative refpsecs cannot be exact sha1 */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\n@@ -101,7 +101,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\t/* LHS */\n \t\tif (!*item->src)\n \t\t\t; /* empty is ok; it means \"HEAD\" */\n-\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n+\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n \t\t\titem->exact_sha1 = 1; /* ok */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..280880e54e 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -2,7 +2,6 @@\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n-#include \"git-curl-compat.h\"\n #include \"config.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh\nindex 73cf531580..ed81e6b49b 100755\n--- a/t/t5551-http-fetch-smart.sh\n+++ b/t/t5551-http-fetch-smart.sh\n@@ -782,4 +782,19 @@ test_expect_success 'tag following always works over v0 http' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir nongit &&\n+\t(\n+\t\tcd nongit &&\n+\t\tenv GIT_CONFIG_NOSYSTEM=1 \\\n+\t\t\tGIT_CONFIG_GLOBAL=/dev/null \\\n+\t\t\tGIT_CONFIG_COUNT=1 \\\n+\t\t\tGIT_CONFIG_KEY_0=remote.origin.fetch \\\n+\t\t\tGIT_CONFIG_VALUE_0=\"+refs/tags/*:refs/tags/*\" \\\n+\t\t\tgit ls-remote \"$HTTPD_URL/smart/repo.git\"\n+\t)\n+'\n+\n test_done\n-- \n2.53.0\n"},{"id":"539631","messageId":"87qzpck0ar.fsf@gitster.g","threadId":"65325","inReplyTo":"20260322023557.15907-1-jayatheerthkulkarni2005@gmail.com","subject":"Re: [PATCH v2] refspec: safely parse refspecs outside a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-22T03:31:08Z","receivedAt":"2026-03-22T03:31:13Z","isPatch":true,"body":"K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:\n\n> Additionally, while looking into the remote-curl execution path,\n> take the opportunity to remove an unused `#include \"git-curl-compat.h\"`\n> from `remote-curl.c`.\n\nI wish you didn't do this in the same patch.  It is completely\nunrelated, isn't it?\n\n>  refspec.c                   |  4 ++--\n>  remote-curl.c               |  1 -\n>  t/t5551-http-fetch-smart.sh | 15 +++++++++++++++\n>  3 files changed, 17 insertions(+), 3 deletions(-)\n\n\n\n> +test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n> +\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n> +\texport GIT_CEILING_DIRECTORIES &&\n> +\tmkdir nongit &&\n> +\t(\n> +\t\tcd nongit &&\n> +\t\tenv GIT_CONFIG_NOSYSTEM=1 \\\n> +\t\t\tGIT_CONFIG_GLOBAL=/dev/null \\\n> +\t\t\tGIT_CONFIG_COUNT=1 \\\n> +\t\t\tGIT_CONFIG_KEY_0=remote.origin.fetch \\\n> +\t\t\tGIT_CONFIG_VALUE_0=\"+refs/tags/*:refs/tags/*\" \\\n> +\t\t\tgit ls-remote \"$HTTPD_URL/smart/repo.git\"\n\n\nThis complex \"env\" dance is probably uncalled for.  Wouldn't\nsomething like\n\n\tmkdir nongit &&\n\tgit -C nongit -c remote.origin.fetch=+refs/*:refs/* \\\n\t\tls-remote \"$HTTPD_URL/smart/repo.git\"\n\nbe sufficient?\n"},{"id":"539632","messageId":"20260322035338.GA819989@coredump.intra.peff.net","threadId":"65325","inReplyTo":"20260322023557.15907-1-jayatheerthkulkarni2005@gmail.com","subject":"Re: [PATCH v2] refspec: safely parse refspecs outside a repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-03-22T03:53:38Z","receivedAt":"2026-03-22T03:53:40Z","isPatch":true,"body":"On Sun, Mar 22, 2026 at 08:05:57AM +0530, K Jayatheerth wrote:\n\n> Fix this by ensuring `the_hash_algo` is non-NULL before checking\n> `the_hash_algo->hexsz` for both standard and negative refspecs.\n> When operating outside a repository, fetching is impossible,\n> so bypassing the exact OID check is the cleanest approach.\n\nThis argument is glossing over some details. Trying to break down all of\nthe implications, I think we have:\n\n  - Without knowing the hash algo, we cannot reject negative refspecs\n    that look like oids. This is OK in practice for two reasons. One,\n    the only commands which apply refspecs are fetch and push, and they\n    require a repository. And two, while we miss an opportunity to\n    complain about broken config, it is quite unlikely for somebody to\n    have such config (a global-level configured negative refspec that\n    looks like an oid). And they will be told about it when running an\n    actual fetch anyway.\n\n  - Without knowing the hash algo, we cannot mark refspecs with the\n    exact_sha1 flag. Again, we are not actually applying any refspecs\n    unless we have a repo. The exact_sha1 flag is used to influence the\n    set of prefixes we send to a remote v2 upload-pack process, but\n    only for fetch (which requires a repository). For ls-remote, which\n    can run outside a repo, we don't even look at the refspecs.\n\nAnd so for those reasons it's probably OK to quietly ignore things.\nStill, it rubs me the wrong way a little that we might create a subtle\nbug from some other caller.\n\nIf we think we don't care about refspecs, it kind of makes me wonder if\nwe ought to be able to tell the remote API that we are interested in\nremotes for their URLs only, and _not_ for their refspecs. But maybe\nthat leads to madness, as we end up with half-initialized \"struct\nremote\"s floating around our process.\n\n\nThe other thing I wondered is why we are talking about remote-curl here,\nand not ls-remote. And that's because ls-remote already hacked around\nthis!\n\nCheck out 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside of a\nrepo, 2024-08-02), which adds this:\n\n          /*\n           * TODO: This is buggy, but required for transport helpers. When a\n           * transport helper advertises a \"refspec\", then we'd add that to a\n           * list of refspecs via `refspec_append()`, which transitively depends\n           * on `the_hash_algo`. Thus, when the hash algorithm isn't properly set\n           * up, this would lead to a segfault.\n           *\n           * We really should fix this in the transport helper logic such that we\n           * lazily parse refspec capabilities _after_ we have learned about the\n           * remote's object format. Otherwise, we may end up misparsing refspecs\n           * depending on what object hash the remote uses.\n           */\n          if (!the_repository->hash_algo)\n                  repo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);\n\nObviously that is kicking the can down the road, but it kind of makes\nsense that we would have the same hack in place for remote-curl (which\nin practice is only going to be called out-of-repo by ls-remote anyway).\nIt is only the fact that it happens in a separate process that the\nexisting fix from 9e89dcb66a is not helping us.\n\n> Additionally, while looking into the remote-curl execution path,\n> take the opportunity to remove an unused `#include \"git-curl-compat.h\"`\n> from `remote-curl.c`.\n\nI doubt this is correct.\n\nremote-curl checks GIT_CURL_NEED_TRANSFER_ENCODING_HEADER, which is\ndefined in git-curl-compat.h. It may work fine without that header if\nyou have a recent version of curl, but older systems would be subtly\nbroken.\n\n> +test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n> +\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n> +\texport GIT_CEILING_DIRECTORIES &&\n> +\tmkdir nongit &&\n> +\t(\n> +\t\tcd nongit &&\n> +\t\tenv GIT_CONFIG_NOSYSTEM=1 \\\n> +\t\t\tGIT_CONFIG_GLOBAL=/dev/null \\\n> +\t\t\tGIT_CONFIG_COUNT=1 \\\n> +\t\t\tGIT_CONFIG_KEY_0=remote.origin.fetch \\\n> +\t\t\tGIT_CONFIG_VALUE_0=\"+refs/tags/*:refs/tags/*\" \\\n> +\t\t\tgit ls-remote \"$HTTPD_URL/smart/repo.git\"\n> +\t)\n> +'\n\nSome of this is irrelevant to reproducing the bug (like redirecting\nsystem and global config). And it is much easier to use \"git -c\" to set\ntemporary config.\n\nWe also have a \"nongit\" helper function already. So I think just:\n\n   nongit git \\\n          -c remote.origin.fetch=anything \\\n          ls-remote \"$HTTPD_URL/smart/repo.git\"\n\nis enough to trigger it. Possibly it is slightly more realistic to\nactually use the remote whose refspecs we are configuring:\n\n  nongit git \\\n         -c remote.origin.url=\"$HTTPD_URL/smart/repo.git\" \\\n\t -c remote.origin.fetch=anything \\\n\t ls-remote origin\n\nbut as the bug exists now, either is sufficient to trigger it. You could\nalso add a negative refspec if you want to test that half of the change.\n\n-Peff\n"},{"id":"539634","messageId":"20260322053617.38951-1-jayatheerthkulkarni2005@gmail.com","threadId":"65325","inReplyTo":"20260322023557.15907-1-jayatheerthkulkarni2005@gmail.com","subject":"[PATCH v3 1/2] refspec: safely parse refspecs outside a repository","fromName":"K Jayatheerth","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-22T05:36:16Z","receivedAt":"2026-03-22T05:37:42Z","isPatch":true,"body":"When git-remote-http is invoked outside of a repository (for example,\nby running `git ls-remote` in a non-git directory with a globally\nconfigured fetch refspec), `the_hash_algo` is left as NULL by\nsetup_git_directory_gently().\n\nparse_refspec() checks whether the LHS of a refspec is an exact OID by\nevaluating `llen == the_hash_algo->hexsz`. With `the_hash_algo` being\nNULL, this results in a segmentation fault. The same NULL dereference\nexists in the negative refspec path.\n\nNote that builtin/ls-remote already works around a related issue by\nsetting a fallback hash algorithm before calling into the transport\nlayer (see 9e89dcb66a). However, since remote-curl runs as a separate\nprocess, that fix does not help here.\n\nGuard both dereferences with a NULL check on `the_hash_algo`. When\noperating outside a repository, fetching and pushing are impossible\nanyway, so skipping the exact OID check is safe: the exact_sha1 flag\nonly influences ref prefixes sent to a remote v2 upload-pack during\nfetch, and we will never reach that point without a local repository.\n\nReported-by: Jo Liss <joliss@gmail.com>\nHelped-by: Jeff King <peff@peff.net>\nSigned-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n---\n refspec.c                   | 4 ++--\n t/t5551-http-fetch-smart.sh | 7 +++++++\n 2 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/refspec.c b/refspec.c\nindex 0775358d96..a864a0bac2 100644\n--- a/refspec.c\n+++ b/refspec.c\n@@ -84,7 +84,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\t */\n \t\tif (!*item->src)\n \t\t\treturn 0; /* negative refspecs must not be empty */\n-\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n+\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n \t\t\treturn 0; /* negative refpsecs cannot be exact sha1 */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\n@@ -101,7 +101,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\t/* LHS */\n \t\tif (!*item->src)\n \t\t\t; /* empty is ok; it means \"HEAD\" */\n-\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n+\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n \t\t\titem->exact_sha1 = 1; /* ok */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\ndiff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh\nindex 73cf531580..a26b6c2844 100755\n--- a/t/t5551-http-fetch-smart.sh\n+++ b/t/t5551-http-fetch-smart.sh\n@@ -782,4 +782,11 @@ test_expect_success 'tag following always works over v0 http' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n+\tnongit git \\\n+\t\t-c remote.origin.url=\"$HTTPD_URL/smart/repo.git\" \\\n+\t\t-c remote.origin.fetch=anything \\\n+\t\tls-remote origin\n+'\n+\n test_done\n-- \n2.53.0\n\n"},{"id":"539635","messageId":"20260322053617.38951-2-jayatheerthkulkarni2005@gmail.com","threadId":"65325","inReplyTo":"20260322053617.38951-1-jayatheerthkulkarni2005@gmail.com","subject":"[PATCH v3 2/2] refspec: fix typo in comment","fromName":"K Jayatheerth","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-22T05:36:17Z","receivedAt":"2026-03-22T05:38:14Z","isPatch":true,"body":"Fix a long-standing typo in a comment: \"refpsecs\" -> \"refspecs\".\n\nSigned-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n---\n refspec.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/refspec.c b/refspec.c\nindex a864a0bac2..a0c9edfbea 100644\n--- a/refspec.c\n+++ b/refspec.c\n@@ -85,7 +85,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\tif (!*item->src)\n \t\t\treturn 0; /* negative refspecs must not be empty */\n \t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n-\t\t\treturn 0; /* negative refpsecs cannot be exact sha1 */\n+\t\t\treturn 0; /* negative refspecs cannot be exact sha1 */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\n \t\telse\n-- \n2.53.0\n\n"},{"id":"539788","messageId":"xmqq341q41wu.fsf@gitster.g","threadId":"65325","inReplyTo":"20260322053617.38951-1-jayatheerthkulkarni2005@gmail.com","subject":"Re: [PATCH v3 1/2] refspec: safely parse refspecs outside a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-23T22:27:29Z","receivedAt":"2026-03-23T22:27:31Z","isPatch":true,"body":"K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:\n\n> When git-remote-http is invoked outside of a repository (for example,\n> by running `git ls-remote` in a non-git directory with a globally\n> configured fetch refspec), `the_hash_algo` is left as NULL by\n> setup_git_directory_gently().\n>\n> parse_refspec() checks whether the LHS of a refspec is an exact OID by\n> evaluating `llen == the_hash_algo->hexsz`. With `the_hash_algo` being\n> NULL, this results in a segmentation fault. The same NULL dereference\n> exists in the negative refspec path.\n>\n> Note that builtin/ls-remote already works around a related issue by\n> setting a fallback hash algorithm before calling into the transport\n> layer (see 9e89dcb66a). However, since remote-curl runs as a separate\n> process, that fix does not help here.\n>\n> Guard both dereferences with a NULL check on `the_hash_algo`. When\n> operating outside a repository, fetching and pushing are impossible\n> anyway, so skipping the exact OID check is safe: the exact_sha1 flag\n> only influences ref prefixes sent to a remote v2 upload-pack during\n> fetch, and we will never reach that point without a local repository.\n>\n> Reported-by: Jo Liss <joliss@gmail.com>\n> Helped-by: Jeff King <peff@peff.net>\n> Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n> ---\n>  refspec.c                   | 4 ++--\n>  t/t5551-http-fetch-smart.sh | 7 +++++++\n>  2 files changed, 9 insertions(+), 2 deletions(-)\n\nLooking good.  Shall we declare victory and mark the topic for\n'next' by now?\n\nThanks.\n\n> diff --git a/refspec.c b/refspec.c\n> index 0775358d96..a864a0bac2 100644\n> --- a/refspec.c\n> +++ b/refspec.c\n> @@ -84,7 +84,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n>  \t\t */\n>  \t\tif (!*item->src)\n>  \t\t\treturn 0; /* negative refspecs must not be empty */\n> -\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n> +\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n>  \t\t\treturn 0; /* negative refpsecs cannot be exact sha1 */\n>  \t\telse if (!check_refname_format(item->src, flags))\n>  \t\t\t; /* valid looking ref is ok */\n> @@ -101,7 +101,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n>  \t\t/* LHS */\n>  \t\tif (!*item->src)\n>  \t\t\t; /* empty is ok; it means \"HEAD\" */\n> -\t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n> +\t\telse if (the_hash_algo && llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n>  \t\t\titem->exact_sha1 = 1; /* ok */\n>  \t\telse if (!check_refname_format(item->src, flags))\n>  \t\t\t; /* valid looking ref is ok */\n> diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh\n> index 73cf531580..a26b6c2844 100755\n> --- a/t/t5551-http-fetch-smart.sh\n> +++ b/t/t5551-http-fetch-smart.sh\n> @@ -782,4 +782,11 @@ test_expect_success 'tag following always works over v0 http' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n> +\tnongit git \\\n> +\t\t-c remote.origin.url=\"$HTTPD_URL/smart/repo.git\" \\\n> +\t\t-c remote.origin.fetch=anything \\\n> +\t\tls-remote origin\n> +'\n> +\n>  test_done\n"},{"id":"539790","messageId":"20260323231049.GA23721@coredump.intra.peff.net","threadId":"65325","inReplyTo":"xmqq341q41wu.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] refspec: safely parse refspecs outside a repository","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-03-23T23:10:49Z","receivedAt":"2026-03-23T23:10:57Z","isPatch":true,"body":"On Mon, Mar 23, 2026 at 03:27:29PM -0700, Junio C Hamano wrote:\n\n> Looking good.  Shall we declare victory and mark the topic for\n> 'next' by now?\n\nI'm not entirely convinced the better solution isn't just:\n\ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..60774af929 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -1552,6 +1552,11 @@ int cmd_main(int argc, const char **argv)\n \t\tgoto cleanup;\n \t}\n \n+\t/* yuck, see 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside\n+\t * of a repo, 2024-08-02) */\n+\tif (nongit)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);\n+\n \toptions.verbosity = 1;\n \toptions.progress = !!isatty(2);\n \toptions.thin = 1;\n\nThat would make the http transport consistent with non-http ones (or at\nleast any that execute in-process within ls-remote).\n\nOr alternatively, if we think that this use of parse_refspec() is the\nonly remaining spot for which ls-remote needs a fallback, then we could\napply the patch here and then revert 9e89dcb66a.\n\n-Peff\n"},{"id":"539791","messageId":"xmqqse9q2k0t.fsf@gitster.g","threadId":"65325","inReplyTo":"20260323231049.GA23721@coredump.intra.peff.net","subject":"Re: [PATCH v3 1/2] refspec: safely parse refspecs outside a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-23T23:39:14Z","receivedAt":"2026-03-23T23:39:17Z","isPatch":true,"body":"Jeff King <peff@peff.net> writes:\n\n> On Mon, Mar 23, 2026 at 03:27:29PM -0700, Junio C Hamano wrote:\n>\n>> Looking good.  Shall we declare victory and mark the topic for\n>> 'next' by now?\n>\n> I'm not entirely convinced the better solution isn't just:\n>\n> diff --git a/remote-curl.c b/remote-curl.c\n> index 92e40bb682..60774af929 100644\n> --- a/remote-curl.c\n> +++ b/remote-curl.c\n> @@ -1552,6 +1552,11 @@ int cmd_main(int argc, const char **argv)\n>  \t\tgoto cleanup;\n>  \t}\n>  \n> +\t/* yuck, see 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside\n> +\t * of a repo, 2024-08-02) */\n> +\tif (nongit)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);\n> +\n>  \toptions.verbosity = 1;\n>  \toptions.progress = !!isatty(2);\n>  \toptions.thin = 1;\n>\n> That would make the http transport consistent with non-http ones (or at\n> least any that execute in-process within ls-remote).\n\nAh, yes, I like this much better.\n\nThanks.\n\n"},{"id":"539797","messageId":"20260324015734.18470-1-jayatheerthkulkarni2005@gmail.com","threadId":"65325","inReplyTo":"20260322023557.15907-1-jayatheerthkulkarni2005@gmail.com","subject":"[PATCH v4 1/2] remote-curl: fall back to default hash outside repo","fromName":"K Jayatheerth","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-24T01:57:33Z","receivedAt":"2026-03-24T01:58:39Z","isPatch":true,"body":"When a remote helper like git-remote-http is invoked outside of a\nrepository (for example, by running git ls-remote in a non-git\ndirectory), setup_git_directory_gently() leaves the_hash_algo\nuninitialized as NULL.\n\nIf the user has a globally configured fetch refspec, remote-curl\nattempts to parse it during initialization. Inside parse_refspec(),\nit checks whether the LHS of the refspec is an exact OID by evaluating\nllen == the_hash_algo->hexsz. Because the_hash_algo is NULL, this\nresults in a segmentation fault.\n\nIn 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside of a repo,\n2024-08-02), we added a workaround to ls-remote to fall back to the\ndefault hash algorithm to prevent exactly this type of crash when\nparsing refspec capabilities. However, because remote-curl runs as a\nseparate process, it does not inherit that fallback and crashes anyway.\n\nInstead of pushing a NULL-guard workaround down into parse_refspec(),\nfix this by mirroring the ls-remote workaround directly in\nremote-curl.c. If we are operating outside a repository, initialize\nthe_hash_algo to GIT_HASH_DEFAULT. This keeps the HTTP transport\nconsistent with non-HTTP transports that execute in-process, preventing\ncrashes without altering the generic refspec parsing logic.\n\nReported-by: Jo Liss <joliss@gmail.com>\nHelped-by: Jeff King <peff@peff.net>\nSigned-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n---\nThanks Peff and Junio this has been informative.\nI understood a lot of things here.\n\n remote-curl.c               | 5 +++++\n t/t5551-http-fetch-smart.sh | 7 +++++++\n 2 files changed, 12 insertions(+)\n\ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..60774af929 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -1552,6 +1552,11 @@ int cmd_main(int argc, const char **argv)\n \t\tgoto cleanup;\n \t}\n \n+\t/* yuck, see 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside\n+\t * of a repo, 2024-08-02) */\n+\tif (nongit)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);\n+\n \toptions.verbosity = 1;\n \toptions.progress = !!isatty(2);\n \toptions.thin = 1;\ndiff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh\nindex 73cf531580..a26b6c2844 100755\n--- a/t/t5551-http-fetch-smart.sh\n+++ b/t/t5551-http-fetch-smart.sh\n@@ -782,4 +782,11 @@ test_expect_success 'tag following always works over v0 http' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n+\tnongit git \\\n+\t\t-c remote.origin.url=\"$HTTPD_URL/smart/repo.git\" \\\n+\t\t-c remote.origin.fetch=anything \\\n+\t\tls-remote origin\n+'\n+\n test_done\n-- \n2.53.0\n"},{"id":"539798","messageId":"20260324015734.18470-2-jayatheerthkulkarni2005@gmail.com","threadId":"65325","inReplyTo":"20260324015734.18470-1-jayatheerthkulkarni2005@gmail.com","subject":"[PATCH v4 2/2] refspec: fix typo in comment","fromName":"K Jayatheerth","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-24T01:57:34Z","receivedAt":"2026-03-24T01:58:54Z","isPatch":true,"body":"Fix a long-standing typo in a comment: \"refpsecs\" -> \"refspecs\".\n\nSigned-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n---\n refspec.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/refspec.c b/refspec.c\nindex 0775358d96..fb89bce1db 100644\n--- a/refspec.c\n+++ b/refspec.c\n@@ -85,7 +85,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet\n \t\tif (!*item->src)\n \t\t\treturn 0; /* negative refspecs must not be empty */\n \t\telse if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))\n-\t\t\treturn 0; /* negative refpsecs cannot be exact sha1 */\n+\t\t\treturn 0; /* negative refspecs cannot be exact sha1 */\n \t\telse if (!check_refname_format(item->src, flags))\n \t\t\t; /* valid looking ref is ok */\n \t\telse\n-- \n2.53.0\n\n"},{"id":"539802","messageId":"xmqqfr5p3lbe.fsf@gitster.g","threadId":"65325","inReplyTo":"20260324015734.18470-1-jayatheerthkulkarni2005@gmail.com","subject":"Re: [PATCH v4 1/2] remote-curl: fall back to default hash outside repo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-24T04:25:57Z","receivedAt":"2026-03-24T04:26:00Z","isPatch":true,"body":"K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:\n\n> Instead of pushing a NULL-guard workaround down into parse_refspec(),\n> fix this by mirroring the ls-remote workaround directly in\n> remote-curl.c. If we are operating outside a repository, initialize\n> the_hash_algo to GIT_HASH_DEFAULT. This keeps the HTTP transport\n> consistent with non-HTTP transports that execute in-process, preventing\n> crashes without altering the generic refspec parsing logic.\n\nThanks.\n\n>\n> Reported-by: Jo Liss <joliss@gmail.com>\n> Helped-by: Jeff King <peff@peff.net>\n> Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>\n> ---\n> Thanks Peff and Junio this has been informative.\n> I understood a lot of things here.\n>\n>  remote-curl.c               | 5 +++++\n>  t/t5551-http-fetch-smart.sh | 7 +++++++\n>  2 files changed, 12 insertions(+)\n>\n> diff --git a/remote-curl.c b/remote-curl.c\n> index 92e40bb682..60774af929 100644\n> --- a/remote-curl.c\n> +++ b/remote-curl.c\n> @@ -1552,6 +1552,11 @@ int cmd_main(int argc, const char **argv)\n>  \t\tgoto cleanup;\n>  \t}\n>  \n> +\t/* yuck, see 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside\n> +\t * of a repo, 2024-08-02) */\n> +\tif (nongit)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);\n> +\n>  \toptions.verbosity = 1;\n>  \toptions.progress = !!isatty(2);\n>  \toptions.thin = 1;\n> diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh\n> index 73cf531580..a26b6c2844 100755\n> --- a/t/t5551-http-fetch-smart.sh\n> +++ b/t/t5551-http-fetch-smart.sh\n> @@ -782,4 +782,11 @@ test_expect_success 'tag following always works over v0 http' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '\n> +\tnongit git \\\n> +\t\t-c remote.origin.url=\"$HTTPD_URL/smart/repo.git\" \\\n> +\t\t-c remote.origin.fetch=anything \\\n> +\t\tls-remote origin\n> +'\n> +\n>  test_done\n"}]}