{"thread":{"id":"61463","subject":"[PATCH 0/2] Fix use of uninitialized hash algos","startedAt":"2024-05-13T07:15:10Z","lastAt":"2024-05-22T04:51:52Z","messageCount":62,"participants":["Patrick Steinhardt","Junio C Hamano","Kyle Lippincott"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"494564","messageId":"cover.1715582857.git.ps@pks.im","threadId":"61463","inReplyTo":null,"subject":"[PATCH 0/2] Fix use of uninitialized hash algos","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-13T07:15:04Z","receivedAt":"2024-05-13T07:15:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nwith c8aed5e8da (repository: stop setting SHA1 as the default object\nhash, 2024-05-07), we have stopped setting up the default hash function\nfor `the_repository`. This change was done so that we stop implicitly\nusing SHA1 in places where we don't really intend to. Instead, code\nwhere we try to access `the_hash_algo` without having `the_repository`\nproperly initialized will now crash hard.\n\nI have found two more cases where this can now be triggered:\n\n  - git-patch-id(1) can read diffs from stdin.\n\n  - git-hash-object(1) can hash data from stdin.\n\nBoth cases can work without a repository, and if they don't have one\nthey will now crash.\n\nI still consider it a good thing that we did the change regardless of\nthose crashes. In the case of git-patch-id(1) I would claim that using\n`the_hash_algo` is wrong in the first place, as patch IDs should be\nstable and are documented to always use SHA1. Thus, patch IDs in SHA256\nrepos are essentially broken. And in the case of git-hash-object(1), we\nshould expose a command line option to let the user specify the object\nhash. So both cases demonstrate that there is room for improvement.\n\nIf these cases keep on popping up and we don't feel comfortable with it,\nthen we can still decide to drop c8aed5e8da. The remainder of the topic\nthat this commit was part of should in that case stay though, as those\nare real bug fixes. We could then re-try in a subsequent release cycle.\nBut for now I don't think this would be warranted yet.\n\nThis topic depends on js/ps/undecided-is-not-necessarily-sha1 at\nc8aed5e8da (repository: stop setting SHA1 as the default object hash,\n2024-05-07).\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (2):\n  builtin/patch-id: fix uninitialized hash function\n  builtin/hash-object: fix uninitialized hash function\n\n builtin/hash-object.c  |  7 +++++++\n builtin/patch-id.c     | 13 +++++++++++++\n t/t1007-hash-object.sh |  6 ++++++\n t/t4204-patch-id.sh    | 34 ++++++++++++++++++++++++++++++++++\n 4 files changed, 60 insertions(+)\n\n-- \n2.45.GIT\n\n"},{"id":"494565","messageId":"3200dcad2372fef3bcb4da599b44043bcf5b3692.1715582857.git.ps@pks.im","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"[PATCH 1/2] builtin/patch-id: fix uninitialized hash function","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-13T07:15:09Z","receivedAt":"2024-05-13T07:15:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In c8aed5e8da (repository: stop setting SHA1 as the default object hash,\n2024-05-07), we have adapted `initialize_repository()` to no longer set\nup a default hash function. As this function is also used to set up\n`the_repository`, the consequence is that `the_hash_algo` will now by\ndefault be a `NULL` pointer unless the hash algorithm was configured\nproperly. This is done as a mechanism to detect cases where we may be\nusing the wrong hash function by accident.\n\nThis change now causes git-patch-id(1) to segfault when it's run outside\nof a repository. As this command can read diffs from stdin, it does not\nnecessarily need a repository, but then relies on `the_hash_algo` to\ncompute the patch ID itself.\n\nIt is somewhat dubious that git-patch-id(1) relies on `the_hash_algo` in\nthe first place. Quoting its manpage:\n\n    A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs\n    associated with a patch, with line numbers ignored. As such, it’s\n    \"reasonably stable\", but at the same time also reasonably unique,\n    i.e., two patches that have the same \"patch ID\" are almost\n    guaranteed to be the same thing.\n\nWe explicitly document patch IDs to be using SHA-1. Furthermore, patch\nIDs are supposed to be stable for most of the part. But even with the\nsame input, the patch IDs will now be different depending on the repo's\nconfigured object hash.\n\nWork around the issue by setting up SHA-1 when there was no startup\nrepository for now. This is arguably not the correct fix, but for now we\nrather want to focus on getting the segfault fixed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/patch-id.c  | 13 +++++++++++++\n t/t4204-patch-id.sh | 34 ++++++++++++++++++++++++++++++++++\n 2 files changed, 47 insertions(+)\n\ndiff --git a/builtin/patch-id.c b/builtin/patch-id.c\nindex 3894d2b970..be5a85e71c 100644\n--- a/builtin/patch-id.c\n+++ b/builtin/patch-id.c\n@@ -5,6 +5,7 @@\n #include \"hash.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n+#include \"setup.h\"\n \n static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)\n {\n@@ -237,6 +238,18 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, builtin_patch_id_options,\n \t\t\t     patch_id_usage, 0);\n \n+\t/*\n+\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n+\t * it means that the hash algorithm now depends on the object hash of\n+\t * the repository, even though git-patch-id(1) clearly defines that\n+\t * patch IDs always use SHA1.\n+\t *\n+\t * TODO: This hack should be removed in favor of converting the code\n+\t *       that computes patch IDs to always use SHA1.\n+\t */\n+\tif (!startup_info->have_repository)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tgenerate_id_list(opts ? opts > 1 : config.stable,\n \t\t\t opts ? opts == 3 : config.verbatim);\n \treturn 0;\ndiff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh\nindex a7fa94ce0a..605faea0c7 100755\n--- a/t/t4204-patch-id.sh\n+++ b/t/t4204-patch-id.sh\n@@ -310,4 +310,38 @@ test_expect_success 'patch-id handles diffs with one line of before/after' '\n \ttest_config patchid.stable true &&\n \tcalc_patch_id diffu1stable <diffu1\n '\n+\n+test_expect_failure 'patch-id computes same ID with different object hashes' '\n+\ttest_when_finished \"rm -rf repo-sha1 repo-sha256\" &&\n+\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\n+\tgit init --object-format=sha1 repo-sha1 &&\n+\tgit -C repo-sha1 patch-id <diff >patch-id-sha1 &&\n+\tgit init --object-format=sha256 repo-sha256 &&\n+\tgit -C repo-sha256 patch-id <diff >patch-id-sha256 &&\n+\ttest_cmp patch-id-sha1 patch-id-sha256\n+'\n+\n+test_expect_success 'patch-id without repository' '\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\tnongit git patch-id <diff\n+'\n+\n test_done\n-- \n2.45.GIT\n\n"},{"id":"494566","messageId":"1e010f798ce50e51100bd46564a69ddbd31d29ea.1715582857.git.ps@pks.im","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"[PATCH 2/2] builtin/hash-object: fix uninitialized hash function","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-13T07:15:13Z","receivedAt":"2024-05-13T07:15:17Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The git-hash-object(1) command allows users to hash an object even\nwithout a repository. Starting with c8aed5e8da (repository: stop setting\nSHA1 as the default object hash, 2024-05-07), this will make us hit an\nuninitialized hash function, which subsequently leads to a segfault.\n\nFix this by falling back to SHA-1 explicitly when running outside of a\nGit repository. Eventually, we should expose this function as a command\nline option to the users so that they can pick which object hash to use\nby themselves.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/hash-object.c  | 7 +++++++\n t/t1007-hash-object.sh | 6 ++++++\n 2 files changed, 13 insertions(+)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex 82ca6d2bfd..0855f4f8aa 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -123,6 +123,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n \telse\n \t\tprefix = setup_git_directory_gently(&nongit);\n \n+\t/*\n+\t * TODO: Allow the hash algorithm to be configured by the user via a\n+\t *       command line option when not using `-w`.\n+\t */\n+\tif (nongit)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (vpath && prefix) {\n \t\tvpath_free = prefix_filename(prefix, vpath);\n \t\tvpath = vpath_free;\ndiff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh\nindex 64aea38486..4c138c6ca4 100755\n--- a/t/t1007-hash-object.sh\n+++ b/t/t1007-hash-object.sh\n@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '\n \techo example | git hash-object -t $t --literally --stdin\n '\n \n+test_expect_success '--stdin outside of repository' '\n+\tnongit git hash-object --stdin <hello >actual &&\n+\techo \"$(test_oid hello)\" >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.45.GIT\n\n"},{"id":"494636","messageId":"xmqqttj1hfb3.fsf@gitster.g","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"Re: [PATCH 0/2] Fix use of uninitialized hash algos","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T16:01:04Z","receivedAt":"2024-05-13T16:01:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> with c8aed5e8da (repository: stop setting SHA1 as the default object\n> hash, 2024-05-07), we have stopped setting up the default hash function\n> for `the_repository`. This change was done so that we stop implicitly\n> using SHA1 in places where we don't really intend to. Instead, code\n> where we try to access `the_hash_algo` without having `the_repository`\n> properly initialized will now crash hard.\n>\n> I have found two more cases where this can now be triggered:\n>\n>   - git-patch-id(1) can read diffs from stdin.\n>\n>   - git-hash-object(1) can hash data from stdin.\n>\n> Both cases can work without a repository, and if they don't have one\n> they will now crash.\n\nPerhaps we should double-check with all commands that are designed\nto be able to work outside a repository, e.g. \"git apply\", \"git grep\n--no-index\", \"git diff --no-index\" (tried to be exhausitive without\nconsulting documentation, so the list is not exhausitive at all).\n\n> I still consider it a good thing that we did the change regardless of\n> those crashes. In the case of git-patch-id(1) I would claim that using\n> `the_hash_algo` is wrong in the first place, as patch IDs should be\n> stable and are documented to always use SHA1. Thus, patch IDs in SHA256\n> repos are essentially broken. And in the case of git-hash-object(1), we\n> should expose a command line option to let the user specify the object\n> hash. So both cases demonstrate that there is room for improvement.\n\nIt is good that the topic is kept outside 'master' (and it is in\n'next' to give the topic a bit wider exposure than merely in 'seen'\nand the list archive).\n\nWe may want a test file that explicitly make commands that ought\nto work outside a repository actually run outside a repository,\nmaking use of the GIT_CEILING_DIRECTORIES mechanism, something along\nthe lines of the attached.\n\n t/t1517-outside-repo.sh | 42 ++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 42 insertions(+)\n\ndiff --git c/t/t1517-outside-repo.sh w/t/t1517-outside-repo.sh\nnew file mode 100755\nindex 0000000000..4c595c2ff7\n--- /dev/null\n+++ w/t/t1517-outside-repo.sh\n@@ -0,0 +1,42 @@\n+#!/bin/sh\n+\n+test_description='check random commands outside repo'\n+\n+TEST_PASSES_SANITIZE_LEAK=true\n+. ./test-lib.sh\n+\n+test_expect_success 'set up a non-repo directory and test file' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir non-repo &&\n+\t(\n+\t\tcd non-repo &&\n+\t\t# confirm that git does not find a repo\n+\t\ttest_must_fail git rev-parse --git-dir\n+\t) &&\n+\ttest_write_lines one two three four >nums &&\n+\tgit add nums &&\n+\tcp nums nums.old &&\n+\ttest_write_lines five >>nums &&\n+\tgit diff >sample.patch\n+'\n+\n+test_expect_success 'apply a patch outside repository' '\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit apply ../sample.patch\n+\t) &&\n+\ttest_cmp nums non-repo/nums\n+'\n+\n+test_expect_success 'compute a patch-id outside repository' '\n+\tgit patch-id <sample.patch >patch-id.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit patch-id <../sample.patch >../patch-id.actual\n+\t) &&\n+\ttest_cmp patch-id.expect patch-id.actual\n+'\n+\n+test_done\n"},{"id":"494644","messageId":"xmqqcyppftjs.fsf@gitster.g","threadId":"61463","inReplyTo":"xmqqttj1hfb3.fsf@gitster.g","subject":"Re: [PATCH 0/2] Fix use of uninitialized hash algos","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T18:36:23Z","receivedAt":"2024-05-13T18:36:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>> I still consider it a good thing that we did the change regardless of\n>> those crashes. In the case of git-patch-id(1) I would claim that using\n>> `the_hash_algo` is wrong in the first place, as patch IDs should be\n>> stable and are documented to always use SHA1. Thus, patch IDs in SHA256\n>> repos are essentially broken. And in the case of git-hash-object(1), we\n>> should expose a command line option to let the user specify the object\n>> hash. So both cases demonstrate that there is room for improvement.\n>\n> It is good that the topic is kept outside 'master' (and it is in\n> 'next' to give the topic a bit wider exposure than merely in 'seen'\n> and the list archive).\n>\n> We may want a test file that explicitly make commands that ought\n> to work outside a repository actually run outside a repository,\n> making use of the GIT_CEILING_DIRECTORIES mechanism, something along\n> the lines of the attached.\n\nAnother thought.  Perhaps we should do, in the meantime, the\nattached patch?\n\nWithout your \"fix patch-id\" patch, one of the tests in 1517 will\nfail, and the other fails as there is no fix posted yet, but with\nthe GIT_TEST_DEFAULT_HASH_IS_SHA1 set explicit to 1, they keep\npassing.  This way, when we run out tests, we will always leave the\ndefault hash uninitialized to catch more errors, the binary built\nout of our source by default will crash to help our users catch more\nerrors for us, yet when they really really need to, the users can\nset and export GIT_TEST_DEFAULT_HASH_IS_SHA1=1 to keep assuming that\nSHA1 is the hash algorithm when there is no specified.\n\n\n repository.c            | 24 ++++++++++++++++++++++++\n t/t1517-outside-repo.sh | 42 ++++++++++++++++++++++++++++++++++++++++++\n t/test-lib.sh           |  4 ++++\n 3 files changed, 70 insertions(+)\n\ndiff --git c/repository.c w/repository.c\nindex 15c10015b0..6f67966e35 100644\n--- c/repository.c\n+++ w/repository.c\n@@ -26,6 +26,30 @@ void initialize_repository(struct repository *repo)\n \trepo->parsed_objects = parsed_object_pool_new();\n \tALLOC_ARRAY(repo->index, 1);\n \tindex_state_init(repo->index, repo);\n+\n+\t/*\n+\t * Unfortunately, we need to keep this hack around for the time being:\n+\t *\n+\t *   - Not setting up the hash algorithm for `the_repository` leads to\n+\t *     crashes because `the_hash_algo` is a macro that expands to\n+\t *     `the_repository->hash_algo`. So if Git commands try to access\n+\t *     `the_hash_algo` without a Git directory we crash.\n+\t *\n+\t *   - Setting up the hash algorithm to be SHA1 by default breaks other\n+\t *     commands when running with SHA256.\n+\t *\n+\t * This is another point in case why having global state is a bad idea.\n+\t * Eventually, we should remove this hack and stop setting the hash\n+\t * algorithm in this function altogether. Instead, it should only ever\n+\t * be set via our repository setup procedures. But that requires more\n+\t * work.\n+\t *\n+\t * As we discover the code paths that need fixing, we may remove this\n+\t * code completely, but we are not there yet.\n+\t */\n+\tif (repo == the_repository &&\n+\t    git_env_bool(\"GIT_TEST_DEFAULT_HASH_IS_SHA1\", 0))\n+\t\trepo_set_hash_algo(repo, GIT_HASH_SHA1);\n }\n \n static void expand_base_dir(char **out, const char *in,\ndiff --git c/t/t1517-outside-repo.sh w/t/t1517-outside-repo.sh\nnew file mode 100755\nindex 0000000000..4c595c2ff7\n--- /dev/null\n+++ w/t/t1517-outside-repo.sh\n@@ -0,0 +1,42 @@\n+#!/bin/sh\n+\n+test_description='check random commands outside repo'\n+\n+TEST_PASSES_SANITIZE_LEAK=true\n+. ./test-lib.sh\n+\n+test_expect_success 'set up a non-repo directory and test file' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir non-repo &&\n+\t(\n+\t\tcd non-repo &&\n+\t\t# confirm that git does not find a repo\n+\t\ttest_must_fail git rev-parse --git-dir\n+\t) &&\n+\ttest_write_lines one two three four >nums &&\n+\tgit add nums &&\n+\tcp nums nums.old &&\n+\ttest_write_lines five >>nums &&\n+\tgit diff >sample.patch\n+'\n+\n+test_expect_success 'apply a patch outside repository' '\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit apply ../sample.patch\n+\t) &&\n+\ttest_cmp nums non-repo/nums\n+'\n+\n+test_expect_success 'compute a patch-id outside repository' '\n+\tgit patch-id <sample.patch >patch-id.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit patch-id <../sample.patch >../patch-id.actual\n+\t) &&\n+\ttest_cmp patch-id.expect patch-id.actual\n+'\n+\n+test_done\ndiff --git c/t/test-lib.sh w/t/test-lib.sh\nindex 79d3e0e7d9..36d311fb4a 100644\n--- c/t/test-lib.sh\n+++ w/t/test-lib.sh\n@@ -542,6 +542,10 @@ export EDITOR\n \n GIT_DEFAULT_HASH=\"${GIT_TEST_DEFAULT_HASH:-sha1}\"\n export GIT_DEFAULT_HASH\n+\n+GIT_TEST_DEFAULT_HASH_IS_SHA1=0\n+export GIT_TEST_DEFAULT_HASH_IS_SHA1\n+\n GIT_DEFAULT_REF_FORMAT=\"${GIT_TEST_DEFAULT_REF_FORMAT:-files}\"\n export GIT_DEFAULT_REF_FORMAT\n GIT_TEST_MERGE_ALGORITHM=\"${GIT_TEST_MERGE_ALGORITHM:-ort}\"\n"},{"id":"494653","messageId":"20240513192112.866021-1-gitster@pobox.com","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"[PATCH v2 0/4] Fix use of uninitialized hash algorithms","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T19:21:08Z","receivedAt":"2024-05-13T19:21:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The series adds an escape hatch to \"the default hash algorithm is\nno longer SHA-1; it is an error to rely on the default\" by\nintroducing an undocumented GIT_TEST_DEFAULT_HASH_IS_SHA1=1\nenvironment variable that users can set after reporting an failure\nthey saw to us.\n\nWe can see that Patrick's two fixes to patch-id and hash-object\ncorrects the breakage as the series progresses.\n\nJunio C Hamano (2):\n  setup: add an escape hatch for \"no more default hash algorithm\" change\n  t1517: test commands that are designed to be run outside repository\n\nPatrick Steinhardt (2):\n  builtin/patch-id: fix uninitialized hash function\n  builtin/hash-object: fix uninitialized hash function\n\n builtin/hash-object.c   |  7 +++++\n builtin/patch-id.c      | 13 +++++++++\n repository.c            | 24 ++++++++++++++++\n t/t1007-hash-object.sh  |  6 ++++\n t/t1517-outside-repo.sh | 61 +++++++++++++++++++++++++++++++++++++++++\n t/t4204-patch-id.sh     | 34 +++++++++++++++++++++++\n t/test-lib.sh           |  4 +++\n 7 files changed, 149 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494654","messageId":"20240513192112.866021-2-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513192112.866021-1-gitster@pobox.com","subject":"[PATCH v2 1/4] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T19:21:09Z","receivedAt":"2024-05-13T19:21:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Partially revert c8aed5e8 (repository: stop setting SHA1 as the\ndefault object hash, 2024-05-07), to keep end-user systems still\nbroken when we have gap in our test coverage but yet give them an\nescape hatch to set the GIT_TEST_DEFAULT_HASH_IS_SHA1=1 environment\nvariable to revert to the previous behaviour.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n repository.c  | 24 ++++++++++++++++++++++++\n t/test-lib.sh |  4 ++++\n 2 files changed, 28 insertions(+)\n\ndiff --git a/repository.c b/repository.c\nindex 15c10015b0..6f67966e35 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -26,6 +26,30 @@ void initialize_repository(struct repository *repo)\n \trepo->parsed_objects = parsed_object_pool_new();\n \tALLOC_ARRAY(repo->index, 1);\n \tindex_state_init(repo->index, repo);\n+\n+\t/*\n+\t * Unfortunately, we need to keep this hack around for the time being:\n+\t *\n+\t *   - Not setting up the hash algorithm for `the_repository` leads to\n+\t *     crashes because `the_hash_algo` is a macro that expands to\n+\t *     `the_repository->hash_algo`. So if Git commands try to access\n+\t *     `the_hash_algo` without a Git directory we crash.\n+\t *\n+\t *   - Setting up the hash algorithm to be SHA1 by default breaks other\n+\t *     commands when running with SHA256.\n+\t *\n+\t * This is another point in case why having global state is a bad idea.\n+\t * Eventually, we should remove this hack and stop setting the hash\n+\t * algorithm in this function altogether. Instead, it should only ever\n+\t * be set via our repository setup procedures. But that requires more\n+\t * work.\n+\t *\n+\t * As we discover the code paths that need fixing, we may remove this\n+\t * code completely, but we are not there yet.\n+\t */\n+\tif (repo == the_repository &&\n+\t    git_env_bool(\"GIT_TEST_DEFAULT_HASH_IS_SHA1\", 0))\n+\t\trepo_set_hash_algo(repo, GIT_HASH_SHA1);\n }\n \n static void expand_base_dir(char **out, const char *in,\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 79d3e0e7d9..36d311fb4a 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -542,6 +542,10 @@ export EDITOR\n \n GIT_DEFAULT_HASH=\"${GIT_TEST_DEFAULT_HASH:-sha1}\"\n export GIT_DEFAULT_HASH\n+\n+GIT_TEST_DEFAULT_HASH_IS_SHA1=0\n+export GIT_TEST_DEFAULT_HASH_IS_SHA1\n+\n GIT_DEFAULT_REF_FORMAT=\"${GIT_TEST_DEFAULT_REF_FORMAT:-files}\"\n export GIT_DEFAULT_REF_FORMAT\n GIT_TEST_MERGE_ALGORITHM=\"${GIT_TEST_MERGE_ALGORITHM:-ort}\"\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494655","messageId":"20240513192112.866021-3-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513192112.866021-1-gitster@pobox.com","subject":"[PATCH v2 2/4] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T19:21:10Z","receivedAt":"2024-05-13T19:21:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A few commands, like \"git apply\" and \"git patch-id\", have been\nbroken with a recent change to stop setting the default hash\nalgorithm to SHA-1.  Test them and fix them in later commits.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1517-outside-repo.sh | 61 +++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 61 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nnew file mode 100755\nindex 0000000000..e0fd495ec1\n--- /dev/null\n+++ b/t/t1517-outside-repo.sh\n@@ -0,0 +1,61 @@\n+#!/bin/sh\n+\n+test_description='check random commands outside repo'\n+\n+TEST_PASSES_SANITIZE_LEAK=true\n+. ./test-lib.sh\n+\n+test_expect_success 'set up a non-repo directory and test file' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir non-repo &&\n+\t(\n+\t\tcd non-repo &&\n+\t\t# confirm that git does not find a repo\n+\t\ttest_must_fail git rev-parse --git-dir\n+\t) &&\n+\ttest_write_lines one two three four >nums &&\n+\tgit add nums &&\n+\tcp nums nums.old &&\n+\ttest_write_lines five >>nums &&\n+\tgit diff >sample.patch\n+'\n+\n+test_expect_failure 'compute a patch-id outside repository' '\n+\tgit patch-id <sample.patch >patch-id.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit patch-id <../sample.patch >../patch-id.actual\n+\t) &&\n+\ttest_cmp patch-id.expect patch-id.actual\n+'\n+\n+test_expect_failure 'hash-object outside repository' '\n+\tgit hash-object --stdin <sample.patch >hash.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit hash-object --stdin <../sample.patch >../hash.actual\n+\t) &&\n+\ttest_cmp hash.expect hash.actual\n+'\n+\n+test_expect_failure 'apply a patch outside repository' '\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit apply ../sample.patch\n+\t) &&\n+\ttest_cmp nums non-repo/nums\n+'\n+\n+test_expect_success 'grep outside repository' '\n+\tgit grep --cached two >expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit grep --no-index two >../actual\n+\t) &&\n+\ttest_cmp expect actual\n+'\n+\n+test_done\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494656","messageId":"20240513192112.866021-4-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513192112.866021-1-gitster@pobox.com","subject":"[PATCH v2 3/4] builtin/patch-id: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T19:21:11Z","receivedAt":"2024-05-13T19:21:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nIn c8aed5e8da (repository: stop setting SHA1 as the default object hash,\n2024-05-07), we have adapted `initialize_repository()` to no longer set\nup a default hash function. As this function is also used to set up\n`the_repository`, the consequence is that `the_hash_algo` will now by\ndefault be a `NULL` pointer unless the hash algorithm was configured\nproperly. This is done as a mechanism to detect cases where we may be\nusing the wrong hash function by accident.\n\nThis change now causes git-patch-id(1) to segfault when it's run outside\nof a repository. As this command can read diffs from stdin, it does not\nnecessarily need a repository, but then relies on `the_hash_algo` to\ncompute the patch ID itself.\n\nIt is somewhat dubious that git-patch-id(1) relies on `the_hash_algo` in\nthe first place. Quoting its manpage:\n\n    A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs\n    associated with a patch, with line numbers ignored. As such, it’s\n    \"reasonably stable\", but at the same time also reasonably unique,\n    i.e., two patches that have the same \"patch ID\" are almost\n    guaranteed to be the same thing.\n\nWe explicitly document patch IDs to be using SHA-1. Furthermore, patch\nIDs are supposed to be stable for most of the part. But even with the\nsame input, the patch IDs will now be different depending on the repo's\nconfigured object hash.\n\nWork around the issue by setting up SHA-1 when there was no startup\nrepository for now. This is arguably not the correct fix, but for now we\nrather want to focus on getting the segfault fixed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/patch-id.c      | 13 +++++++++++++\n t/t1517-outside-repo.sh |  2 +-\n t/t4204-patch-id.sh     | 34 ++++++++++++++++++++++++++++++++++\n 3 files changed, 48 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/patch-id.c b/builtin/patch-id.c\nindex 3894d2b970..be5a85e71c 100644\n--- a/builtin/patch-id.c\n+++ b/builtin/patch-id.c\n@@ -5,6 +5,7 @@\n #include \"hash.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n+#include \"setup.h\"\n \n static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)\n {\n@@ -237,6 +238,18 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, builtin_patch_id_options,\n \t\t\t     patch_id_usage, 0);\n \n+\t/*\n+\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n+\t * it means that the hash algorithm now depends on the object hash of\n+\t * the repository, even though git-patch-id(1) clearly defines that\n+\t * patch IDs always use SHA1.\n+\t *\n+\t * TODO: This hack should be removed in favor of converting the code\n+\t *       that computes patch IDs to always use SHA1.\n+\t */\n+\tif (!startup_info->have_repository)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tgenerate_id_list(opts ? opts > 1 : config.stable,\n \t\t\t opts ? opts == 3 : config.verbatim);\n \treturn 0;\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex e0fd495ec1..ac5f3191cc 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -21,7 +21,7 @@ test_expect_success 'set up a non-repo directory and test file' '\n \tgit diff >sample.patch\n '\n \n-test_expect_failure 'compute a patch-id outside repository' '\n+test_expect_success 'compute a patch-id outside repository' '\n \tgit patch-id <sample.patch >patch-id.expect &&\n \t(\n \t\tcd non-repo &&\ndiff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh\nindex a7fa94ce0a..605faea0c7 100755\n--- a/t/t4204-patch-id.sh\n+++ b/t/t4204-patch-id.sh\n@@ -310,4 +310,38 @@ test_expect_success 'patch-id handles diffs with one line of before/after' '\n \ttest_config patchid.stable true &&\n \tcalc_patch_id diffu1stable <diffu1\n '\n+\n+test_expect_failure 'patch-id computes same ID with different object hashes' '\n+\ttest_when_finished \"rm -rf repo-sha1 repo-sha256\" &&\n+\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\n+\tgit init --object-format=sha1 repo-sha1 &&\n+\tgit -C repo-sha1 patch-id <diff >patch-id-sha1 &&\n+\tgit init --object-format=sha256 repo-sha256 &&\n+\tgit -C repo-sha256 patch-id <diff >patch-id-sha256 &&\n+\ttest_cmp patch-id-sha1 patch-id-sha256\n+'\n+\n+test_expect_success 'patch-id without repository' '\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\tnongit git patch-id <diff\n+'\n+\n test_done\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494657","messageId":"20240513192112.866021-5-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513192112.866021-1-gitster@pobox.com","subject":"[PATCH v2 4/4] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T19:21:12Z","receivedAt":"2024-05-13T19:21:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nThe git-hash-object(1) command allows users to hash an object even\nwithout a repository. Starting with c8aed5e8da (repository: stop setting\nSHA1 as the default object hash, 2024-05-07), this will make us hit an\nuninitialized hash function, which subsequently leads to a segfault.\n\nFix this by falling back to SHA-1 explicitly when running outside of a\nGit repository. Eventually, we should expose this function as a command\nline option to the users so that they can pick which object hash to use\nby themselves.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/hash-object.c   | 7 +++++++\n t/t1007-hash-object.sh  | 6 ++++++\n t/t1517-outside-repo.sh | 2 +-\n 3 files changed, 14 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex 82ca6d2bfd..0855f4f8aa 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -123,6 +123,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n \telse\n \t\tprefix = setup_git_directory_gently(&nongit);\n \n+\t/*\n+\t * TODO: Allow the hash algorithm to be configured by the user via a\n+\t *       command line option when not using `-w`.\n+\t */\n+\tif (nongit)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (vpath && prefix) {\n \t\tvpath_free = prefix_filename(prefix, vpath);\n \t\tvpath = vpath_free;\ndiff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh\nindex 64aea38486..4c138c6ca4 100755\n--- a/t/t1007-hash-object.sh\n+++ b/t/t1007-hash-object.sh\n@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '\n \techo example | git hash-object -t $t --literally --stdin\n '\n \n+test_expect_success '--stdin outside of repository' '\n+\tnongit git hash-object --stdin <hello >actual &&\n+\techo \"$(test_oid hello)\" >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex ac5f3191cc..854bb8f343 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -30,7 +30,7 @@ test_expect_success 'compute a patch-id outside repository' '\n \ttest_cmp patch-id.expect patch-id.actual\n '\n \n-test_expect_failure 'hash-object outside repository' '\n+test_expect_success 'hash-object outside repository' '\n \tgit hash-object --stdin <sample.patch >hash.expect &&\n \t(\n \t\tcd non-repo &&\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494659","messageId":"CAO_smVhxCGUD2D5m9eDj+CBmteauBuGG=6RgjADnuXgBeB5O8A@mail.gmail.com","threadId":"61463","inReplyTo":"20240513192112.866021-2-gitster@pobox.com","subject":"Re: [PATCH v2 1/4] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Kyle Lippincott","fromEmail":"spectral@google.com","sentAt":"2024-05-13T19:48:05Z","receivedAt":"2024-05-13T19:48:18Z","isPatch":true,"sender":{"key":"spectral@google.com","avatar":"https://avatars.githubusercontent.com/u/6371650?v=4"},"body":"On Mon, May 13, 2024 at 12:21 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n> default object hash, 2024-05-07), to keep end-user systems still\n> broken when we have gap in our test coverage but yet give them an\n> escape hatch to set the GIT_TEST_DEFAULT_HASH_IS_SHA1=1 environment\n> variable to revert to the previous behaviour.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  repository.c  | 24 ++++++++++++++++++++++++\n\nNice idea, this concept LG.\n\n>  t/test-lib.sh |  4 ++++\n>  2 files changed, 28 insertions(+)\n>\n> diff --git a/repository.c b/repository.c\n> index 15c10015b0..6f67966e35 100644\n> --- a/repository.c\n> +++ b/repository.c\n> @@ -26,6 +26,30 @@ void initialize_repository(struct repository *repo)\n>         repo->parsed_objects = parsed_object_pool_new();\n>         ALLOC_ARRAY(repo->index, 1);\n>         index_state_init(repo->index, repo);\n> +\n> +       /*\n> +        * Unfortunately, we need to keep this hack around for the time being:\n\nNit: the comment says we need to keep it around, but it's actually\ndefaulted to off. We may want to add clarification of the current\nstatus to the comment (or replace the entire comment with a comment\ndescribing that we added a hack to the hack, and that it should be\nremoved \"soon\").\n\n> +        *\n> +        *   - Not setting up the hash algorithm for `the_repository` leads to\n> +        *     crashes because `the_hash_algo` is a macro that expands to\n> +        *     `the_repository->hash_algo`. So if Git commands try to access\n> +        *     `the_hash_algo` without a Git directory we crash.\n> +        *\n> +        *   - Setting up the hash algorithm to be SHA1 by default breaks other\n> +        *     commands when running with SHA256.\n> +        *\n> +        * This is another point in case why having global state is a bad idea.\n> +        * Eventually, we should remove this hack and stop setting the hash\n> +        * algorithm in this function altogether. Instead, it should only ever\n> +        * be set via our repository setup procedures. But that requires more\n> +        * work.\n> +        *\n> +        * As we discover the code paths that need fixing, we may remove this\n> +        * code completely, but we are not there yet.\n> +        */\n> +       if (repo == the_repository &&\n> +           git_env_bool(\"GIT_TEST_DEFAULT_HASH_IS_SHA1\", 0))\n> +               repo_set_hash_algo(repo, GIT_HASH_SHA1);\n>  }\n>\n>  static void expand_base_dir(char **out, const char *in,\n> diff --git a/t/test-lib.sh b/t/test-lib.sh\n> index 79d3e0e7d9..36d311fb4a 100644\n> --- a/t/test-lib.sh\n> +++ b/t/test-lib.sh\n> @@ -542,6 +542,10 @@ export EDITOR\n>\n>  GIT_DEFAULT_HASH=\"${GIT_TEST_DEFAULT_HASH:-sha1}\"\n>  export GIT_DEFAULT_HASH\n> +\n> +GIT_TEST_DEFAULT_HASH_IS_SHA1=0\n\nThis is the default as being established in this commit, correct?\nShould we add a comment saying this is the default and describe why we\nhave it here anyway?\n\n> +export GIT_TEST_DEFAULT_HASH_IS_SHA1\n> +\n>  GIT_DEFAULT_REF_FORMAT=\"${GIT_TEST_DEFAULT_REF_FORMAT:-files}\"\n>  export GIT_DEFAULT_REF_FORMAT\n>  GIT_TEST_MERGE_ALGORITHM=\"${GIT_TEST_MERGE_ALGORITHM:-ort}\"\n> --\n> 2.45.0-145-g3e4a232f6e\n>\n>\n"},{"id":"494660","messageId":"CAO_smVg7mdQHp+sg4-vVUEOVRBEoZjqXZu=Kk8PuYc9mtYeMXg@mail.gmail.com","threadId":"61463","inReplyTo":"20240513192112.866021-3-gitster@pobox.com","subject":"Re: [PATCH v2 2/4] t1517: test commands that are designed to be run outside repository","fromName":"Kyle Lippincott","fromEmail":"spectral@google.com","sentAt":"2024-05-13T19:57:11Z","receivedAt":"2024-05-13T19:57:24Z","isPatch":true,"sender":{"key":"spectral@google.com","avatar":"https://avatars.githubusercontent.com/u/6371650?v=4"},"body":"On Mon, May 13, 2024 at 12:21 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> A few commands, like \"git apply\" and \"git patch-id\", have been\n> broken with a recent change to stop setting the default hash\n> algorithm to SHA-1.  Test them and fix them in later commits.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  t/t1517-outside-repo.sh | 61 +++++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 61 insertions(+)\n>  create mode 100755 t/t1517-outside-repo.sh\n>\n> diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\n> new file mode 100755\n> index 0000000000..e0fd495ec1\n> --- /dev/null\n> +++ b/t/t1517-outside-repo.sh\n> @@ -0,0 +1,61 @@\n> +#!/bin/sh\n> +\n> +test_description='check random commands outside repo'\n> +\n> +TEST_PASSES_SANITIZE_LEAK=true\n> +. ./test-lib.sh\n> +\n> +test_expect_success 'set up a non-repo directory and test file' '\n> +       GIT_CEILING_DIRECTORIES=$(pwd) &&\n> +       export GIT_CEILING_DIRECTORIES &&\n> +       mkdir non-repo &&\n> +       (\n> +               cd non-repo &&\n> +               # confirm that git does not find a repo\n> +               test_must_fail git rev-parse --git-dir\n> +       ) &&\n> +       test_write_lines one two three four >nums &&\n> +       git add nums &&\n> +       cp nums nums.old &&\n> +       test_write_lines five >>nums &&\n> +       git diff >sample.patch\n> +'\n> +\n> +test_expect_failure 'compute a patch-id outside repository' '\n\nDo we only expect failure because of a temporary condition (the bug\nthat is mentioned in the commit message)? If so, we should probably\nadd a TODO, FIXME, or some other similar style of comment that\ndescribes that this should be fixed. This way, if the patch series to\nfix the issue doesn't materialize, people don't read the test file and\nthink that these commands aren't supported outside of a repository.\n\nDo we have a way of catching the specific failure mode? i.e. if it\ncrashes, is there a test_expect_crash? I'm thinking that it might be\nnice to be more specific about what kind of failure we expect, this\nway if it fails in a different way before we convert these to\ntest_expect_success, the test fails (due to the unexpected change).\nI'm assuming that for crashes of this type there's no good/portable\nway of verifying that it's a specific crash, but having the test check\nfor a difference between an exit code that indicates a signal was\nraised and an exit code that indicates that the process returned\n\"naturally\" after an unsuccessful execution might be feasible, if we\nalready have such a mechanism. Adding one just for this series doesn't\nseem justified.\n\n> +       git patch-id <sample.patch >patch-id.expect &&\n> +       (\n> +               cd non-repo &&\n> +               git patch-id <../sample.patch >../patch-id.actual\n> +       ) &&\n> +       test_cmp patch-id.expect patch-id.actual\n> +'\n> +\n> +test_expect_failure 'hash-object outside repository' '\n> +       git hash-object --stdin <sample.patch >hash.expect &&\n> +       (\n> +               cd non-repo &&\n> +               git hash-object --stdin <../sample.patch >../hash.actual\n> +       ) &&\n> +       test_cmp hash.expect hash.actual\n> +'\n> +\n> +test_expect_failure 'apply a patch outside repository' '\n> +       (\n> +               cd non-repo &&\n> +               cp ../nums.old nums &&\n> +               git apply ../sample.patch\n> +       ) &&\n> +       test_cmp nums non-repo/nums\n> +'\n> +\n> +test_expect_success 'grep outside repository' '\n> +       git grep --cached two >expect &&\n> +       (\n> +               cd non-repo &&\n> +               cp ../nums.old nums &&\n> +               git grep --no-index two >../actual\n> +       ) &&\n> +       test_cmp expect actual\n> +'\n> +\n> +test_done\n> --\n> 2.45.0-145-g3e4a232f6e\n>\n>\n"},{"id":"494663","messageId":"xmqqy18de9kq.fsf@gitster.g","threadId":"61463","inReplyTo":"CAO_smVg7mdQHp+sg4-vVUEOVRBEoZjqXZu=Kk8PuYc9mtYeMXg@mail.gmail.com","subject":"Re: [PATCH v2 2/4] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T20:33:09Z","receivedAt":"2024-05-13T20:33:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kyle Lippincott <spectral@google.com> writes:\n\n> Do we only expect failure because of a temporary condition (the bug\n> that is mentioned in the commit message)? If so, we should probably\n> add a TODO, FIXME, or some other similar style of comment that\n> describes that this should be fixed.\n\ntest_expect_failure is description enough for that purpose.\n\nIf a command should NOT work outside the project we will write a\ntest more like so:\n\n\ttest_expect_success 'foo does not work outside' '\n\t\t... prepare that $cwd is outside ...\n\t\ttest_must_fail git foo\n\t'\n"},{"id":"494664","messageId":"xmqqseyle8aw.fsf@gitster.g","threadId":"61463","inReplyTo":"xmqqy18de9kq.fsf@gitster.g","subject":"Re: [PATCH v2 2/4] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T21:00:39Z","receivedAt":"2024-05-13T21:00:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Kyle Lippincott <spectral@google.com> writes:\n>\n>> Do we only expect failure because of a temporary condition (the bug\n>> that is mentioned in the commit message)? If so, we should probably\n>> add a TODO, FIXME, or some other similar style of comment that\n>> describes that this should be fixed.\n>\n> test_expect_failure is description enough for that purpose.\n\nWe say this in t/README:\n\n - test_expect_failure [<prereq>] <message> <script>\n\n   This is NOT the opposite of test_expect_success, but is used\n   to mark a test that demonstrates a known breakage.  Unlike\n   the usual test_expect_success tests, which say \"ok\" on\n   success and \"FAIL\" on failure, this will say \"FIXED\" on\n   success and \"still broken\" on failure.  Failures from these\n   tests won't cause -i (immediate) to stop.\n\nWhich means that when somebody rans out of things to do, grepping\nfor test_expect_failure may give them a good place to start ;-).\n\nNote that there were a few very rare occasions that what was marked\nas \"known breakage\" with test_expect_failure turned out to be what\nwas working as intended.\n\nThanks.\n"},{"id":"494666","messageId":"CAO_smVgj85+LdGyhwgyzrCV-KYJ7r+zhJq-cBq_2wa+Qs1bbjQ@mail.gmail.com","threadId":"61463","inReplyTo":"xmqqseyle8aw.fsf@gitster.g","subject":"Re: [PATCH v2 2/4] t1517: test commands that are designed to be run outside repository","fromName":"Kyle Lippincott","fromEmail":"spectral@google.com","sentAt":"2024-05-13T21:07:38Z","receivedAt":"2024-05-13T21:07:56Z","isPatch":true,"sender":{"key":"spectral@google.com","avatar":"https://avatars.githubusercontent.com/u/6371650?v=4"},"body":"On Mon, May 13, 2024 at 2:00 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > Kyle Lippincott <spectral@google.com> writes:\n> >\n> >> Do we only expect failure because of a temporary condition (the bug\n> >> that is mentioned in the commit message)? If so, we should probably\n> >> add a TODO, FIXME, or some other similar style of comment that\n> >> describes that this should be fixed.\n> >\n> > test_expect_failure is description enough for that purpose.\n>\n> We say this in t/README:\n>\n>  - test_expect_failure [<prereq>] <message> <script>\n>\n>    This is NOT the opposite of test_expect_success, but is used\n>    to mark a test that demonstrates a known breakage.  Unlike\n>    the usual test_expect_success tests, which say \"ok\" on\n>    success and \"FAIL\" on failure, this will say \"FIXED\" on\n>    success and \"still broken\" on failure.  Failures from these\n>    tests won't cause -i (immediate) to stop.\n\nGot it, thanks for explaining. With that, this change looks good to me.\n\n>\n> Which means that when somebody rans out of things to do, grepping\n> for test_expect_failure may give them a good place to start ;-).\n>\n> Note that there were a few very rare occasions that what was marked\n> as \"known breakage\" with test_expect_failure turned out to be what\n> was working as intended.\n>\n> Thanks.\n"},{"id":"494668","messageId":"xmqqcyppe70k.fsf_-_@gitster.g","threadId":"61463","inReplyTo":"20240513192112.866021-1-gitster@pobox.com","subject":"[PATCH 5/4] apply: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T21:28:27Z","receivedAt":"2024-05-13T21:28:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git apply\" can work outside a repository as a better \"GNU patch\",\nbut when it does so, it still assumed that it can access\nthe_hash_algo, which is no longer true in the new world order.\n\nMake sure we explicitly fall back to SHA-1 algorithm for backward\ncompatibility.  Just like we argued for hash-objects, we probably\nshould have a mechanism to specify the hash algorithm used outside\na repository.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * After finishing these steps, it started to dawn on me that we\n   probably can instead add GIT_DEFAULT_HASH_ALGO environment\n   variable for exactly that purpose.  Then the escape hatch I\n   introduced in [1/4] can become just that.\n\n builtin/apply.c         | 4 ++++\n t/t1517-outside-repo.sh | 2 +-\n 2 files changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 861a01910c..e9175f820f 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -1,6 +1,7 @@\n #include \"builtin.h\"\n #include \"gettext.h\"\n #include \"repository.h\"\n+#include \"hash.h\"\n #include \"apply.h\"\n \n static const char * const apply_usage[] = {\n@@ -18,6 +19,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)\n \tif (init_apply_state(&state, the_repository, prefix))\n \t\texit(128);\n \n+\tif (!the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \targc = apply_parse_options(argc, argv,\n \t\t\t\t   &state, &force_apply, &options,\n \t\t\t\t   apply_usage);\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 854bb8f343..6f32a40c6d 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -39,7 +39,7 @@ test_expect_success 'hash-object outside repository' '\n \ttest_cmp hash.expect hash.actual\n '\n \n-test_expect_failure 'apply a patch outside repository' '\n+test_expect_success 'apply a patch outside repository' '\n \t(\n \t\tcd non-repo &&\n \t\tcp ../nums.old nums &&\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494671","messageId":"20240513224127.2042052-1-gitster@pobox.com","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"[PATCH v3 0/5] Fix use of uninitialized hash algorithms","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T22:41:22Z","receivedAt":"2024-05-13T22:41:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"In this round, the escape hatch is no longer the escape hatch, but\nalso serves as an end-user knob to specify what hash algorithm to\nuse when there is no repository to tell us which one to use.\n\nWe can see that Patrick's two fixes to patch-id and hash-object, as\nwell as my fix to apply, correct the breakage as the series\nprogresses.\n\nJunio C Hamano (3):\n  setup: add an escape hatch for \"no more default hash algorithm\" change\n  t1517: test commands that are designed to be run outside repository\n  apply: fix uninitialized hash function\n\nPatrick Steinhardt (2):\n  builtin/patch-id: fix uninitialized hash function\n  builtin/hash-object: fix uninitialized hash function\n\n builtin/apply.c         |  4 +++\n builtin/hash-object.c   |  3 ++\n builtin/patch-id.c      | 13 +++++++++\n repository.c            | 32 +++++++++++++++++++++\n t/t1007-hash-object.sh  |  6 ++++\n t/t1517-outside-repo.sh | 64 +++++++++++++++++++++++++++++++++++++++++\n t/t4204-patch-id.sh     | 34 ++++++++++++++++++++++\n 7 files changed, 156 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494672","messageId":"20240513224127.2042052-2-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513224127.2042052-1-gitster@pobox.com","subject":"[PATCH v3 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T22:41:23Z","receivedAt":"2024-05-13T22:41:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Partially revert c8aed5e8 (repository: stop setting SHA1 as the\ndefault object hash, 2024-05-07), to keep end-user systems still\nbroken when we have gap in our test coverage but yet give them an\nescape hatch to set the GIT_TEST_DEFAULT_HASH_ALGORITHM environment\nvariable to \"sha1\" in order to revert to the previous behaviour.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n repository.c | 32 ++++++++++++++++++++++++++++++++\n 1 file changed, 32 insertions(+)\n\ndiff --git a/repository.c b/repository.c\nindex 15c10015b0..2001c760dc 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -19,6 +19,20 @@\n static struct repository the_repo;\n struct repository *the_repository = &the_repo;\n \n+static void set_default_hash_algo(struct repository *repo)\n+{\n+\tconst char *hash_name;\n+\tint algo;\n+\n+\thash_name = getenv(\"GIT_DEFAULT_HASH_ALGORITHM\");\n+\tif (!hash_name)\n+\t\treturn;\n+\talgo = hash_algo_by_name(hash_name);\n+\tif (algo == GIT_HASH_UNKNOWN)\n+\t\treturn;\n+\trepo_set_hash_algo(repo, algo);\n+}\n+\n void initialize_repository(struct repository *repo)\n {\n \trepo->objects = raw_object_store_new();\n@@ -26,6 +40,24 @@ void initialize_repository(struct repository *repo)\n \trepo->parsed_objects = parsed_object_pool_new();\n \tALLOC_ARRAY(repo->index, 1);\n \tindex_state_init(repo->index, repo);\n+\n+\t/*\n+\t * When a command runs inside a repository, it learns what\n+\t * hash algorithm is in use from the repository, but some\n+\t * commands are designed to work outside a repository, yet\n+\t * they want to access the_hash_algo, if only for the length\n+\t * of the hashed value to see if their input looks like a\n+\t * plausible hash value.\n+\t *\n+\t * We are in the process of identifying the codepaths and\n+\t * giving them an appropriate default individually; any\n+\t * unconverted codepath that tries to access the_hash_algo\n+\t * will thus fail.  The end-users however have an escape hatch\n+\t * to set GIT_DEFAULT_HASH_ALGORITHM environment variable to\n+\t * \"sha1\" get back the old behaviour of defaulting to SHA-1.\n+\t */\n+\tif (repo == the_repository)\n+\t\tset_default_hash_algo(repo);\n }\n \n static void expand_base_dir(char **out, const char *in,\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494673","messageId":"20240513224127.2042052-3-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513224127.2042052-1-gitster@pobox.com","subject":"[PATCH v3 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T22:41:24Z","receivedAt":"2024-05-13T22:41:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A few commands, like \"git apply\" and \"git patch-id\", have been\nbroken with a recent change to stop setting the default hash\nalgorithm to SHA-1.  Test them and fix them in later commits.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1517-outside-repo.sh | 64 +++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 64 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nnew file mode 100755\nindex 0000000000..16d9714c27\n--- /dev/null\n+++ b/t/t1517-outside-repo.sh\n@@ -0,0 +1,64 @@\n+#!/bin/sh\n+\n+test_description='check random commands outside repo'\n+\n+TEST_PASSES_SANITIZE_LEAK=true\n+. ./test-lib.sh\n+\n+# Do not use the end-user workaround for this test.\n+# GIT_DEFAULT_HASH_ALGORITHM=sha1; export GIT_DEFAULT_HASH_ALGORITHM\n+\n+test_expect_success 'set up a non-repo directory and test file' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir non-repo &&\n+\t(\n+\t\tcd non-repo &&\n+\t\t# confirm that git does not find a repo\n+\t\ttest_must_fail git rev-parse --git-dir\n+\t) &&\n+\ttest_write_lines one two three four >nums &&\n+\tgit add nums &&\n+\tcp nums nums.old &&\n+\ttest_write_lines five >>nums &&\n+\tgit diff >sample.patch\n+'\n+\n+test_expect_failure 'compute a patch-id outside repository' '\n+\tgit patch-id <sample.patch >patch-id.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit patch-id <../sample.patch >../patch-id.actual\n+\t) &&\n+\ttest_cmp patch-id.expect patch-id.actual\n+'\n+\n+test_expect_failure 'hash-object outside repository' '\n+\tgit hash-object --stdin <sample.patch >hash.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit hash-object --stdin <../sample.patch >../hash.actual\n+\t) &&\n+\ttest_cmp hash.expect hash.actual\n+'\n+\n+test_expect_failure 'apply a patch outside repository' '\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit apply ../sample.patch\n+\t) &&\n+\ttest_cmp nums non-repo/nums\n+'\n+\n+test_expect_success 'grep outside repository' '\n+\tgit grep --cached two >expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit grep --no-index two >../actual\n+\t) &&\n+\ttest_cmp expect actual\n+'\n+\n+test_done\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494674","messageId":"20240513224127.2042052-4-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513224127.2042052-1-gitster@pobox.com","subject":"[PATCH v3 3/5] builtin/patch-id: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T22:41:25Z","receivedAt":"2024-05-13T22:41:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nIn c8aed5e8da (repository: stop setting SHA1 as the default object hash,\n2024-05-07), we have adapted `initialize_repository()` to no longer set\nup a default hash function. As this function is also used to set up\n`the_repository`, the consequence is that `the_hash_algo` will now by\ndefault be a `NULL` pointer unless the hash algorithm was configured\nproperly. This is done as a mechanism to detect cases where we may be\nusing the wrong hash function by accident.\n\nThis change now causes git-patch-id(1) to segfault when it's run outside\nof a repository. As this command can read diffs from stdin, it does not\nnecessarily need a repository, but then relies on `the_hash_algo` to\ncompute the patch ID itself.\n\nIt is somewhat dubious that git-patch-id(1) relies on `the_hash_algo` in\nthe first place. Quoting its manpage:\n\n    A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs\n    associated with a patch, with line numbers ignored. As such, it’s\n    \"reasonably stable\", but at the same time also reasonably unique,\n    i.e., two patches that have the same \"patch ID\" are almost\n    guaranteed to be the same thing.\n\nWe explicitly document patch IDs to be using SHA-1. Furthermore, patch\nIDs are supposed to be stable for most of the part. But even with the\nsame input, the patch IDs will now be different depending on the repo's\nconfigured object hash.\n\nWork around the issue by setting up SHA-1 when there was no startup\nrepository for now. This is arguably not the correct fix, but for now we\nrather want to focus on getting the segfault fixed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/patch-id.c      | 13 +++++++++++++\n t/t1517-outside-repo.sh |  2 +-\n t/t4204-patch-id.sh     | 34 ++++++++++++++++++++++++++++++++++\n 3 files changed, 48 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/patch-id.c b/builtin/patch-id.c\nindex 3894d2b970..e6ae89beab 100644\n--- a/builtin/patch-id.c\n+++ b/builtin/patch-id.c\n@@ -5,6 +5,7 @@\n #include \"hash.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n+#include \"setup.h\"\n \n static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)\n {\n@@ -237,6 +238,18 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, builtin_patch_id_options,\n \t\t\t     patch_id_usage, 0);\n \n+\t/*\n+\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n+\t * it means that the hash algorithm now depends on the object hash of\n+\t * the repository, even though git-patch-id(1) clearly defines that\n+\t * patch IDs always use SHA1.\n+\t *\n+\t * NEEDSWORK: This hack should be removed in favor of converting\n+\t * the code that computes patch IDs to always use SHA1.\n+\t */\n+\tif (!startup_info->have_repository)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tgenerate_id_list(opts ? opts > 1 : config.stable,\n \t\t\t opts ? opts == 3 : config.verbatim);\n \treturn 0;\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 16d9714c27..f1fd5c9888 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -24,7 +24,7 @@ test_expect_success 'set up a non-repo directory and test file' '\n \tgit diff >sample.patch\n '\n \n-test_expect_failure 'compute a patch-id outside repository' '\n+test_expect_success 'compute a patch-id outside repository' '\n \tgit patch-id <sample.patch >patch-id.expect &&\n \t(\n \t\tcd non-repo &&\ndiff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh\nindex a7fa94ce0a..605faea0c7 100755\n--- a/t/t4204-patch-id.sh\n+++ b/t/t4204-patch-id.sh\n@@ -310,4 +310,38 @@ test_expect_success 'patch-id handles diffs with one line of before/after' '\n \ttest_config patchid.stable true &&\n \tcalc_patch_id diffu1stable <diffu1\n '\n+\n+test_expect_failure 'patch-id computes same ID with different object hashes' '\n+\ttest_when_finished \"rm -rf repo-sha1 repo-sha256\" &&\n+\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\n+\tgit init --object-format=sha1 repo-sha1 &&\n+\tgit -C repo-sha1 patch-id <diff >patch-id-sha1 &&\n+\tgit init --object-format=sha256 repo-sha256 &&\n+\tgit -C repo-sha256 patch-id <diff >patch-id-sha256 &&\n+\ttest_cmp patch-id-sha1 patch-id-sha256\n+'\n+\n+test_expect_success 'patch-id without repository' '\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\tnongit git patch-id <diff\n+'\n+\n test_done\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494675","messageId":"20240513224127.2042052-5-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513224127.2042052-1-gitster@pobox.com","subject":"[PATCH v3 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T22:41:26Z","receivedAt":"2024-05-13T22:41:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nThe git-hash-object(1) command allows users to hash an object even\nwithout a repository. Starting with c8aed5e8da (repository: stop setting\nSHA1 as the default object hash, 2024-05-07), this will make us hit an\nuninitialized hash function, which subsequently leads to a segfault.\n\nFix this by falling back to SHA-1 explicitly when running outside of a\nGit repository. Users can use GIT_DEFAULT_HASH_ALGORITHM environment to\nspecify what hash algorithm they want, so arguably this code should not\nbe needed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/hash-object.c   | 3 +++\n t/t1007-hash-object.sh  | 6 ++++++\n t/t1517-outside-repo.sh | 2 +-\n 3 files changed, 10 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex 82ca6d2bfd..c767414a0c 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n \telse\n \t\tprefix = setup_git_directory_gently(&nongit);\n \n+\tif (nongit && !the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (vpath && prefix) {\n \t\tvpath_free = prefix_filename(prefix, vpath);\n \t\tvpath = vpath_free;\ndiff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh\nindex 64aea38486..4c138c6ca4 100755\n--- a/t/t1007-hash-object.sh\n+++ b/t/t1007-hash-object.sh\n@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '\n \techo example | git hash-object -t $t --literally --stdin\n '\n \n+test_expect_success '--stdin outside of repository' '\n+\tnongit git hash-object --stdin <hello >actual &&\n+\techo \"$(test_oid hello)\" >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex f1fd5c9888..80261e43c7 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -33,7 +33,7 @@ test_expect_success 'compute a patch-id outside repository' '\n \ttest_cmp patch-id.expect patch-id.actual\n '\n \n-test_expect_failure 'hash-object outside repository' '\n+test_expect_success 'hash-object outside repository' '\n \tgit hash-object --stdin <sample.patch >hash.expect &&\n \t(\n \t\tcd non-repo &&\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494676","messageId":"20240513224127.2042052-6-gitster@pobox.com","threadId":"61463","inReplyTo":"20240513224127.2042052-1-gitster@pobox.com","subject":"[PATCH v3 5/5] apply: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T22:41:27Z","receivedAt":"2024-05-13T22:41:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git apply\" can work outside a repository as a better \"GNU patch\",\nbut when it does so, it still assumed that it can access\nthe_hash_algo, which is no longer true in the new world order.\n\nMake sure we explicitly fall back to SHA-1 algorithm for backward\ncompatibility.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/apply.c         | 4 ++++\n t/t1517-outside-repo.sh | 2 +-\n 2 files changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 861a01910c..e9175f820f 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -1,6 +1,7 @@\n #include \"builtin.h\"\n #include \"gettext.h\"\n #include \"repository.h\"\n+#include \"hash.h\"\n #include \"apply.h\"\n \n static const char * const apply_usage[] = {\n@@ -18,6 +19,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)\n \tif (init_apply_state(&state, the_repository, prefix))\n \t\texit(128);\n \n+\tif (!the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \targc = apply_parse_options(argc, argv,\n \t\t\t\t   &state, &force_apply, &options,\n \t\t\t\t   apply_usage);\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 80261e43c7..89d89cf3f0 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -42,7 +42,7 @@ test_expect_success 'hash-object outside repository' '\n \ttest_cmp hash.expect hash.actual\n '\n \n-test_expect_failure 'apply a patch outside repository' '\n+test_expect_success 'apply a patch outside repository' '\n \t(\n \t\tcd non-repo &&\n \t\tcp ../nums.old nums &&\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494680","messageId":"xmqqbk59cnp6.fsf@gitster.g","threadId":"61463","inReplyTo":"20240513224127.2042052-4-gitster@pobox.com","subject":"Re: [PATCH v3 3/5] builtin/patch-id: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T23:11:01Z","receivedAt":"2024-05-13T23:11:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> We explicitly document patch IDs to be using SHA-1. Furthermore, patch\n> IDs are supposed to be stable for most of the part. But even with the\n> same input, the patch IDs will now be different depending on the repo's\n> configured object hash.\n>\n> Work around the issue by setting up SHA-1 when there was no startup\n> repository for now. This is arguably not the correct fix, but for now we\n> rather want to focus on getting the segfault fixed.\n\nI tend to agree that the use of SHA-256 in patch-id computation is a\nregression when we added the SHA-256 support.  Even with the\nGIT_DEFAULT_HASH_ALGORITHM fallback, we cannot fix it in an\ninitialized SHA-256 repository.\n\nWe should fix it but I agree that is probably outside the scope of\nthe \"oops, we leave the hash algorithm totally uninitialized\" fix.\n> +\t/*\n> +\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n> +\t * it means that the hash algorithm now depends on the object hash of\n> +\t * the repository, even though git-patch-id(1) clearly defines that\n> +\t * patch IDs always use SHA1.\n> +\t *\n> +\t * NEEDSWORK: This hack should be removed in favor of converting\n> +\t * the code that computes patch IDs to always use SHA1.\n> +\t */\n> +\tif (!startup_info->have_repository)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n\nHmph, in other places I did\n\n\tif (!the_hash_algo)\n\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n\nto find the case where we need a reasonable default.\n\nIs there a practical difference?  If there isn't we should\nstandardise one and use the same test consistently everywhere.\n\nNot that it matters for this particular case, where we in the longer\nterm should be hardcoding the use of SHA-1 even in SHA-256 repository\nfor the pupose of computing the patch-id.\n\nThanks.\n"},{"id":"494682","messageId":"xmqq7cfxcnlc.fsf@gitster.g","threadId":"61463","inReplyTo":"20240513224127.2042052-5-gitster@pobox.com","subject":"Re: [PATCH v3 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-13T23:13:19Z","receivedAt":"2024-05-13T23:13:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> From: Patrick Steinhardt <ps@pks.im>\n>\n> The git-hash-object(1) command allows users to hash an object even\n> without a repository. Starting with c8aed5e8da (repository: stop setting\n> SHA1 as the default object hash, 2024-05-07), this will make us hit an\n> uninitialized hash function, which subsequently leads to a segfault.\n>\n> Fix this by falling back to SHA-1 explicitly when running outside of a\n> Git repository. Users can use GIT_DEFAULT_HASH_ALGORITHM environment to\n> specify what hash algorithm they want, so arguably this code should not\n> be needed.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  builtin/hash-object.c   | 3 +++\n>  t/t1007-hash-object.sh  | 6 ++++++\n>  t/t1517-outside-repo.sh | 2 +-\n>  3 files changed, 10 insertions(+), 1 deletion(-)\n>\n> diff --git a/builtin/hash-object.c b/builtin/hash-object.c\n> index 82ca6d2bfd..c767414a0c 100644\n> --- a/builtin/hash-object.c\n> +++ b/builtin/hash-object.c\n> @@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n>  \telse\n>  \t\tprefix = setup_git_directory_gently(&nongit);\n>  \n> +\tif (nongit && !the_hash_algo)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n\nThis is slightly different from your version, which always used SHA-1\nwhen nongit is true, in the hope that it would make it more useful if\nthe user can say \"GIT_DEFAULT_HASH_ALGORITHM=sha256 git hash-objects\"\noutside a repository.  I am not 100% convinced it is better or we\nrather should aim for predictability that you'd always and only get\nSHA-1 outside a repository.\n\n\n"},{"id":"494684","messageId":"xmqqttj1b63u.fsf@gitster.g","threadId":"61463","inReplyTo":"1e010f798ce50e51100bd46564a69ddbd31d29ea.1715582857.git.ps@pks.im","subject":"Re: [PATCH 2/2] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T00:16:21Z","receivedAt":"2024-05-14T00:16:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> diff --git a/builtin/hash-object.c b/builtin/hash-object.c\n> index 82ca6d2bfd..0855f4f8aa 100644\n> --- a/builtin/hash-object.c\n> +++ b/builtin/hash-object.c\n> @@ -123,6 +123,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n>  \telse\n>  \t\tprefix = setup_git_directory_gently(&nongit);\n>  \n> +\t/*\n> +\t * TODO: Allow the hash algorithm to be configured by the user via a\n> +\t *       command line option when not using `-w`.\n> +\t */\n> +\tif (nongit)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n\nThis breaks t1007 when\n\n        linux-sha256)\n                export GIT_TEST_DEFAULT_HASH=sha256\n\nis in effect.\n"},{"id":"494687","messageId":"20240514011437.3779151-1-gitster@pobox.com","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"[PATCH v4 0/5] Fix use of uninitialized hash algorithms","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T01:14:32Z","receivedAt":"2024-05-14T01:14:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A change recently merged to 'next' stops us from defaulting to using\nSHA-1 unless other code (like a logic early in the start-up sequence\nto see what hash is being used in the repository we are working in)\nexplicitly sets it, leading to a (deliberate) crash of \"git\" when we\nforgot to cover certain code paths.\n\nIt turns out we have a few.  Notable ones are all operations that\nare designed to work outside a repository.  We should go over all\nsuch code paths and give them a reasonable default when there is one\navailable (e.g. for historical reasons, patch-id is documented to\nwork with SHA-1 hashes, so arguably it should do so everywhere, not\njust in SHA-1 repositories, but outside any repository), and when\nthere is none, we can use the existing GIT_DEFAULT_HASH environment\nvariable to let the user control the choice.\n\nIn this fourth iteration, I used the existing GIT_DEFAULT_HASH\nenvironment variable that has been used to allow users to opt into\nan early experiment of SHA-256 support.  I saw breakages in SHA-256\nCI jobs for earlier rounds of this series, but hopefully this is now\ngood to go.  Knock wood...\n\nJunio C Hamano (3):\n  setup: add an escape hatch for \"no more default hash algorithm\" change\n  t1517: test commands that are designed to be run outside repository\n  apply: fix uninitialized hash function\n\nPatrick Steinhardt (2):\n  builtin/patch-id: fix uninitialized hash function\n  builtin/hash-object: fix uninitialized hash function\n\n builtin/apply.c         |  4 +++\n builtin/hash-object.c   |  3 ++\n builtin/patch-id.c      | 13 +++++++++\n environment.h           |  1 +\n repository.c            | 40 +++++++++++++++++++++++++++\n setup.c                 |  2 --\n t/t1007-hash-object.sh  |  6 ++++\n t/t1517-outside-repo.sh | 61 +++++++++++++++++++++++++++++++++++++++++\n t/t4204-patch-id.sh     | 34 +++++++++++++++++++++++\n 9 files changed, 162 insertions(+), 2 deletions(-)\n create mode 100755 t/t1517-outside-repo.sh\n\nRange-diff against v3:\n1:  7adbf0cc5f ! 1:  3038f73e1c setup: add an escape hatch for \"no more default hash algorithm\" change\n    @@ Commit message\n         Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n         default object hash, 2024-05-07), to keep end-user systems still\n         broken when we have gap in our test coverage but yet give them an\n    -    escape hatch to set the GIT_TEST_DEFAULT_HASH_ALGORITHM environment\n    -    variable to \"sha1\" in order to revert to the previous behaviour.\n    +    escape hatch to set the GIT_DEFAULT_HASH environment variable to\n    +    \"sha1\" in order to revert to the previous behaviour.  This variable\n    +    has been in use for using SHA-256 hash by default, and it should be\n    +    a better fit than inventing a new and test-only knob.\n     \n         Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     \n    + ## environment.h ##\n    +@@ environment.h: const char *getenv_safe(struct strvec *argv, const char *name);\n    + #define GIT_OPTIONAL_LOCKS_ENVIRONMENT \"GIT_OPTIONAL_LOCKS\"\n    + #define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT \"GIT_TEXTDOMAINDIR\"\n    + #define GIT_ATTR_SOURCE_ENVIRONMENT \"GIT_ATTR_SOURCE\"\n    ++#define GIT_DEFAULT_HASH_ENVIRONMENT \"GIT_DEFAULT_HASH\"\n    + \n    + /*\n    +  * Environment variable used in handshaking the wire protocol.\n    +\n      ## repository.c ##\n    +@@\n    + #include \"git-compat-util.h\"\n    + #include \"abspath.h\"\n    ++#include \"environment.h\"\n    + #include \"repository.h\"\n    + #include \"object-store-ll.h\"\n    + #include \"config.h\"\n     @@\n      static struct repository the_repo;\n      struct repository *the_repository = &the_repo;\n    @@ repository.c\n     +\tconst char *hash_name;\n     +\tint algo;\n     +\n    -+\thash_name = getenv(\"GIT_DEFAULT_HASH_ALGORITHM\");\n    ++\thash_name = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);\n     +\tif (!hash_name)\n     +\t\treturn;\n     +\talgo = hash_algo_by_name(hash_name);\n    ++\n    ++\t/*\n    ++\t * NEEDSWORK: after all, falling back to SHA-1 by assigning\n    ++\t * GIT_HASH_SHA1 to algo here, instead of returning, may give\n    ++\t * us better behaviour.\n    ++\t */\n     +\tif (algo == GIT_HASH_UNKNOWN)\n     +\t\treturn;\n    ++\n     +\trepo_set_hash_algo(repo, algo);\n     +}\n     +\n    @@ repository.c: void initialize_repository(struct repository *repo)\n     +\t * giving them an appropriate default individually; any\n     +\t * unconverted codepath that tries to access the_hash_algo\n     +\t * will thus fail.  The end-users however have an escape hatch\n    -+\t * to set GIT_DEFAULT_HASH_ALGORITHM environment variable to\n    -+\t * \"sha1\" get back the old behaviour of defaulting to SHA-1.\n    ++\t * to set GIT_DEFAULT_HASH environment variable to \"sha1\" get\n    ++\t * back the old behaviour of defaulting to SHA-1.\n     +\t */\n     +\tif (repo == the_repository)\n     +\t\tset_default_hash_algo(repo);\n      }\n      \n      static void expand_base_dir(char **out, const char *in,\n    +\n    + ## setup.c ##\n    +@@ setup.c: int daemonize(void)\n    + #define TEST_FILEMODE 1\n    + #endif\n    + \n    +-#define GIT_DEFAULT_HASH_ENVIRONMENT \"GIT_DEFAULT_HASH\"\n    +-\n    + static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,\n    + \t\t\t     DIR *dir)\n    + {\n2:  c40b2bc7b5 ! 2:  e56ae68961 t1517: test commands that are designed to be run outside repository\n    @@ t/t1517-outside-repo.sh (new)\n     +TEST_PASSES_SANITIZE_LEAK=true\n     +. ./test-lib.sh\n     +\n    -+# Do not use the end-user workaround for this test.\n    -+# GIT_DEFAULT_HASH_ALGORITHM=sha1; export GIT_DEFAULT_HASH_ALGORITHM\n    -+\n     +test_expect_success 'set up a non-repo directory and test file' '\n     +\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n     +\texport GIT_CEILING_DIRECTORIES &&\n3:  48d83fe1fd ! 3:  e1ae0e95fc builtin/patch-id: fix uninitialized hash function\n    @@ builtin/patch-id.c: int cmd_patch_id(int argc, const char **argv, const char *pr\n     +\t * NEEDSWORK: This hack should be removed in favor of converting\n     +\t * the code that computes patch IDs to always use SHA1.\n     +\t */\n    -+\tif (!startup_info->have_repository)\n    ++\tif (!the_hash_algo)\n     +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n     +\n      \tgenerate_id_list(opts ? opts > 1 : config.stable,\n4:  a5bf0dfb0a ! 4:  1c8ce0d024 builtin/hash-object: fix uninitialized hash function\n    @@ Commit message\n         SHA1 as the default object hash, 2024-05-07), this will make us hit an\n         uninitialized hash function, which subsequently leads to a segfault.\n     \n    -    Fix this by falling back to SHA-1 explicitly when running outside of a\n    -    Git repository. Users can use GIT_DEFAULT_HASH_ALGORITHM environment to\n    -    specify what hash algorithm they want, so arguably this code should not\n    -    be needed.\n    +    Fix this by falling back to SHA-1 explicitly when running outside of\n    +    a Git repository. Users can use GIT_DEFAULT_HASH environment to\n    +    specify what hash algorithm they want, so arguably this code should\n    +    not be needed.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n         Signed-off-by: Junio C Hamano <gitster@pobox.com>\n5:  2b9e486c3f = 5:  5b0ec43757 apply: fix uninitialized hash function\n"},{"id":"494688","messageId":"20240514011437.3779151-2-gitster@pobox.com","threadId":"61463","inReplyTo":"20240514011437.3779151-1-gitster@pobox.com","subject":"[PATCH v4 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T01:14:33Z","receivedAt":"2024-05-14T01:14:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Partially revert c8aed5e8 (repository: stop setting SHA1 as the\ndefault object hash, 2024-05-07), to keep end-user systems still\nbroken when we have gap in our test coverage but yet give them an\nescape hatch to set the GIT_DEFAULT_HASH environment variable to\n\"sha1\" in order to revert to the previous behaviour.  This variable\nhas been in use for using SHA-256 hash by default, and it should be\na better fit than inventing a new and test-only knob.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n environment.h |  1 +\n repository.c  | 40 ++++++++++++++++++++++++++++++++++++++++\n setup.c       |  2 --\n 3 files changed, 41 insertions(+), 2 deletions(-)\n\ndiff --git a/environment.h b/environment.h\nindex 05fd94d7be..deaa29408f 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -56,6 +56,7 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n #define GIT_OPTIONAL_LOCKS_ENVIRONMENT \"GIT_OPTIONAL_LOCKS\"\n #define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT \"GIT_TEXTDOMAINDIR\"\n #define GIT_ATTR_SOURCE_ENVIRONMENT \"GIT_ATTR_SOURCE\"\n+#define GIT_DEFAULT_HASH_ENVIRONMENT \"GIT_DEFAULT_HASH\"\n \n /*\n  * Environment variable used in handshaking the wire protocol.\ndiff --git a/repository.c b/repository.c\nindex 15c10015b0..f912ee9a7c 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -1,5 +1,6 @@\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n+#include \"environment.h\"\n #include \"repository.h\"\n #include \"object-store-ll.h\"\n #include \"config.h\"\n@@ -19,6 +20,27 @@\n static struct repository the_repo;\n struct repository *the_repository = &the_repo;\n \n+static void set_default_hash_algo(struct repository *repo)\n+{\n+\tconst char *hash_name;\n+\tint algo;\n+\n+\thash_name = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);\n+\tif (!hash_name)\n+\t\treturn;\n+\talgo = hash_algo_by_name(hash_name);\n+\n+\t/*\n+\t * NEEDSWORK: after all, falling back to SHA-1 by assigning\n+\t * GIT_HASH_SHA1 to algo here, instead of returning, may give\n+\t * us better behaviour.\n+\t */\n+\tif (algo == GIT_HASH_UNKNOWN)\n+\t\treturn;\n+\n+\trepo_set_hash_algo(repo, algo);\n+}\n+\n void initialize_repository(struct repository *repo)\n {\n \trepo->objects = raw_object_store_new();\n@@ -26,6 +48,24 @@ void initialize_repository(struct repository *repo)\n \trepo->parsed_objects = parsed_object_pool_new();\n \tALLOC_ARRAY(repo->index, 1);\n \tindex_state_init(repo->index, repo);\n+\n+\t/*\n+\t * When a command runs inside a repository, it learns what\n+\t * hash algorithm is in use from the repository, but some\n+\t * commands are designed to work outside a repository, yet\n+\t * they want to access the_hash_algo, if only for the length\n+\t * of the hashed value to see if their input looks like a\n+\t * plausible hash value.\n+\t *\n+\t * We are in the process of identifying the codepaths and\n+\t * giving them an appropriate default individually; any\n+\t * unconverted codepath that tries to access the_hash_algo\n+\t * will thus fail.  The end-users however have an escape hatch\n+\t * to set GIT_DEFAULT_HASH environment variable to \"sha1\" get\n+\t * back the old behaviour of defaulting to SHA-1.\n+\t */\n+\tif (repo == the_repository)\n+\t\tset_default_hash_algo(repo);\n }\n \n static void expand_base_dir(char **out, const char *in,\ndiff --git a/setup.c b/setup.c\nindex 7c996659bd..d084703465 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -1840,8 +1840,6 @@ int daemonize(void)\n #define TEST_FILEMODE 1\n #endif\n \n-#define GIT_DEFAULT_HASH_ENVIRONMENT \"GIT_DEFAULT_HASH\"\n-\n static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,\n \t\t\t     DIR *dir)\n {\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494689","messageId":"20240514011437.3779151-3-gitster@pobox.com","threadId":"61463","inReplyTo":"20240514011437.3779151-1-gitster@pobox.com","subject":"[PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T01:14:34Z","receivedAt":"2024-05-14T01:14:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A few commands, like \"git apply\" and \"git patch-id\", have been\nbroken with a recent change to stop setting the default hash\nalgorithm to SHA-1.  Test them and fix them in later commits.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1517-outside-repo.sh | 61 +++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 61 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nnew file mode 100755\nindex 0000000000..e0fd495ec1\n--- /dev/null\n+++ b/t/t1517-outside-repo.sh\n@@ -0,0 +1,61 @@\n+#!/bin/sh\n+\n+test_description='check random commands outside repo'\n+\n+TEST_PASSES_SANITIZE_LEAK=true\n+. ./test-lib.sh\n+\n+test_expect_success 'set up a non-repo directory and test file' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir non-repo &&\n+\t(\n+\t\tcd non-repo &&\n+\t\t# confirm that git does not find a repo\n+\t\ttest_must_fail git rev-parse --git-dir\n+\t) &&\n+\ttest_write_lines one two three four >nums &&\n+\tgit add nums &&\n+\tcp nums nums.old &&\n+\ttest_write_lines five >>nums &&\n+\tgit diff >sample.patch\n+'\n+\n+test_expect_failure 'compute a patch-id outside repository' '\n+\tgit patch-id <sample.patch >patch-id.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit patch-id <../sample.patch >../patch-id.actual\n+\t) &&\n+\ttest_cmp patch-id.expect patch-id.actual\n+'\n+\n+test_expect_failure 'hash-object outside repository' '\n+\tgit hash-object --stdin <sample.patch >hash.expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tgit hash-object --stdin <../sample.patch >../hash.actual\n+\t) &&\n+\ttest_cmp hash.expect hash.actual\n+'\n+\n+test_expect_failure 'apply a patch outside repository' '\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit apply ../sample.patch\n+\t) &&\n+\ttest_cmp nums non-repo/nums\n+'\n+\n+test_expect_success 'grep outside repository' '\n+\tgit grep --cached two >expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit grep --no-index two >../actual\n+\t) &&\n+\ttest_cmp expect actual\n+'\n+\n+test_done\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494690","messageId":"20240514011437.3779151-4-gitster@pobox.com","threadId":"61463","inReplyTo":"20240514011437.3779151-1-gitster@pobox.com","subject":"[PATCH v4 3/5] builtin/patch-id: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T01:14:35Z","receivedAt":"2024-05-14T01:14:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nIn c8aed5e8da (repository: stop setting SHA1 as the default object hash,\n2024-05-07), we have adapted `initialize_repository()` to no longer set\nup a default hash function. As this function is also used to set up\n`the_repository`, the consequence is that `the_hash_algo` will now by\ndefault be a `NULL` pointer unless the hash algorithm was configured\nproperly. This is done as a mechanism to detect cases where we may be\nusing the wrong hash function by accident.\n\nThis change now causes git-patch-id(1) to segfault when it's run outside\nof a repository. As this command can read diffs from stdin, it does not\nnecessarily need a repository, but then relies on `the_hash_algo` to\ncompute the patch ID itself.\n\nIt is somewhat dubious that git-patch-id(1) relies on `the_hash_algo` in\nthe first place. Quoting its manpage:\n\n    A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs\n    associated with a patch, with line numbers ignored. As such, it’s\n    \"reasonably stable\", but at the same time also reasonably unique,\n    i.e., two patches that have the same \"patch ID\" are almost\n    guaranteed to be the same thing.\n\nWe explicitly document patch IDs to be using SHA-1. Furthermore, patch\nIDs are supposed to be stable for most of the part. But even with the\nsame input, the patch IDs will now be different depending on the repo's\nconfigured object hash.\n\nWork around the issue by setting up SHA-1 when there was no startup\nrepository for now. This is arguably not the correct fix, but for now we\nrather want to focus on getting the segfault fixed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/patch-id.c      | 13 +++++++++++++\n t/t1517-outside-repo.sh |  2 +-\n t/t4204-patch-id.sh     | 34 ++++++++++++++++++++++++++++++++++\n 3 files changed, 48 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/patch-id.c b/builtin/patch-id.c\nindex 3894d2b970..583099cacf 100644\n--- a/builtin/patch-id.c\n+++ b/builtin/patch-id.c\n@@ -5,6 +5,7 @@\n #include \"hash.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n+#include \"setup.h\"\n \n static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)\n {\n@@ -237,6 +238,18 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, builtin_patch_id_options,\n \t\t\t     patch_id_usage, 0);\n \n+\t/*\n+\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n+\t * it means that the hash algorithm now depends on the object hash of\n+\t * the repository, even though git-patch-id(1) clearly defines that\n+\t * patch IDs always use SHA1.\n+\t *\n+\t * NEEDSWORK: This hack should be removed in favor of converting\n+\t * the code that computes patch IDs to always use SHA1.\n+\t */\n+\tif (!the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tgenerate_id_list(opts ? opts > 1 : config.stable,\n \t\t\t opts ? opts == 3 : config.verbatim);\n \treturn 0;\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex e0fd495ec1..ac5f3191cc 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -21,7 +21,7 @@ test_expect_success 'set up a non-repo directory and test file' '\n \tgit diff >sample.patch\n '\n \n-test_expect_failure 'compute a patch-id outside repository' '\n+test_expect_success 'compute a patch-id outside repository' '\n \tgit patch-id <sample.patch >patch-id.expect &&\n \t(\n \t\tcd non-repo &&\ndiff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh\nindex a7fa94ce0a..605faea0c7 100755\n--- a/t/t4204-patch-id.sh\n+++ b/t/t4204-patch-id.sh\n@@ -310,4 +310,38 @@ test_expect_success 'patch-id handles diffs with one line of before/after' '\n \ttest_config patchid.stable true &&\n \tcalc_patch_id diffu1stable <diffu1\n '\n+\n+test_expect_failure 'patch-id computes same ID with different object hashes' '\n+\ttest_when_finished \"rm -rf repo-sha1 repo-sha256\" &&\n+\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\n+\tgit init --object-format=sha1 repo-sha1 &&\n+\tgit -C repo-sha1 patch-id <diff >patch-id-sha1 &&\n+\tgit init --object-format=sha256 repo-sha256 &&\n+\tgit -C repo-sha256 patch-id <diff >patch-id-sha256 &&\n+\ttest_cmp patch-id-sha1 patch-id-sha256\n+'\n+\n+test_expect_success 'patch-id without repository' '\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\tnongit git patch-id <diff\n+'\n+\n test_done\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494691","messageId":"20240514011437.3779151-5-gitster@pobox.com","threadId":"61463","inReplyTo":"20240514011437.3779151-1-gitster@pobox.com","subject":"[PATCH v4 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T01:14:36Z","receivedAt":"2024-05-14T01:14:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nThe git-hash-object(1) command allows users to hash an object even\nwithout a repository. Starting with c8aed5e8da (repository: stop setting\nSHA1 as the default object hash, 2024-05-07), this will make us hit an\nuninitialized hash function, which subsequently leads to a segfault.\n\nFix this by falling back to SHA-1 explicitly when running outside of\na Git repository. Users can use GIT_DEFAULT_HASH environment to\nspecify what hash algorithm they want, so arguably this code should\nnot be needed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/hash-object.c   | 3 +++\n t/t1007-hash-object.sh  | 6 ++++++\n t/t1517-outside-repo.sh | 2 +-\n 3 files changed, 10 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex 82ca6d2bfd..c767414a0c 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n \telse\n \t\tprefix = setup_git_directory_gently(&nongit);\n \n+\tif (nongit && !the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (vpath && prefix) {\n \t\tvpath_free = prefix_filename(prefix, vpath);\n \t\tvpath = vpath_free;\ndiff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh\nindex 64aea38486..4c138c6ca4 100755\n--- a/t/t1007-hash-object.sh\n+++ b/t/t1007-hash-object.sh\n@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '\n \techo example | git hash-object -t $t --literally --stdin\n '\n \n+test_expect_success '--stdin outside of repository' '\n+\tnongit git hash-object --stdin <hello >actual &&\n+\techo \"$(test_oid hello)\" >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex ac5f3191cc..854bb8f343 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -30,7 +30,7 @@ test_expect_success 'compute a patch-id outside repository' '\n \ttest_cmp patch-id.expect patch-id.actual\n '\n \n-test_expect_failure 'hash-object outside repository' '\n+test_expect_success 'hash-object outside repository' '\n \tgit hash-object --stdin <sample.patch >hash.expect &&\n \t(\n \t\tcd non-repo &&\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494692","messageId":"20240514011437.3779151-6-gitster@pobox.com","threadId":"61463","inReplyTo":"20240514011437.3779151-1-gitster@pobox.com","subject":"[PATCH v4 5/5] apply: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T01:14:37Z","receivedAt":"2024-05-14T01:15:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git apply\" can work outside a repository as a better \"GNU patch\",\nbut when it does so, it still assumed that it can access\nthe_hash_algo, which is no longer true in the new world order.\n\nMake sure we explicitly fall back to SHA-1 algorithm for backward\ncompatibility.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/apply.c         | 4 ++++\n t/t1517-outside-repo.sh | 2 +-\n 2 files changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 861a01910c..e9175f820f 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -1,6 +1,7 @@\n #include \"builtin.h\"\n #include \"gettext.h\"\n #include \"repository.h\"\n+#include \"hash.h\"\n #include \"apply.h\"\n \n static const char * const apply_usage[] = {\n@@ -18,6 +19,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)\n \tif (init_apply_state(&state, the_repository, prefix))\n \t\texit(128);\n \n+\tif (!the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \targc = apply_parse_options(argc, argv,\n \t\t\t\t   &state, &force_apply, &options,\n \t\t\t\t   apply_usage);\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 854bb8f343..6f32a40c6d 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -39,7 +39,7 @@ test_expect_success 'hash-object outside repository' '\n \ttest_cmp hash.expect hash.actual\n '\n \n-test_expect_failure 'apply a patch outside repository' '\n+test_expect_success 'apply a patch outside repository' '\n \t(\n \t\tcd non-repo &&\n \t\tcp ../nums.old nums &&\n-- \n2.45.0-145-g3e4a232f6e\n\n"},{"id":"494693","messageId":"ZkLpN6UaI_jj2zDg@tanuki","threadId":"61463","inReplyTo":"xmqqbk59cnp6.fsf@gitster.g","subject":"Re: [PATCH v3 3/5] builtin/patch-id: fix uninitialized hash function","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-14T04:31:51Z","receivedAt":"2024-05-14T04:31:58Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 13, 2024 at 04:11:01PM -0700, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n[snip]\n> > +\t/*\n> > +\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n> > +\t * it means that the hash algorithm now depends on the object hash of\n> > +\t * the repository, even though git-patch-id(1) clearly defines that\n> > +\t * patch IDs always use SHA1.\n> > +\t *\n> > +\t * NEEDSWORK: This hack should be removed in favor of converting\n> > +\t * the code that computes patch IDs to always use SHA1.\n> > +\t */\n> > +\tif (!startup_info->have_repository)\n> > +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n> \n> Hmph, in other places I did\n> \n> \tif (!the_hash_algo)\n> \t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n> \n> to find the case where we need a reasonable default.\n> \n> Is there a practical difference?  If there isn't we should\n> standardise one and use the same test consistently everywhere.\n> \n> Not that it matters for this particular case, where we in the longer\n> term should be hardcoding the use of SHA-1 even in SHA-256 repository\n> for the pupose of computing the patch-id.\n\nTo the best of my knowledge there isn't. What I prefer about my approach\nis that it explicitly points out that this is conditional on whether or\nnot we have a repository. But in the end I don't mind much which of both\nversions we use.\n\nPatrick\n"},{"id":"494694","messageId":"ZkLpSW6TNcpKpg-V@tanuki","threadId":"61463","inReplyTo":"20240514011437.3779151-2-gitster@pobox.com","subject":"Re: [PATCH v4 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-14T04:32:09Z","receivedAt":"2024-05-14T04:32:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 13, 2024 at 06:14:33PM -0700, Junio C Hamano wrote:\n[snip]\n> diff --git a/repository.c b/repository.c\n> index 15c10015b0..f912ee9a7c 100644\n> --- a/repository.c\n> +++ b/repository.c\n> @@ -1,5 +1,6 @@\n>  #include \"git-compat-util.h\"\n>  #include \"abspath.h\"\n> +#include \"environment.h\"\n>  #include \"repository.h\"\n>  #include \"object-store-ll.h\"\n>  #include \"config.h\"\n> @@ -19,6 +20,27 @@\n>  static struct repository the_repo;\n>  struct repository *the_repository = &the_repo;\n>  \n> +static void set_default_hash_algo(struct repository *repo)\n> +{\n> +\tconst char *hash_name;\n> +\tint algo;\n> +\n> +\thash_name = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);\n> +\tif (!hash_name)\n> +\t\treturn;\n> +\talgo = hash_algo_by_name(hash_name);\n> +\n> +\t/*\n> +\t * NEEDSWORK: after all, falling back to SHA-1 by assigning\n> +\t * GIT_HASH_SHA1 to algo here, instead of returning, may give\n> +\t * us better behaviour.\n> +\t */\n> +\tif (algo == GIT_HASH_UNKNOWN)\n> +\t\treturn;\n> +\n> +\trepo_set_hash_algo(repo, algo);\n> +}\n\nThe problem with reusing \"GIT_DEFAULT_HASH\" is that we unconditionally\nset it in our test suite in \"test-lib.sh\". This will have the effect\nthat we will never hit segfaults in our tests because we always end up\nsetting up the default hash, whereas our users now will.\n\nI would propose to revert this back to the first iteration you had,\nwhere the workaround only enables the SHA1 fallback. No users have yet\ncomplained about the inability to pick the hash algo outside of a repo,\nindicating that it's not widely used. And when they complain, there is\nmore motivation to fix this properly by adding a `--object-hash=` switch\nto the respective commands so that a user can pick the desired object\nhash.\n\nPatrick\n"},{"id":"494695","messageId":"ZkLpTwNgFGFyC4_N@tanuki","threadId":"61463","inReplyTo":"20240514011437.3779151-3-gitster@pobox.com","subject":"Re: [PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-14T04:32:15Z","receivedAt":"2024-05-14T04:32:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 13, 2024 at 06:14:34PM -0700, Junio C Hamano wrote:\n> A few commands, like \"git apply\" and \"git patch-id\", have been\n> broken with a recent change to stop setting the default hash\n> algorithm to SHA-1.  Test them and fix them in later commits.\n\nIs there a specific reason why this needs a whole patch suite, as\nopposed to adding the tests to the respective test suites of the\ncommands?\n\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  t/t1517-outside-repo.sh | 61 +++++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 61 insertions(+)\n>  create mode 100755 t/t1517-outside-repo.sh\n> \n> diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\n> new file mode 100755\n> index 0000000000..e0fd495ec1\n> --- /dev/null\n> +++ b/t/t1517-outside-repo.sh\n> @@ -0,0 +1,61 @@\n> +#!/bin/sh\n> +\n> +test_description='check random commands outside repo'\n> +\n> +TEST_PASSES_SANITIZE_LEAK=true\n> +. ./test-lib.sh\n> +\n> +test_expect_success 'set up a non-repo directory and test file' '\n> +\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n> +\texport GIT_CEILING_DIRECTORIES &&\n> +\tmkdir non-repo &&\n> +\t(\n> +\t\tcd non-repo &&\n> +\t\t# confirm that git does not find a repo\n> +\t\ttest_must_fail git rev-parse --git-dir\n> +\t) &&\n> +\ttest_write_lines one two three four >nums &&\n> +\tgit add nums &&\n> +\tcp nums nums.old &&\n> +\ttest_write_lines five >>nums &&\n> +\tgit diff >sample.patch\n> +'\n\nWe have the \"nongit\" command that does most of this for us.\n\nPatrick\n"},{"id":"494696","messageId":"ZkLpVSVv1XPz-D8v@tanuki","threadId":"61463","inReplyTo":"xmqq7cfxcnlc.fsf@gitster.g","subject":"Re: [PATCH v3 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-14T04:32:21Z","receivedAt":"2024-05-14T04:32:24Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 13, 2024 at 04:13:19PM -0700, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > From: Patrick Steinhardt <ps@pks.im>\n> >\n> > The git-hash-object(1) command allows users to hash an object even\n> > without a repository. Starting with c8aed5e8da (repository: stop setting\n> > SHA1 as the default object hash, 2024-05-07), this will make us hit an\n> > uninitialized hash function, which subsequently leads to a segfault.\n> >\n> > Fix this by falling back to SHA-1 explicitly when running outside of a\n> > Git repository. Users can use GIT_DEFAULT_HASH_ALGORITHM environment to\n> > specify what hash algorithm they want, so arguably this code should not\n> > be needed.\n> >\n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> > Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> > ---\n> >  builtin/hash-object.c   | 3 +++\n> >  t/t1007-hash-object.sh  | 6 ++++++\n> >  t/t1517-outside-repo.sh | 2 +-\n> >  3 files changed, 10 insertions(+), 1 deletion(-)\n> >\n> > diff --git a/builtin/hash-object.c b/builtin/hash-object.c\n> > index 82ca6d2bfd..c767414a0c 100644\n> > --- a/builtin/hash-object.c\n> > +++ b/builtin/hash-object.c\n> > @@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n> >  \telse\n> >  \t\tprefix = setup_git_directory_gently(&nongit);\n> >  \n> > +\tif (nongit && !the_hash_algo)\n> > +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n> \n> This is slightly different from your version, which always used SHA-1\n> when nongit is true, in the hope that it would make it more useful if\n> the user can say \"GIT_DEFAULT_HASH_ALGORITHM=sha256 git hash-objects\"\n> outside a repository.  I am not 100% convinced it is better or we\n> rather should aim for predictability that you'd always and only get\n> SHA-1 outside a repository.\n\nI'd prefer the latter -- always use SHA-1. As you say, it's easier to\nunderstand and doesn't create implicit mechanisms that we'll have to\nmaintain going forward. Also, users didn't have a desire yet to pick a\ndifferent algorithm than SHA-1, which probably also comes from the fact\nthat SHA-256 repositories are still scarce.\n\nEventually, we should then add a new option `--object-hash=` to\ngit-hash-object(1) and other commands that may run outside of a Git\nrepository to let the user pick their desired hash.\n\nPatrick\n"},{"id":"494719","messageId":"xmqqseyk77sl.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkLpSW6TNcpKpg-V@tanuki","subject":"Re: [PATCH v4 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T15:05:46Z","receivedAt":"2024-05-14T15:05:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> The problem with reusing \"GIT_DEFAULT_HASH\" is that we unconditionally\n> set it in our test suite in \"test-lib.sh\". This will have the effect\n> that we will never hit segfaults in our tests because we always end up\n> setting up the default hash, whereas our users now will.\n\nI tried the version you posted with only SHA-1 fallback and it\nfailed with SHA256 CI jobs, and eventually came up with using the\nexisting environment variable.\n\nThe variable is the perfect fit in the longer term for our purpose.\nIt is what the end-users will set, not for papering over remaining\nbugs from the \"no longer there is a fallback default\" change, but\nfor telling Git that they want to use sha256 repositories.\n\nWith GIT_DEFAULT_HASH set to sha256, we will be testing a\nconfiguration that is very close to those end-users.\n\nThere probably are four cases we need to check:\n\n - In a repository, invocations of commands that should honor the\n   hash function that is in use by the repository (i.e. this is true\n   for most commands and their invocations).\n\n - In a repository, invocations of commands that should ignore the\n   repository settings and always use SHA-1 (i.e. proposed fix to\n   patch-id).\n\n - Outside a repository, invocations with GIT_DEFAULT_HASH set\n   should probably parallel the above two, as if GIT_DEFAULT_HASH\n   came from the repository.\n\n - Outside a repository, invocations without GIT_DEFAULT_HASH set\n   should all default to SHA-1???\n\nThe last combination cannot be tested UNLESS we unset GIT_DEFAULT_HASH\nthat is given by test-lib.sh, but that can easily be arranged, now\nwe have one primary/central place that tests out-of-repository\ninvocations of various commands in t1517.\n\nAnd using the existing environment variable has an added benefit\nthat we do not have to add an extra option to random commands.\n"},{"id":"494720","messageId":"xmqqo79877oc.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkLpTwNgFGFyC4_N@tanuki","subject":"Re: [PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T15:08:19Z","receivedAt":"2024-05-14T15:08:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Is there a specific reason why this needs a whole patch suite, as\n> opposed to adding the tests to the respective test suites of the\n> commands?\n\nYes, testing out-of-repository operations needs certain trick and\npeople forget to write such tests using the GIT_CEILING_DIRECTORIES\nmechanism.  Having one place where we have an enumeration of\ncommands that are designed to be usable outside repository is a\nhandy way to make sure that we have enough test coverage.  It would\nmake it easy to control how GIT_DEFAULT_HASH environment is set\nduring these tests to have them in all one place.\n"},{"id":"494723","messageId":"xmqqcypo5r27.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkLpN6UaI_jj2zDg@tanuki","subject":"Re: [PATCH v3 3/5] builtin/patch-id: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T15:52:32Z","receivedAt":"2024-05-14T15:52:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n>> Hmph, in other places I did\n>> \n>> \tif (!the_hash_algo)\n>> \t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n>> \n>> to find the case where we need a reasonable default.\n>> \n>> Is there a practical difference?  If there isn't we should\n>> standardise one and use the same test consistently everywhere.\n>> ...\n>\n> To the best of my knowledge there isn't. What I prefer about my approach\n> is that it explicitly points out that this is conditional on whether or\n> not we have a repository. But in the end I don't mind much which of both\n> versions we use.\n\nAh, that makes sense, and it is quite subjective but makes certain\nsense.\n\nThe reason I prefered to check \"the_hash_algo\" is very much the\nopposite.  In this particular decision to call (or not call)\nset_hash_algo(), we only care if the_hash_algo is not yet set, and\nthat is why the_hash_algo is checked.\n\nSpecifically, we do not care *why* it is still unset; in the current\ncodebase, the most likely reason why we do not have the_hash_algo\nset might be that we haven't found the repository yet, but we do not\nhave to rely on that assumption to hold true.  It would help\nmaintainability into the future where the_hash_algo is set already\nbefore we come here when outside a repository, or vice versa.\n"},{"id":"494724","messageId":"xmqq8r0c5qwu.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkLpVSVv1XPz-D8v@tanuki","subject":"Re: [PATCH v3 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T15:55:45Z","receivedAt":"2024-05-14T15:55:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> I'd prefer the latter -- always use SHA-1. As you say, it's easier to\n> understand and doesn't create implicit mechanisms that we'll have to\n> maintain going forward. Also, users didn't have a desire yet to pick a\n> different algorithm than SHA-1, which probably also comes from the fact\n> that SHA-256 repositories are still scarce.\n> ...\n> Eventually, we should then add a new option `--object-hash=` to\n> git-hash-object(1) and other commands that may run outside of a Git\n> repository to let the user pick their desired hash.\n\nIf we were planning to allow using something other than SHA-1 in the\nfuture, then I do not think I agree with your argument.  We can use\nthe same GIT_DEFAULT_HASH mechanism to specify what hash to use without\nlater adding an extra option just fine.\n\n"},{"id":"494728","messageId":"xmqqikzg48hm.fsf@gitster.g","threadId":"61463","inReplyTo":"20240514011437.3779151-2-gitster@pobox.com","subject":"Re: [PATCH v4 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-14T17:19:01Z","receivedAt":"2024-05-14T17:19:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n> default object hash, 2024-05-07), to keep end-user systems still\n> broken when we have gap in our test coverage but yet give them an\n> escape hatch to set the GIT_DEFAULT_HASH environment variable to\n> \"sha1\" in order to revert to the previous behaviour.  This variable\n> has been in use for using SHA-256 hash by default, and it should be\n> a better fit than inventing a new and test-only knob.\n\nHaving done all of this, I actually am very tempted to add the\n\"always default to SHA-1\" back as a fallback position to the\nset_default_hash_algo() function.  We know we are going to get the\nright hash algorithm when working in the repository, so the only\ncase the default matters in practice is when working outside the\nrepository.\n\nWe already have such a custom code for \"git diff --no-index\", and we\nare adding a few more back in here, but they can disappear if we had\ncode to set the fallback default when GIT_DEFAULT_HASH does not\nexist here.  The \"always use SHA-1 regardless of the hash used by\nthe repository\" code like \"patch-id\" should not depend on such a\nfallback default but should have its own code to explicitly set it.\n\nAs the user can tweak what algorithm they want if the wanted to, it\ndoes not sound too bad to have a fallback default when the user did\nnot choose.\n"},{"id":"494808","messageId":"ZkSpXnsyxEf6p_4R@tanuki","threadId":"61463","inReplyTo":"xmqqikzg48hm.fsf@gitster.g","subject":"Re: [PATCH v4 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-15T12:23:58Z","receivedAt":"2024-05-15T12:24:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, May 14, 2024 at 10:19:01AM -0700, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n> > default object hash, 2024-05-07), to keep end-user systems still\n> > broken when we have gap in our test coverage but yet give them an\n> > escape hatch to set the GIT_DEFAULT_HASH environment variable to\n> > \"sha1\" in order to revert to the previous behaviour.  This variable\n> > has been in use for using SHA-256 hash by default, and it should be\n> > a better fit than inventing a new and test-only knob.\n> \n> Having done all of this, I actually am very tempted to add the\n> \"always default to SHA-1\" back as a fallback position to the\n> set_default_hash_algo() function.  We know we are going to get the\n> right hash algorithm when working in the repository, so the only\n> case the default matters in practice is when working outside the\n> repository.\n> \n> We already have such a custom code for \"git diff --no-index\", and we\n> are adding a few more back in here, but they can disappear if we had\n> code to set the fallback default when GIT_DEFAULT_HASH does not\n> exist here.  The \"always use SHA-1 regardless of the hash used by\n> the repository\" code like \"patch-id\" should not depend on such a\n> fallback default but should have its own code to explicitly set it.\n> \n> As the user can tweak what algorithm they want if the wanted to, it\n> does not sound too bad to have a fallback default when the user did\n> not choose.\n\nI think that this is going into the wrong direction. The patches that we\nhave added surface real issues. If we now unconditionally add back the\nfallback to SHA-1, then we only punt those issues further down the road\nto the point in time where we drop `the_hash_algo` and/or\n`the_repository`. All the issues that were surfaced until now are\ntechnical debt, and the proposed fixes have been documented with a\n\"TODO\" item that they need more work.\n\nIn some cases it's as simple as adding in an option to the respective\ncommand that lets the user pick the hash algorithm, and I do not think\nthat GIT_DEFAULT_HASH is a proper replacement for that. In other cases\nlike for git-patch-id(1) the issue runs deeper and we need to refactor\nthe whole subsystem to stop relying on `the_hash_algo` altogether.\n\nPatrick\n"},{"id":"494809","messageId":"ZkSpk3v2kRsdOcbQ@tanuki","threadId":"61463","inReplyTo":"xmqqo79877oc.fsf@gitster.g","subject":"Re: [PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-15T12:24:51Z","receivedAt":"2024-05-15T12:24:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, May 14, 2024 at 08:08:19AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > Is there a specific reason why this needs a whole patch suite, as\n> > opposed to adding the tests to the respective test suites of the\n> > commands?\n> \n> Yes, testing out-of-repository operations needs certain trick and\n> people forget to write such tests using the GIT_CEILING_DIRECTORIES\n> mechanism.  Having one place where we have an enumeration of\n> commands that are designed to be usable outside repository is a\n> handy way to make sure that we have enough test coverage.  It would\n> make it easy to control how GIT_DEFAULT_HASH environment is set\n> during these tests to have them in all one place.\n\nWe already have the \"nogit\" command that neatly encapsulates all of this\nlogic, so the trickery is contained in a single spot in practice.\n\nPatrick\n"},{"id":"494816","messageId":"xmqq4jaz2may.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkSpk3v2kRsdOcbQ@tanuki","subject":"Re: [PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-15T14:15:49Z","receivedAt":"2024-05-15T14:15:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Tue, May 14, 2024 at 08:08:19AM -0700, Junio C Hamano wrote:\n>> Patrick Steinhardt <ps@pks.im> writes:\n>> \n>> > Is there a specific reason why this needs a whole patch suite, as\n>> > opposed to adding the tests to the respective test suites of the\n>> > commands?\n>> \n>> Yes, testing out-of-repository operations needs certain trick and\n>> people forget to write such tests using the GIT_CEILING_DIRECTORIES\n>> mechanism.  Having one place where we have an enumeration of\n>> commands that are designed to be usable outside repository is a\n>> handy way to make sure that we have enough test coverage.  It would\n>> make it easy to control how GIT_DEFAULT_HASH environment is set\n>> during these tests to have them in all one place.\n>\n> We already have the \"nogit\" command that neatly encapsulates all of this\n> logic, so the trickery is contained in a single spot in practice.\n\nHeh, you asked for \"a\" specific reason, and I listed three.  The\ntests that are spread across many scripts make it harder to see if\nwe have enough coverage for the out-of-repository operations, and\nthe use of \"nongit\" helper does not change the equation, does it?\n\n"},{"id":"494818","messageId":"ZkTFvVihZAY184Gm@tanuki","threadId":"61463","inReplyTo":"xmqq4jaz2may.fsf@gitster.g","subject":"Re: [PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-15T14:25:01Z","receivedAt":"2024-05-15T14:25:08Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, May 15, 2024 at 07:15:49AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > On Tue, May 14, 2024 at 08:08:19AM -0700, Junio C Hamano wrote:\n> >> Patrick Steinhardt <ps@pks.im> writes:\n> >> \n> >> > Is there a specific reason why this needs a whole patch suite, as\n> >> > opposed to adding the tests to the respective test suites of the\n> >> > commands?\n> >> \n> >> Yes, testing out-of-repository operations needs certain trick and\n> >> people forget to write such tests using the GIT_CEILING_DIRECTORIES\n> >> mechanism.  Having one place where we have an enumeration of\n> >> commands that are designed to be usable outside repository is a\n> >> handy way to make sure that we have enough test coverage.  It would\n> >> make it easy to control how GIT_DEFAULT_HASH environment is set\n> >> during these tests to have them in all one place.\n> >\n> > We already have the \"nogit\" command that neatly encapsulates all of this\n> > logic, so the trickery is contained in a single spot in practice.\n> \n> Heh, you asked for \"a\" specific reason, and I listed three.\n\nHm. I guess I got thrown off a bit as this was written in a single\nparagraph, so my mind didn't process it as different reasons :)\n\n> The tests that are spread across many scripts make it harder to see if\n> we have enough coverage for the out-of-repository operations,\n\nPut this way I in fact agree with you.\n\n> and the use of \"nongit\" helper does not change the equation, does it?\n\nNo, it doesn't really.\n\nThanks!\n\nPatrick\n"},{"id":"494821","messageId":"xmqq8r0b13t5.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkTFvVihZAY184Gm@tanuki","subject":"Re: [PATCH v4 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-15T15:40:38Z","receivedAt":"2024-05-15T15:40:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n>> The tests that are spread across many scripts make it harder to see if\n>> we have enough coverage for the out-of-repository operations,\n>\n> Put this way I in fact agree with you.\n>\n>> and the use of \"nongit\" helper does not change the equation, does it?\n>\n> No, it doesn't really.\n\nOf course the other side of the coin is that having all tests about\na single command (say, \"git mailmap\") in the same script for both\nin-repo and out-of-repo operations is also handy in a different way.\n\nI haven't found a good way to balance the two.  Obviously duplicating\nthe same test in two scripts (one collection for the same command,\nthe other collection out-of repo operation of various commands) is\nsomething I really do want to avoid, so...\n"},{"id":"494893","messageId":"xmqqcyplu61f.fsf@gitster.g","threadId":"61463","inReplyTo":"xmqqikzg48hm.fsf@gitster.g","subject":"Re: [PATCH v4 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-16T15:31:56Z","receivedAt":"2024-05-16T15:32:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Having done all of this, I actually am very tempted to add the\n> \"always default to SHA-1\" back as a fallback position to the\n> set_default_hash_algo() function.  We know we are going to get the\n> right hash algorithm when working in the repository, so the only\n> case the default matters in practice is when working outside the\n> repository.\n\nNot really.  It does not add anything to help either real world or\nour tests.  The current test setting is already bad enough in that,\nunlike in the real world settings, even tests with the SHA-1\nalgorithm has GIT_DEFAULT_HASH environment variable set, which means\nthat such a \"if the environment variable is not set, further fall\nback to SHA-1\" does not do anything.\n\nUnless we change t/test-lib.sh not to set GIT_DEFAULT_HASH tweaking\nthe fallback default in repository.c:set_default_hash_algo() based\non GIT_DEFAULT_HASH would not be a workable solution.\n\nI wanted to arrange things so that the end-user exectuion by default\nhas an extra fallback (perhaps to SHA-1, or GIT_DEFAULT_HASH) to\navoid disrupting their real-world use, which we can disable in our\ntests to expose code paths that still rely on the \"default\" set when\nin-core repository struct gets initialized, but that is not possible\nwithout changing the way t/test-lib.sh uses GIT_DEFAULT_HASH, it\nseems.  So the arrangement unfortunately has to be \"we have no\ndefault, and bugs will break the real-world uses as well as tests\nthe same way.  The real-world users have to export an extra\n'workaround' environment variable to force \"default\" to SHA-1 (or\nGIT_DEFAULT_HASH) --- which may be \"workable\" but very far from being\nintuitive.  They can set GIT_DEFAULT_HASH but to make it effective\neverywhere, including the \"default\" given by set_default_hash_algo(),\nthey need to set this other \"workaround\" thing.\n\n> We already have such a custom code for \"git diff --no-index\", and we\n> are adding a few more back in here, but they can disappear if we had\n> code to set the fallback default when GIT_DEFAULT_HASH does not\n> exist here.\n\nWhile I think a manual setting of the_hash_algo in \"diff --no-index\"\ncode path should not hardcode \"SHA-1\" but instead use the hash\nspecified by the GIT_DEFAULT_HASH environment to be consistent with\nthe use of \"git\" by the same parent process that had that variable\nexported to the environment, that should not be done globally in\nrepository.c:set_default_hash_algo().\n"},{"id":"495012","messageId":"xmqqmsoodmoe.fsf@gitster.g","threadId":"61463","inReplyTo":"20240514011437.3779151-5-gitster@pobox.com","subject":"Re: [PATCH v4 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-17T23:49:05Z","receivedAt":"2024-05-17T23:49:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> From: Patrick Steinhardt <ps@pks.im>\n>\n> The git-hash-object(1) command allows users to hash an object even\n> without a repository. Starting with c8aed5e8da (repository: stop setting\n> SHA1 as the default object hash, 2024-05-07), this will make us hit an\n> uninitialized hash function, which subsequently leads to a segfault.\n>\n> Fix this by falling back to SHA-1 explicitly when running outside of\n> a Git repository. Users can use GIT_DEFAULT_HASH environment to\n> specify what hash algorithm they want, so arguably this code should\n> not be needed.\n\nBy the way, this breaks the expectation of t1007 and t1517 when run\nwith GIT_DEFAULT_HASH=sha256 (I recall that they passed with the\nearlier iteration of my \"fall back to GIT_DEFAULT_HASH\" in [1/5],\nbut we decided abusing GIT_DEFAULT_HASH is a bad idea).\n\nhttps://github.com/git/git/actions/runs/9135149292/job/25122031380\n"},{"id":"495121","messageId":"xmqqed9wdvv5.fsf@gitster.g","threadId":"61463","inReplyTo":"xmqqmsoodmoe.fsf@gitster.g","subject":"Re: [PATCH v4 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T21:19:42Z","receivedAt":"2024-05-20T21:19:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> From: Patrick Steinhardt <ps@pks.im>\n>>\n>> The git-hash-object(1) command allows users to hash an object even\n>> without a repository. Starting with c8aed5e8da (repository: stop setting\n>> SHA1 as the default object hash, 2024-05-07), this will make us hit an\n>> uninitialized hash function, which subsequently leads to a segfault.\n>>\n>> Fix this by falling back to SHA-1 explicitly when running outside of\n>> a Git repository. Users can use GIT_DEFAULT_HASH environment to\n>> specify what hash algorithm they want, so arguably this code should\n>> not be needed.\n>\n> By the way, this breaks the expectation of t1007 and t1517 when run\n> with GIT_DEFAULT_HASH=sha256 (I recall that they passed with the\n> earlier iteration of my \"fall back to GIT_DEFAULT_HASH\" in [1/5],\n> but we decided abusing GIT_DEFAULT_HASH is a bad idea).\n\nThe breakage in 1517 turns out to be a thinko on my part.  Outside a\nrepository, we do use SHA-1 with our \"if the_hash_algo is not set\nyet, default to SHA-1\" in patch-id and hash-object but the way I\nprepared the expected output was to use whatever GIT_TEST_DEFAULT_HASH\nwas in use.  A fix would be to go outside a repository and force the\nhash with GIT_DEFAULT_HASH to sha1 when preparing the expected output.\n\nI haven't looked at the breakage in 1007 yet, though.\n\ndiff --git i/t/t1517-outside-repo.sh w/t/t1517-outside-repo.sh\nindex 6f32a40c6d..6363c8e3c4 100755\n--- i/t/t1517-outside-repo.sh\n+++ w/t/t1517-outside-repo.sh\n@@ -21,22 +21,24 @@ test_expect_success 'set up a non-repo directory and test file' '\n \tgit diff >sample.patch\n '\n \n-test_expect_success 'compute a patch-id outside repository' '\n-\tgit patch-id <sample.patch >patch-id.expect &&\n+test_expect_success 'compute a patch-id outside repository (default to SHA-1)' '\n \t(\n \t\tcd non-repo &&\n-\t\tgit patch-id <../sample.patch >../patch-id.actual\n-\t) &&\n-\ttest_cmp patch-id.expect patch-id.actual\n+\t\tGIT_DEFAULT_HASH=sha1 \\\n+\t\tgit patch-id <../sample.patch >patch-id.expect &&\n+\t\tgit patch-id <../sample.patch >patch-id.actual &&\n+\t\ttest_cmp patch-id.expect patch-id.actual\n+\t)\n '\n \n-test_expect_success 'hash-object outside repository' '\n-\tgit hash-object --stdin <sample.patch >hash.expect &&\n+test_expect_success 'hash-object outside repository (default to SHA-1)' '\n \t(\n \t\tcd non-repo &&\n-\t\tgit hash-object --stdin <../sample.patch >../hash.actual\n-\t) &&\n-\ttest_cmp hash.expect hash.actual\n+\t\tGIT_DEFAULT_HASH=sha1 \\\n+\t\tgit hash-object --stdin <../sample.patch >hash.expect &&\n+\t\tgit hash-object --stdin <../sample.patch >hash.actual &&\n+\t\ttest_cmp hash.expect hash.actual\n+\t)\n '\n \n test_expect_success 'apply a patch outside repository' '\n\n"},{"id":"495124","messageId":"xmqqa5kkdrwm.fsf@gitster.g","threadId":"61463","inReplyTo":"xmqqed9wdvv5.fsf@gitster.g","subject":"Re: [PATCH v4 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T22:45:13Z","receivedAt":"2024-05-20T22:45:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I haven't looked at the breakage in 1007 yet, though.\n\nThis turned out to be almost trivial.  A fix relative to an earlier\nversion is that the call to test_oid helper needs to explicitly ask\nfor SHA-1 variant, as the command invocation outside a repository\nuses SHA-1 (not due to falling back to a hardcoded default, but by\nan explicit fallback in the \"git hash-object\" itself.\n\nI'll send a v5 of the whole series sometime later (if I have time it\nmay happen today but otherwise tomorrow).\n\nThanks.\n\ndiff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh\nindex 64aea38486..d73a5cc237 100755\n--- a/t/t1007-hash-object.sh\n+++ b/t/t1007-hash-object.sh\n@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '\n \techo example | git hash-object -t $t --literally --stdin\n '\n \n+test_expect_success '--stdin outside of repository (uses SHA-1)' '\n+\tnongit git hash-object --stdin <hello >actual &&\n+\techo \"$(test_oid --hash=sha1 hello)\" >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex 82ca6d2bfd..c767414a0c 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n \telse\n \t\tprefix = setup_git_directory_gently(&nongit);\n \n+\tif (nongit && !the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (vpath && prefix) {\n \t\tvpath_free = prefix_filename(prefix, vpath);\n \t\tvpath = vpath_free;\n"},{"id":"495126","messageId":"20240520231434.1816979-1-gitster@pobox.com","threadId":"61463","inReplyTo":"cover.1715582857.git.ps@pks.im","subject":"[PATCH v5 0/5] Fix use of uninitialized hash algorithms","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T23:14:29Z","receivedAt":"2024-05-20T23:14:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A change recently merged to 'next' stops us from defaulting to using\nSHA-1 unless other code (like a logic early in the start-up sequence\nto see what hash is being used in the repository we are working in)\nexplicitly sets it, leading to a (deliberate) crash of \"git\" when we\nforgot to cover certain code paths.\n\nIt turns out we have a few.  Notable ones are all operations that\nare designed to work outside a repository.  We should go over all\nsuch code paths and give them a reasonable default when there is one\navailable (e.g. for historical reasons, patch-id is documented to\nwork with SHA-1 hashes, so arguably it, or at least when it is\ninvoked with the \"--stable\" option, should do so everywhere, not\njust in SHA-1 repositories, but in SHA-256 repository or outside any\nrepository).  In the meantime, if an end-user hits such a \"bug\"\nbefore we can fix it, it would be nice to give them an escape hatch\nto restore the historical behaviour of falling back to use SHA-1.\n\nThese patches are designed to apply on a merge of c8aed5e8\n(repository: stop setting SHA1 as the default object hash,\n2024-05-07) into 3e4a232f (The third batch, 2024-05-13), which has\nbeen the same base throughout the past iterations.\n\nIn this fifth iteration:\n\n - The first step no longer falls back to GIT_DEFAULT_HASH; the\n   escape hatch is a dedicated GIT_TEST_DEFAULT_HASH_ALGO\n   environment variable, but hopefully we do not have to advertise\n   it all that often.\n\n - The second step has been simplified somewhat to use the \"nongit\"\n   helper when we only need to run a single \"git\" command in t1517.\n   The way the expected output files were prepared in the previous\n   versions did not correctly force use of SHA-1 algorithm, which\n   has been corrected.  The third step and fourth step for t1517\n   continue to be \"flip expect_failure to expect_success\", but you\n   can see context differences in the range-diff.\n\n - The fourth step also has a fix for t1007 where the previous\n   iterations did not correctly force use of SHA-1 to prepare the\n   expected output.\n\nOtherwise this round should be ready, modulo possible typoes.\n\n\nJunio C Hamano (3):\n  setup: add an escape hatch for \"no more default hash algorithm\" change\n  t1517: test commands that are designed to be run outside repository\n  apply: fix uninitialized hash function\n\nPatrick Steinhardt (2):\n  builtin/patch-id: fix uninitialized hash function\n  builtin/hash-object: fix uninitialized hash function\n\n builtin/apply.c         |  4 +++\n builtin/hash-object.c   |  3 +++\n builtin/patch-id.c      | 13 +++++++++\n repository.c            | 44 ++++++++++++++++++++++++++++++\n t/t1007-hash-object.sh  |  6 +++++\n t/t1517-outside-repo.sh | 59 +++++++++++++++++++++++++++++++++++++++++\n t/t4204-patch-id.sh     | 34 ++++++++++++++++++++++++\n 7 files changed, 163 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\n-- \n2.45.1-216-g4365c6fcf9\n\n1:  3038f73e1c ! 1:  f5e6868a61 setup: add an escape hatch for \"no more default hash algorithm\" change\n    @@ Commit message\n         Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n         default object hash, 2024-05-07), to keep end-user systems still\n         broken when we have gap in our test coverage but yet give them an\n    -    escape hatch to set the GIT_DEFAULT_HASH environment variable to\n    -    \"sha1\" in order to revert to the previous behaviour.  This variable\n    -    has been in use for using SHA-256 hash by default, and it should be\n    -    a better fit than inventing a new and test-only knob.\n    +    escape hatch to set the GIT_TEST_DEFAULT_HASH_ALGO environment\n    +    variable to \"sha1\" in order to revert to the previous behaviour.\n     \n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n    +    Due to the way the end-user facing GIT_DEFAULT_HASH environment\n    +    variable is used in our test suite, we unfortunately cannot reuse it\n    +    for this purpose.\n     \n    - ## environment.h ##\n    -@@ environment.h: const char *getenv_safe(struct strvec *argv, const char *name);\n    - #define GIT_OPTIONAL_LOCKS_ENVIRONMENT \"GIT_OPTIONAL_LOCKS\"\n    - #define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT \"GIT_TEXTDOMAINDIR\"\n    - #define GIT_ATTR_SOURCE_ENVIRONMENT \"GIT_ATTR_SOURCE\"\n    -+#define GIT_DEFAULT_HASH_ENVIRONMENT \"GIT_DEFAULT_HASH\"\n    - \n    - /*\n    -  * Environment variable used in handshaking the wire protocol.\n    +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     \n      ## repository.c ##\n    -@@\n    - #include \"git-compat-util.h\"\n    - #include \"abspath.h\"\n    -+#include \"environment.h\"\n    - #include \"repository.h\"\n    - #include \"object-store-ll.h\"\n    - #include \"config.h\"\n     @@\n      static struct repository the_repo;\n      struct repository *the_repository = &the_repo;\n      \n    ++/*\n    ++ * An escape hatch: if we hit a bug in the production code that fails\n    ++ * to set an appropriate hash algorithm (most likely to happen when\n    ++ * running outside a repository), we can tell the user who reported\n    ++ * the crash to set the environment variable to \"sha1\" (all lowercase)\n    ++ * to revert to the historical behaviour of defaulting to SHA-1.\n    ++ */\n     +static void set_default_hash_algo(struct repository *repo)\n     +{\n     +\tconst char *hash_name;\n     +\tint algo;\n     +\n    -+\thash_name = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);\n    ++\thash_name = getenv(\"GIT_TEST_DEFAULT_HASH_ALGO\");\n     +\tif (!hash_name)\n     +\t\treturn;\n     +\talgo = hash_algo_by_name(hash_name);\n    -+\n    -+\t/*\n    -+\t * NEEDSWORK: after all, falling back to SHA-1 by assigning\n    -+\t * GIT_HASH_SHA1 to algo here, instead of returning, may give\n    -+\t * us better behaviour.\n    -+\t */\n     +\tif (algo == GIT_HASH_UNKNOWN)\n     +\t\treturn;\n     +\n    @@ repository.c: void initialize_repository(struct repository *repo)\n     +\t * of the hashed value to see if their input looks like a\n     +\t * plausible hash value.\n     +\t *\n    -+\t * We are in the process of identifying the codepaths and\n    ++\t * We are in the process of identifying such code paths and\n     +\t * giving them an appropriate default individually; any\n    -+\t * unconverted codepath that tries to access the_hash_algo\n    ++\t * unconverted code paths that try to access the_hash_algo\n     +\t * will thus fail.  The end-users however have an escape hatch\n    -+\t * to set GIT_DEFAULT_HASH environment variable to \"sha1\" get\n    -+\t * back the old behaviour of defaulting to SHA-1.\n    ++\t * to set GIT_TEST_DEFAULT_HASH_ALGO environment variable to\n    ++\t * \"sha1\" to get back the old behaviour of defaulting to SHA-1.\n    ++\t *\n    ++\t * This escape hatch is deliberately kept unadvertised, so\n    ++\t * that they see crashes and we can get a report before\n    ++\t * telling them about it.\n     +\t */\n     +\tif (repo == the_repository)\n     +\t\tset_default_hash_algo(repo);\n      }\n      \n      static void expand_base_dir(char **out, const char *in,\n    -\n    - ## setup.c ##\n    -@@ setup.c: int daemonize(void)\n    - #define TEST_FILEMODE 1\n    - #endif\n    - \n    --#define GIT_DEFAULT_HASH_ENVIRONMENT \"GIT_DEFAULT_HASH\"\n    --\n    - static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,\n    - \t\t\t     DIR *dir)\n    - {\n2:  e56ae68961 ! 2:  f3f9bf0480 t1517: test commands that are designed to be run outside repository\n    @@ t/t1517-outside-repo.sh (new)\n     +\tgit diff >sample.patch\n     +'\n     +\n    -+test_expect_failure 'compute a patch-id outside repository' '\n    -+\tgit patch-id <sample.patch >patch-id.expect &&\n    -+\t(\n    -+\t\tcd non-repo &&\n    -+\t\tgit patch-id <../sample.patch >../patch-id.actual\n    -+\t) &&\n    ++test_expect_failure 'compute a patch-id outside repository (uses SHA-1)' '\n    ++\tnongit env GIT_DEFAULT_HASH=sha1 \\\n    ++\t\tgit patch-id <sample.patch >patch-id.expect &&\n    ++\tnongit \\\n    ++\t\tgit patch-id <sample.patch >patch-id.actual &&\n     +\ttest_cmp patch-id.expect patch-id.actual\n     +'\n     +\n    -+test_expect_failure 'hash-object outside repository' '\n    -+\tgit hash-object --stdin <sample.patch >hash.expect &&\n    -+\t(\n    -+\t\tcd non-repo &&\n    -+\t\tgit hash-object --stdin <../sample.patch >../hash.actual\n    -+\t) &&\n    ++test_expect_failure 'hash-object outside repository (uses SHA-1)' '\n    ++\tnongit env GIT_DEFAULT_HASH=sha1 \\\n    ++\t\tgit hash-object --stdin <sample.patch >hash.expect &&\n    ++\tnongit \\\n    ++\t\tgit hash-object --stdin <sample.patch >hash.actual &&\n     +\ttest_cmp hash.expect hash.actual\n     +'\n     +\n3:  e1ae0e95fc ! 3:  246cf395d0 builtin/patch-id: fix uninitialized hash function\n    @@ t/t1517-outside-repo.sh: test_expect_success 'set up a non-repo directory and te\n      \tgit diff >sample.patch\n      '\n      \n    --test_expect_failure 'compute a patch-id outside repository' '\n    -+test_expect_success 'compute a patch-id outside repository' '\n    - \tgit patch-id <sample.patch >patch-id.expect &&\n    - \t(\n    - \t\tcd non-repo &&\n    +-test_expect_failure 'compute a patch-id outside repository (uses SHA-1)' '\n    ++test_expect_success 'compute a patch-id outside repository (uses SHA-1)' '\n    + \tnongit env GIT_DEFAULT_HASH=sha1 \\\n    + \t\tgit patch-id <sample.patch >patch-id.expect &&\n    + \tnongit \\\n     \n      ## t/t4204-patch-id.sh ##\n     @@ t/t4204-patch-id.sh: test_expect_success 'patch-id handles diffs with one line of before/after' '\n4:  1c8ce0d024 ! 4:  fe14490548 builtin/hash-object: fix uninitialized hash function\n    @@ t/t1007-hash-object.sh: test_expect_success '--literally with extra-long type' '\n      \techo example | git hash-object -t $t --literally --stdin\n      '\n      \n    -+test_expect_success '--stdin outside of repository' '\n    ++test_expect_success '--stdin outside of repository (uses SHA-1)' '\n     +\tnongit git hash-object --stdin <hello >actual &&\n    -+\techo \"$(test_oid hello)\" >expect &&\n    ++\techo \"$(test_oid --hash=sha1 hello)\" >expect &&\n     +\ttest_cmp expect actual\n     +'\n     +\n      test_done\n     \n      ## t/t1517-outside-repo.sh ##\n    -@@ t/t1517-outside-repo.sh: test_expect_success 'compute a patch-id outside repository' '\n    +@@ t/t1517-outside-repo.sh: test_expect_success 'compute a patch-id outside repository (uses SHA-1)' '\n      \ttest_cmp patch-id.expect patch-id.actual\n      '\n      \n    --test_expect_failure 'hash-object outside repository' '\n    -+test_expect_success 'hash-object outside repository' '\n    - \tgit hash-object --stdin <sample.patch >hash.expect &&\n    - \t(\n    - \t\tcd non-repo &&\n    +-test_expect_failure 'hash-object outside repository (uses SHA-1)' '\n    ++test_expect_success 'hash-object outside repository (uses SHA-1)' '\n    + \tnongit env GIT_DEFAULT_HASH=sha1 \\\n    + \t\tgit hash-object --stdin <sample.patch >hash.expect &&\n    + \tnongit \\\n5:  5b0ec43757 ! 5:  c6d5e68374 apply: fix uninitialized hash function\n    @@ builtin/apply.c: int cmd_apply(int argc, const char **argv, const char *prefix)\n      \t\t\t\t   apply_usage);\n     \n      ## t/t1517-outside-repo.sh ##\n    -@@ t/t1517-outside-repo.sh: test_expect_success 'hash-object outside repository' '\n    +@@ t/t1517-outside-repo.sh: test_expect_success 'hash-object outside repository (uses SHA-1)' '\n      \ttest_cmp hash.expect hash.actual\n      '\n      \n"},{"id":"495127","messageId":"20240520231434.1816979-2-gitster@pobox.com","threadId":"61463","inReplyTo":"20240520231434.1816979-1-gitster@pobox.com","subject":"[PATCH v5 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T23:14:30Z","receivedAt":"2024-05-20T23:14:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Partially revert c8aed5e8 (repository: stop setting SHA1 as the\ndefault object hash, 2024-05-07), to keep end-user systems still\nbroken when we have gap in our test coverage but yet give them an\nescape hatch to set the GIT_TEST_DEFAULT_HASH_ALGO environment\nvariable to \"sha1\" in order to revert to the previous behaviour.\n\nDue to the way the end-user facing GIT_DEFAULT_HASH environment\nvariable is used in our test suite, we unfortunately cannot reuse it\nfor this purpose.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n repository.c | 44 ++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 44 insertions(+)\n\ndiff --git a/repository.c b/repository.c\nindex 15c10015b0..c62e329878 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -19,6 +19,28 @@\n static struct repository the_repo;\n struct repository *the_repository = &the_repo;\n \n+/*\n+ * An escape hatch: if we hit a bug in the production code that fails\n+ * to set an appropriate hash algorithm (most likely to happen when\n+ * running outside a repository), we can tell the user who reported\n+ * the crash to set the environment variable to \"sha1\" (all lowercase)\n+ * to revert to the historical behaviour of defaulting to SHA-1.\n+ */\n+static void set_default_hash_algo(struct repository *repo)\n+{\n+\tconst char *hash_name;\n+\tint algo;\n+\n+\thash_name = getenv(\"GIT_TEST_DEFAULT_HASH_ALGO\");\n+\tif (!hash_name)\n+\t\treturn;\n+\talgo = hash_algo_by_name(hash_name);\n+\tif (algo == GIT_HASH_UNKNOWN)\n+\t\treturn;\n+\n+\trepo_set_hash_algo(repo, algo);\n+}\n+\n void initialize_repository(struct repository *repo)\n {\n \trepo->objects = raw_object_store_new();\n@@ -26,6 +48,28 @@ void initialize_repository(struct repository *repo)\n \trepo->parsed_objects = parsed_object_pool_new();\n \tALLOC_ARRAY(repo->index, 1);\n \tindex_state_init(repo->index, repo);\n+\n+\t/*\n+\t * When a command runs inside a repository, it learns what\n+\t * hash algorithm is in use from the repository, but some\n+\t * commands are designed to work outside a repository, yet\n+\t * they want to access the_hash_algo, if only for the length\n+\t * of the hashed value to see if their input looks like a\n+\t * plausible hash value.\n+\t *\n+\t * We are in the process of identifying such code paths and\n+\t * giving them an appropriate default individually; any\n+\t * unconverted code paths that try to access the_hash_algo\n+\t * will thus fail.  The end-users however have an escape hatch\n+\t * to set GIT_TEST_DEFAULT_HASH_ALGO environment variable to\n+\t * \"sha1\" to get back the old behaviour of defaulting to SHA-1.\n+\t *\n+\t * This escape hatch is deliberately kept unadvertised, so\n+\t * that they see crashes and we can get a report before\n+\t * telling them about it.\n+\t */\n+\tif (repo == the_repository)\n+\t\tset_default_hash_algo(repo);\n }\n \n static void expand_base_dir(char **out, const char *in,\n-- \n2.45.1-216-g4365c6fcf9\n\n"},{"id":"495128","messageId":"20240520231434.1816979-3-gitster@pobox.com","threadId":"61463","inReplyTo":"20240520231434.1816979-1-gitster@pobox.com","subject":"[PATCH v5 2/5] t1517: test commands that are designed to be run outside repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T23:14:31Z","receivedAt":"2024-05-20T23:14:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A few commands, like \"git apply\" and \"git patch-id\", have been\nbroken with a recent change to stop setting the default hash\nalgorithm to SHA-1.  Test them and fix them in later commits.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1517-outside-repo.sh | 59 +++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 59 insertions(+)\n create mode 100755 t/t1517-outside-repo.sh\n\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nnew file mode 100755\nindex 0000000000..389974d9fb\n--- /dev/null\n+++ b/t/t1517-outside-repo.sh\n@@ -0,0 +1,59 @@\n+#!/bin/sh\n+\n+test_description='check random commands outside repo'\n+\n+TEST_PASSES_SANITIZE_LEAK=true\n+. ./test-lib.sh\n+\n+test_expect_success 'set up a non-repo directory and test file' '\n+\tGIT_CEILING_DIRECTORIES=$(pwd) &&\n+\texport GIT_CEILING_DIRECTORIES &&\n+\tmkdir non-repo &&\n+\t(\n+\t\tcd non-repo &&\n+\t\t# confirm that git does not find a repo\n+\t\ttest_must_fail git rev-parse --git-dir\n+\t) &&\n+\ttest_write_lines one two three four >nums &&\n+\tgit add nums &&\n+\tcp nums nums.old &&\n+\ttest_write_lines five >>nums &&\n+\tgit diff >sample.patch\n+'\n+\n+test_expect_failure 'compute a patch-id outside repository (uses SHA-1)' '\n+\tnongit env GIT_DEFAULT_HASH=sha1 \\\n+\t\tgit patch-id <sample.patch >patch-id.expect &&\n+\tnongit \\\n+\t\tgit patch-id <sample.patch >patch-id.actual &&\n+\ttest_cmp patch-id.expect patch-id.actual\n+'\n+\n+test_expect_failure 'hash-object outside repository (uses SHA-1)' '\n+\tnongit env GIT_DEFAULT_HASH=sha1 \\\n+\t\tgit hash-object --stdin <sample.patch >hash.expect &&\n+\tnongit \\\n+\t\tgit hash-object --stdin <sample.patch >hash.actual &&\n+\ttest_cmp hash.expect hash.actual\n+'\n+\n+test_expect_failure 'apply a patch outside repository' '\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit apply ../sample.patch\n+\t) &&\n+\ttest_cmp nums non-repo/nums\n+'\n+\n+test_expect_success 'grep outside repository' '\n+\tgit grep --cached two >expect &&\n+\t(\n+\t\tcd non-repo &&\n+\t\tcp ../nums.old nums &&\n+\t\tgit grep --no-index two >../actual\n+\t) &&\n+\ttest_cmp expect actual\n+'\n+\n+test_done\n-- \n2.45.1-216-g4365c6fcf9\n\n"},{"id":"495129","messageId":"20240520231434.1816979-4-gitster@pobox.com","threadId":"61463","inReplyTo":"20240520231434.1816979-1-gitster@pobox.com","subject":"[PATCH v5 3/5] builtin/patch-id: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T23:14:32Z","receivedAt":"2024-05-20T23:14:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nIn c8aed5e8da (repository: stop setting SHA1 as the default object hash,\n2024-05-07), we have adapted `initialize_repository()` to no longer set\nup a default hash function. As this function is also used to set up\n`the_repository`, the consequence is that `the_hash_algo` will now by\ndefault be a `NULL` pointer unless the hash algorithm was configured\nproperly. This is done as a mechanism to detect cases where we may be\nusing the wrong hash function by accident.\n\nThis change now causes git-patch-id(1) to segfault when it's run outside\nof a repository. As this command can read diffs from stdin, it does not\nnecessarily need a repository, but then relies on `the_hash_algo` to\ncompute the patch ID itself.\n\nIt is somewhat dubious that git-patch-id(1) relies on `the_hash_algo` in\nthe first place. Quoting its manpage:\n\n    A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs\n    associated with a patch, with line numbers ignored. As such, it’s\n    \"reasonably stable\", but at the same time also reasonably unique,\n    i.e., two patches that have the same \"patch ID\" are almost\n    guaranteed to be the same thing.\n\nWe explicitly document patch IDs to be using SHA-1. Furthermore, patch\nIDs are supposed to be stable for most of the part. But even with the\nsame input, the patch IDs will now be different depending on the repo's\nconfigured object hash.\n\nWork around the issue by setting up SHA-1 when there was no startup\nrepository for now. This is arguably not the correct fix, but for now we\nrather want to focus on getting the segfault fixed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/patch-id.c      | 13 +++++++++++++\n t/t1517-outside-repo.sh |  2 +-\n t/t4204-patch-id.sh     | 34 ++++++++++++++++++++++++++++++++++\n 3 files changed, 48 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/patch-id.c b/builtin/patch-id.c\nindex 3894d2b970..583099cacf 100644\n--- a/builtin/patch-id.c\n+++ b/builtin/patch-id.c\n@@ -5,6 +5,7 @@\n #include \"hash.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n+#include \"setup.h\"\n \n static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)\n {\n@@ -237,6 +238,18 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, builtin_patch_id_options,\n \t\t\t     patch_id_usage, 0);\n \n+\t/*\n+\t * We rely on `the_hash_algo` to compute patch IDs. This is dubious as\n+\t * it means that the hash algorithm now depends on the object hash of\n+\t * the repository, even though git-patch-id(1) clearly defines that\n+\t * patch IDs always use SHA1.\n+\t *\n+\t * NEEDSWORK: This hack should be removed in favor of converting\n+\t * the code that computes patch IDs to always use SHA1.\n+\t */\n+\tif (!the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tgenerate_id_list(opts ? opts > 1 : config.stable,\n \t\t\t opts ? opts == 3 : config.verbatim);\n \treturn 0;\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 389974d9fb..278ef57b3a 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -21,7 +21,7 @@ test_expect_success 'set up a non-repo directory and test file' '\n \tgit diff >sample.patch\n '\n \n-test_expect_failure 'compute a patch-id outside repository (uses SHA-1)' '\n+test_expect_success 'compute a patch-id outside repository (uses SHA-1)' '\n \tnongit env GIT_DEFAULT_HASH=sha1 \\\n \t\tgit patch-id <sample.patch >patch-id.expect &&\n \tnongit \\\ndiff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh\nindex a7fa94ce0a..605faea0c7 100755\n--- a/t/t4204-patch-id.sh\n+++ b/t/t4204-patch-id.sh\n@@ -310,4 +310,38 @@ test_expect_success 'patch-id handles diffs with one line of before/after' '\n \ttest_config patchid.stable true &&\n \tcalc_patch_id diffu1stable <diffu1\n '\n+\n+test_expect_failure 'patch-id computes same ID with different object hashes' '\n+\ttest_when_finished \"rm -rf repo-sha1 repo-sha256\" &&\n+\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\n+\tgit init --object-format=sha1 repo-sha1 &&\n+\tgit -C repo-sha1 patch-id <diff >patch-id-sha1 &&\n+\tgit init --object-format=sha256 repo-sha256 &&\n+\tgit -C repo-sha256 patch-id <diff >patch-id-sha256 &&\n+\ttest_cmp patch-id-sha1 patch-id-sha256\n+'\n+\n+test_expect_success 'patch-id without repository' '\n+\tcat >diff <<-\\EOF &&\n+\tdiff --git a/bar b/bar\n+\tindex bdaf90f..31051f6 100644\n+\t--- a/bar\n+\t+++ b/bar\n+\t@@ -2 +2,2 @@\n+\t b\n+\t+c\n+\tEOF\n+\tnongit git patch-id <diff\n+'\n+\n test_done\n-- \n2.45.1-216-g4365c6fcf9\n\n"},{"id":"495130","messageId":"20240520231434.1816979-5-gitster@pobox.com","threadId":"61463","inReplyTo":"20240520231434.1816979-1-gitster@pobox.com","subject":"[PATCH v5 4/5] builtin/hash-object: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T23:14:33Z","receivedAt":"2024-05-20T23:14:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Patrick Steinhardt <ps@pks.im>\n\nThe git-hash-object(1) command allows users to hash an object even\nwithout a repository. Starting with c8aed5e8da (repository: stop setting\nSHA1 as the default object hash, 2024-05-07), this will make us hit an\nuninitialized hash function, which subsequently leads to a segfault.\n\nFix this by falling back to SHA-1 explicitly when running outside of\na Git repository. Users can use GIT_DEFAULT_HASH environment to\nspecify what hash algorithm they want, so arguably this code should\nnot be needed.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/hash-object.c   | 3 +++\n t/t1007-hash-object.sh  | 6 ++++++\n t/t1517-outside-repo.sh | 2 +-\n 3 files changed, 10 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex 82ca6d2bfd..c767414a0c 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)\n \telse\n \t\tprefix = setup_git_directory_gently(&nongit);\n \n+\tif (nongit && !the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \tif (vpath && prefix) {\n \t\tvpath_free = prefix_filename(prefix, vpath);\n \t\tvpath = vpath_free;\ndiff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh\nindex 64aea38486..d73a5cc237 100755\n--- a/t/t1007-hash-object.sh\n+++ b/t/t1007-hash-object.sh\n@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '\n \techo example | git hash-object -t $t --literally --stdin\n '\n \n+test_expect_success '--stdin outside of repository (uses SHA-1)' '\n+\tnongit git hash-object --stdin <hello >actual &&\n+\techo \"$(test_oid --hash=sha1 hello)\" >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 278ef57b3a..2d8982d61a 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -29,7 +29,7 @@ test_expect_success 'compute a patch-id outside repository (uses SHA-1)' '\n \ttest_cmp patch-id.expect patch-id.actual\n '\n \n-test_expect_failure 'hash-object outside repository (uses SHA-1)' '\n+test_expect_success 'hash-object outside repository (uses SHA-1)' '\n \tnongit env GIT_DEFAULT_HASH=sha1 \\\n \t\tgit hash-object --stdin <sample.patch >hash.expect &&\n \tnongit \\\n-- \n2.45.1-216-g4365c6fcf9\n\n"},{"id":"495131","messageId":"20240520231434.1816979-6-gitster@pobox.com","threadId":"61463","inReplyTo":"20240520231434.1816979-1-gitster@pobox.com","subject":"[PATCH v5 5/5] apply: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-20T23:14:34Z","receivedAt":"2024-05-20T23:14:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git apply\" can work outside a repository as a better \"GNU patch\",\nbut when it does so, it still assumed that it can access\nthe_hash_algo, which is no longer true in the new world order.\n\nMake sure we explicitly fall back to SHA-1 algorithm for backward\ncompatibility.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/apply.c         | 4 ++++\n t/t1517-outside-repo.sh | 2 +-\n 2 files changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 861a01910c..e9175f820f 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -1,6 +1,7 @@\n #include \"builtin.h\"\n #include \"gettext.h\"\n #include \"repository.h\"\n+#include \"hash.h\"\n #include \"apply.h\"\n \n static const char * const apply_usage[] = {\n@@ -18,6 +19,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)\n \tif (init_apply_state(&state, the_repository, prefix))\n \t\texit(128);\n \n+\tif (!the_hash_algo)\n+\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n+\n \targc = apply_parse_options(argc, argv,\n \t\t\t\t   &state, &force_apply, &options,\n \t\t\t\t   apply_usage);\ndiff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\nindex 2d8982d61a..557808ffa7 100755\n--- a/t/t1517-outside-repo.sh\n+++ b/t/t1517-outside-repo.sh\n@@ -37,7 +37,7 @@ test_expect_success 'hash-object outside repository (uses SHA-1)' '\n \ttest_cmp hash.expect hash.actual\n '\n \n-test_expect_failure 'apply a patch outside repository' '\n+test_expect_success 'apply a patch outside repository' '\n \t(\n \t\tcd non-repo &&\n \t\tcp ../nums.old nums &&\n-- \n2.45.1-216-g4365c6fcf9\n\n"},{"id":"495150","messageId":"ZkxUBebjx8WvyJnm@tanuki","threadId":"61463","inReplyTo":"20240520231434.1816979-2-gitster@pobox.com","subject":"Re: [PATCH v5 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-21T07:57:57Z","receivedAt":"2024-05-21T07:58:02Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 20, 2024 at 04:14:30PM -0700, Junio C Hamano wrote:\n> Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n> default object hash, 2024-05-07), to keep end-user systems still\n> broken when we have gap in our test coverage but yet give them an\n> escape hatch to set the GIT_TEST_DEFAULT_HASH_ALGO environment\n> variable to \"sha1\" in order to revert to the previous behaviour.\n> \n> Due to the way the end-user facing GIT_DEFAULT_HASH environment\n> variable is used in our test suite, we unfortunately cannot reuse it\n> for this purpose.\n\nOkay, so this now really only is an escape hatch for users as we do not\nspecify it in our tests anymore. It does make me wonder whether we want\nto name the envvar accordingly, but don't mind it much either way. It is\nonly intended to be a stop gap solution anyway that we can eventually\ndrop once we are sufficiently sure that there is no further breakage.\n\nPatrick\n"},{"id":"495151","messageId":"ZkxUEP7HifEVlDZY@tanuki","threadId":"61463","inReplyTo":"20240520231434.1816979-6-gitster@pobox.com","subject":"Re: [PATCH v5 5/5] apply: fix uninitialized hash function","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-21T07:58:08Z","receivedAt":"2024-05-21T07:58:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 20, 2024 at 04:14:34PM -0700, Junio C Hamano wrote:\n> \"git apply\" can work outside a repository as a better \"GNU patch\",\n> but when it does so, it still assumed that it can access\n> the_hash_algo, which is no longer true in the new world order.\n> \n> Make sure we explicitly fall back to SHA-1 algorithm for backward\n> compatibility.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  builtin/apply.c         | 4 ++++\n>  t/t1517-outside-repo.sh | 2 +-\n>  2 files changed, 5 insertions(+), 1 deletion(-)\n> \n> diff --git a/builtin/apply.c b/builtin/apply.c\n> index 861a01910c..e9175f820f 100644\n> --- a/builtin/apply.c\n> +++ b/builtin/apply.c\n> @@ -1,6 +1,7 @@\n>  #include \"builtin.h\"\n>  #include \"gettext.h\"\n>  #include \"repository.h\"\n> +#include \"hash.h\"\n>  #include \"apply.h\"\n>  \n>  static const char * const apply_usage[] = {\n> @@ -18,6 +19,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)\n>  \tif (init_apply_state(&state, the_repository, prefix))\n>  \t\texit(128);\n>  \n> +\tif (!the_hash_algo)\n> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n> +\n\nDo we also want to add a comment here that mentions that we may want to\nmake this configureable via a command line option, like we have in the\npreceding commits?\n\nPatrick\n\n>  \targc = apply_parse_options(argc, argv,\n>  \t\t\t\t   &state, &force_apply, &options,\n>  \t\t\t\t   apply_usage);\n> diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh\n> index 2d8982d61a..557808ffa7 100755\n> --- a/t/t1517-outside-repo.sh\n> +++ b/t/t1517-outside-repo.sh\n> @@ -37,7 +37,7 @@ test_expect_success 'hash-object outside repository (uses SHA-1)' '\n>  \ttest_cmp hash.expect hash.actual\n>  '\n>  \n> -test_expect_failure 'apply a patch outside repository' '\n> +test_expect_success 'apply a patch outside repository' '\n>  \t(\n>  \t\tcd non-repo &&\n>  \t\tcp ../nums.old nums &&\n> -- \n> 2.45.1-216-g4365c6fcf9\n> \n> \n"},{"id":"495152","messageId":"ZkxUGzPn363PNWMF@tanuki","threadId":"61463","inReplyTo":"20240520231434.1816979-1-gitster@pobox.com","subject":"Re: [PATCH v5 0/5] Fix use of uninitialized hash algorithms","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-21T07:58:19Z","receivedAt":"2024-05-21T07:58:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, May 20, 2024 at 04:14:29PM -0700, Junio C Hamano wrote:\n> A change recently merged to 'next' stops us from defaulting to using\n> SHA-1 unless other code (like a logic early in the start-up sequence\n> to see what hash is being used in the repository we are working in)\n> explicitly sets it, leading to a (deliberate) crash of \"git\" when we\n> forgot to cover certain code paths.\n> \n> It turns out we have a few.  Notable ones are all operations that\n> are designed to work outside a repository.  We should go over all\n> such code paths and give them a reasonable default when there is one\n> available (e.g. for historical reasons, patch-id is documented to\n> work with SHA-1 hashes, so arguably it, or at least when it is\n> invoked with the \"--stable\" option, should do so everywhere, not\n> just in SHA-1 repositories, but in SHA-256 repository or outside any\n> repository).  In the meantime, if an end-user hits such a \"bug\"\n> before we can fix it, it would be nice to give them an escape hatch\n> to restore the historical behaviour of falling back to use SHA-1.\n> \n> These patches are designed to apply on a merge of c8aed5e8\n> (repository: stop setting SHA1 as the default object hash,\n> 2024-05-07) into 3e4a232f (The third batch, 2024-05-13), which has\n> been the same base throughout the past iterations.\n> \n> In this fifth iteration:\n> \n>  - The first step no longer falls back to GIT_DEFAULT_HASH; the\n>    escape hatch is a dedicated GIT_TEST_DEFAULT_HASH_ALGO\n>    environment variable, but hopefully we do not have to advertise\n>    it all that often.\n> \n>  - The second step has been simplified somewhat to use the \"nongit\"\n>    helper when we only need to run a single \"git\" command in t1517.\n>    The way the expected output files were prepared in the previous\n>    versions did not correctly force use of SHA-1 algorithm, which\n>    has been corrected.  The third step and fourth step for t1517\n>    continue to be \"flip expect_failure to expect_success\", but you\n>    can see context differences in the range-diff.\n> \n>  - The fourth step also has a fix for t1007 where the previous\n>    iterations did not correctly force use of SHA-1 to prepare the\n>    expected output.\n> \n> Otherwise this round should be ready, modulo possible typoes.\n\nI have two smallish comments, but neither of them really have to be\naddressed. Overall I very much agree with this iteration and think that\nit's the right way to go.\n\nThanks!\n\nPatrick\n"},{"id":"495162","messageId":"xmqqcypfcmn4.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkxUEP7HifEVlDZY@tanuki","subject":"Re: [PATCH v5 5/5] apply: fix uninitialized hash function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-21T13:36:31Z","receivedAt":"2024-05-21T13:36:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n>> +\tif (!the_hash_algo)\n>> +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n>> +\n>\n> Do we also want to add a comment here that mentions that we may want to\n> make this configureable via a command line option, like we have in the\n> preceding commits?\n\nWe may want a comment here that says \n\n    we could to redo the \"apply.c\" machinery to make this arbitrary\n    fallback unnecessary, but the benefit to do so is dubious and\n    the risk of breaking the code is probably not worth the effort.\n\nWhen working as \"better GNU patch\" mode without a repository, we\nshould not and do not use the_hash_algo for the purpose of hashing\nat all.  We do not do the binary diff (because we cannot grab the\npreimage object out of the object store (that does not exist) to\napply the delta to form the postimage, we do not do the 3-way\nfallback using the preimage blob object names that appear on the\n\"index\" lines.  As far as I recall, the only thing we use\nthe_hash_algo for is for the max length of the hash to ask \"is this\nhexadecimal string a plausible looking object name?  We are parsing\na line that started with 'index ' and trying to see if the line\nsyntactically looks like a valid 'index' line\" and the like.  If we\nassume SHA-1 and if somebody tries to injest a SHA-256 --full-index\npatch, that logic may say \"nah, we didn't find a valid 'index'\nheader\", but I think we'll just leave the fields like old-object\nblank, which does not affect anything because we won't do \"apply\n--3way\" anyway.\n\nSo we _could_ identify such places and tell the code \"when\nthe_hash_algo is NULL, instead of the_hash_algo->hexsz, use 0 as\nhexsz\" (this example is from apply.c:gitdiff_index()) and it indeed\nwas the approach I tried in my unpublished draft before the first\nversion I posted.  It quickly got ugly.\n\n"},{"id":"495174","messageId":"xmqqle43b1fy.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkxUBebjx8WvyJnm@tanuki","subject":"Re: [PATCH v5 1/5] setup: add an escape hatch for \"no more default hash algorithm\" change","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-21T15:59:45Z","receivedAt":"2024-05-21T15:59:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Mon, May 20, 2024 at 04:14:30PM -0700, Junio C Hamano wrote:\n>> Partially revert c8aed5e8 (repository: stop setting SHA1 as the\n>> default object hash, 2024-05-07), to keep end-user systems still\n>> broken when we have gap in our test coverage but yet give them an\n>> escape hatch to set the GIT_TEST_DEFAULT_HASH_ALGO environment\n>> variable to \"sha1\" in order to revert to the previous behaviour.\n>> \n>> Due to the way the end-user facing GIT_DEFAULT_HASH environment\n>> variable is used in our test suite, we unfortunately cannot reuse it\n>> for this purpose.\n>\n> Okay, so this now really only is an escape hatch for users as we do not\n> specify it in our tests anymore. It does make me wonder whether we want\n> to name the envvar accordingly, but don't mind it much either way. It is\n> only intended to be a stop gap solution anyway that we can eventually\n> drop once we are sufficiently sure that there is no further breakage.\n\nYes, I think the name of that escape hatch variable should be\nirrelevant by the time we are reasonably confident that we could\nremove it ;-)\n\nBut the proposed log message should make that intention more clear.\nHow does this read?\n\n    ... give them an escape hatch ... in order to revert to the\n    previous behaviour, just in case we haven't done a thorough job\n    in fixing the fallout from c8aed5e8.  After we build confidence,\n    we should remove the escape hatch support, but we are not there\n    yet after only fixing three commands (hash-object, apply, and\n    patch-id) in this series.\n\nThanks.\n"},{"id":"495181","messageId":"xmqqpltf9gz3.fsf@gitster.g","threadId":"61463","inReplyTo":"ZkxUGzPn363PNWMF@tanuki","subject":"Re: [PATCH v5 0/5] Fix use of uninitialized hash algorithms","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-05-21T18:07:12Z","receivedAt":"2024-05-21T18:07:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> I have two smallish comments, but neither of them really have to be\n> addressed. Overall I very much agree with this iteration and think that\n> it's the right way to go.\n\nI've locally done the following locally but it probably does not\nneed to be resent to the list before merging down to 'next'.\n\n\n1:  b23a93597c ! 1:  d3b2ff75fd setup: add an escape hatch for \"no more default hash algorithm\" change\n    @@ Commit message\n         default object hash, 2024-05-07), to keep end-user systems still\n         broken when we have gap in our test coverage but yet give them an\n         escape hatch to set the GIT_TEST_DEFAULT_HASH_ALGO environment\n    -    variable to \"sha1\" in order to revert to the previous behaviour.\n    +    variable to \"sha1\" in order to revert to the previous behaviour, in\n    +    case we haven't done a thorough job in fixing the fallout from\n    +    c8aed5e8.  After we build confidence, we should remove the escape\n    +    hatch support, but we are not there yet after only fixing three\n    +    commands (hash-object, apply, and patch-id) in this series.\n     \n         Due to the way the end-user facing GIT_DEFAULT_HASH environment\n         variable is used in our test suite, we unfortunately cannot reuse it\n2:  6a20370944 = 2:  abece6e970 t1517: test commands that are designed to be run outside repository\n3:  fa258c5d47 = 3:  4a1c95931f builtin/patch-id: fix uninitialized hash function\n4:  164d340cbe = 4:  8d058b8024 builtin/hash-object: fix uninitialized hash function\n5:  bd0246eb51 ! 5:  4674ab682d apply: fix uninitialized hash function\n    @@ Commit message\n         Make sure we explicitly fall back to SHA-1 algorithm for backward\n         compatibility.\n     \n    +    It is of dubious value to make this configurable to other hash\n    +    algorithms, as the code does not use the_hash_algo for hashing\n    +    purposes when working outside a repository (which is how\n    +    the_hash_algo is left to NULL)---it is only used to learn the max\n    +    length of the hash when parsing the object names on the \"index\"\n    +    line, but failing to parse the \"index\" line is not a hard failure,\n    +    and the program does not support operations like applying binary\n    +    patches and --3way fallback that requires object access outside a\n    +    repository.\n    +\n         Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     \n      ## builtin/apply.c ##\n    @@ builtin/apply.c: int cmd_apply(int argc, const char **argv, const char *prefix)\n      \tif (init_apply_state(&state, the_repository, prefix))\n      \t\texit(128);\n      \n    ++\t/*\n    ++\t * We could to redo the \"apply.c\" machinery to make this\n    ++\t * arbitrary fallback unnecessary, but it is dubious that it\n    ++\t * is worth the effort.\n    ++\t * cf. https://lore.kernel.org/git/xmqqcypfcmn4.fsf@gitster.g/\n    ++\t */\n     +\tif (!the_hash_algo)\n     +\t\trepo_set_hash_algo(the_repository, GIT_HASH_SHA1);\n     +\n"},{"id":"495263","messageId":"Zk154eQUf6LG8Qd-@tanuki","threadId":"61463","inReplyTo":"xmqqpltf9gz3.fsf@gitster.g","subject":"Re: [PATCH v5 0/5] Fix use of uninitialized hash algorithms","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-05-22T04:51:45Z","receivedAt":"2024-05-22T04:51:52Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, May 21, 2024 at 11:07:12AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > I have two smallish comments, but neither of them really have to be\n> > addressed. Overall I very much agree with this iteration and think that\n> > it's the right way to go.\n> \n> I've locally done the following locally but it probably does not\n> need to be resent to the list before merging down to 'next'.\n\nThanks, the diff looks good to me.\n\nPatrick\n"}]}