]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-file: disallow adding submodules of different hash algo
authorbrian m. carlson <sandals@crustytoothpaste.net>
Sat, 15 Nov 2025 00:58:17 +0000 (00:58 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sat, 15 Nov 2025 19:51:37 +0000 (11:51 -0800)
The design of the hash algorithm transition plan is that objects stored
must be entirely in one algorithm since we lack any way to indicate a
mix of algorithms.  This also includes submodules, but we have
traditionally not enforced this, which leads to various problems when
trying to clone or check out the the submodule from the remote.

Since this cannot work in the general case, restrict adding a submodule
of a different algorithm to the index.  Add tests for git add and git
submodule add that these are rejected.

Note that we cannot check this in git fsck because the malformed
submodule is stored in the tree as an object ID which is either
truncated (when a SHA-256 submodule is added to a SHA-1 repository) or
padded with zeros (when a SHA-1 submodule is added to a SHA-256
repository).  We cannot detect even the latter case because someone
could have an actual submodule that actually ends in 24 zeros, which
would be a false positive.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
object-file.c
t/t3700-add.sh
t/t7400-submodule-basic.sh

index 2bc36ab3ee8cbf2d83c4b3204a7c5df132b934d6..6ff6cf75499d30f55eabe0924fd6dd8fd9e2c7ab 100644 (file)
@@ -1296,7 +1296,11 @@ int index_path(struct index_state *istate, struct object_id *oid,
                strbuf_release(&sb);
                break;
        case S_IFDIR:
-               return repo_resolve_gitlink_ref(istate->repo, path, "HEAD", oid);
+               if (repo_resolve_gitlink_ref(istate->repo, path, "HEAD", oid))
+                       return -1;
+               if (&hash_algos[oid->algo] != istate->repo->hash_algo)
+                       return error(_("cannot add a submodule of a different hash algorithm"));
+               break;
        default:
                return error(_("%s: unsupported file type"), path);
        }
index df580a5806b4f1ca245a861e473522ccc868d83a..9a2c8dbcc23d9164066a05b5ecbbb3ec1ff44044 100755 (executable)
@@ -541,6 +541,31 @@ test_expect_success 'all statuses changed in folder if . is given' '
        )
 '
 
+test_expect_success 'cannot add a submodule of a different algorithm' '
+       git init --object-format=sha256 sha256 &&
+       (
+               cd sha256 &&
+               test_commit abc &&
+               git init --object-format=sha1 submodule &&
+               test_commit -C submodule def &&
+               test_must_fail git add submodule 2>err &&
+               test_grep "cannot add a submodule of a different hash algorithm" err &&
+               git ls-files --stage >entries &&
+               test_grep ! ^160000 entries
+       ) &&
+       git init --object-format=sha1 sha1 &&
+       (
+               cd sha1 &&
+               test_commit abc &&
+               git init --object-format=sha256 submodule &&
+               test_commit -C submodule def &&
+               test_must_fail git add submodule 2>err &&
+               test_grep "cannot add a submodule of a different hash algorithm" err &&
+               git ls-files --stage >entries &&
+               test_grep ! ^160000 entries
+       )
+'
+
 test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
        path="$(pwd)/BLUB" &&
        touch "$path" &&
index fd3e7e355e4ffca1cc6457d383458f8072aba053..e6b551daad7e58fe7a8bd48b362852a81cf81cae 100755 (executable)
@@ -407,6 +407,31 @@ test_expect_success 'submodule add in subdirectory with relative path should fai
        test_grep toplevel output.err
 '
 
+test_expect_success 'submodule add of a different algorithm fails' '
+       git init --object-format=sha256 sha256 &&
+       (
+               cd sha256 &&
+               test_commit abc &&
+               git init --object-format=sha1 submodule &&
+               test_commit -C submodule def &&
+               test_must_fail git submodule add "$submodurl" submodule 2>err &&
+               test_grep "cannot add a submodule of a different hash algorithm" err &&
+               git ls-files --stage >entries &&
+               test_grep ! ^160000 entries
+       ) &&
+       git init --object-format=sha1 sha1 &&
+       (
+               cd sha1 &&
+               test_commit abc &&
+               git init --object-format=sha256 submodule &&
+               test_commit -C submodule def &&
+               test_must_fail git submodule add "$submodurl" submodule 2>err &&
+               test_grep "cannot add a submodule of a different hash algorithm" err &&
+               git ls-files --stage >entries &&
+               test_grep ! ^160000 entries
+       )
+'
+
 test_expect_success 'setup - add an example entry to .gitmodules' '
        git config --file=.gitmodules submodule.example.url git://example.com/init.git
 '