From: Johannes Schindelin Date: Wed, 10 Apr 2024 20:04:48 +0000 (+0200) Subject: Sync with 2.42.2 X-Git-Tag: v2.43.4~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8e97ec3662a54b07e4c19bb761e95cf87bd54364;p=thirdparty%2Fgit.git Sync with 2.42.2 * maint-2.42: (39 commits) Git 2.42.2 Git 2.41.1 Git 2.40.2 Git 2.39.4 fsck: warn about symlink pointing inside a gitdir core.hooksPath: add some protection while cloning init.templateDir: consider this config setting protected clone: prevent hooks from running during a clone Add a helper function to compare file contents init: refactor the template directory discovery into its own function find_hook(): refactor the `STRIP_EXTENSION` logic clone: when symbolic links collide with directories, keep the latter entry: report more colliding paths t5510: verify that D/F confusion cannot lead to an RCE submodule: require the submodule path to contain directories only clone_submodule: avoid using `access()` on directories submodules: submodule paths must not contain symlinks clone: prevent clashing git dirs when cloning submodule in parallel t7423: add tests for symlinked submodule directories has_dir_name(): do not get confused by characters < '/' ... --- 8e97ec3662a54b07e4c19bb761e95cf87bd54364 diff --cc fsck.h index e3adf9d911,82ba7afedd..17fa2dda5d --- a/fsck.h +++ b/fsck.h @@@ -73,7 -75,8 +75,9 @@@ enum fsck_msg_type FUNC(NULL_SHA1, WARN) \ FUNC(ZERO_PADDED_FILEMODE, WARN) \ FUNC(NUL_IN_COMMIT, WARN) \ + FUNC(LARGE_PATHNAME, WARN) \ + FUNC(SYMLINK_TARGET_LENGTH, WARN) \ + FUNC(SYMLINK_POINTS_TO_GIT_DIR, WARN) \ /* infos (reported as warnings, but ignored by default) */ \ FUNC(BAD_FILEMODE, INFO) \ FUNC(GITMODULES_PARSE, INFO) \ diff --cc t/t0411-clone-from-partial.sh index 0000000000,b3d6ddc4bc..c98d501869 mode 000000,100755..100755 --- a/t/t0411-clone-from-partial.sh +++ b/t/t0411-clone-from-partial.sh @@@ -1,0 -1,78 +1,78 @@@ + #!/bin/sh + + test_description='check that local clone does not fetch from promisor remotes' + + . ./test-lib.sh + + test_expect_success 'create evil repo' ' + git init tmp && + test_commit -C tmp a && + git -C tmp config uploadpack.allowfilter 1 && + git clone --filter=blob:none --no-local --no-checkout tmp evil && + rm -rf tmp && + + git -C evil config remote.origin.uploadpack \"\$TRASH_DIRECTORY/fake-upload-pack\" && + write_script fake-upload-pack <<-\EOF && + echo >&2 "fake-upload-pack running" + >"$TRASH_DIRECTORY/script-executed" + exit 1 + EOF + export TRASH_DIRECTORY && + + # empty shallow file disables local clone optimization + >evil/.git/shallow + ' + + test_expect_success 'local clone must not fetch from promisor remote and execute script' ' + rm -f script-executed && + test_must_fail git clone \ + --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ + evil clone1 2>err && - grep "detected dubious ownership" err && - ! grep "fake-upload-pack running" err && ++ test_grep "detected dubious ownership" err && ++ test_grep ! "fake-upload-pack running" err && + test_path_is_missing script-executed + ' + + test_expect_success 'clone from file://... must not fetch from promisor remote and execute script' ' + rm -f script-executed && + test_must_fail git clone \ + --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ + "file://$(pwd)/evil" clone2 2>err && - grep "detected dubious ownership" err && - ! grep "fake-upload-pack running" err && ++ test_grep "detected dubious ownership" err && ++ test_grep ! "fake-upload-pack running" err && + test_path_is_missing script-executed + ' + + test_expect_success 'fetch from file://... must not fetch from promisor remote and execute script' ' + rm -f script-executed && + test_must_fail git fetch \ + --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ + "file://$(pwd)/evil" 2>err && - grep "detected dubious ownership" err && - ! grep "fake-upload-pack running" err && ++ test_grep "detected dubious ownership" err && ++ test_grep ! "fake-upload-pack running" err && + test_path_is_missing script-executed + ' + + test_expect_success 'pack-objects should fetch from promisor remote and execute script' ' + rm -f script-executed && + echo "HEAD" | test_must_fail git -C evil pack-objects --revs --stdout >/dev/null 2>err && - grep "fake-upload-pack running" err && ++ test_grep "fake-upload-pack running" err && + test_path_is_file script-executed + ' + + test_expect_success 'clone from promisor remote does not lazy-fetch by default' ' + rm -f script-executed && + test_must_fail git clone evil no-lazy 2>err && - grep "lazy fetching disabled" err && ++ test_grep "lazy fetching disabled" err && + test_path_is_missing script-executed + ' + + test_expect_success 'promisor lazy-fetching can be re-enabled' ' + rm -f script-executed && + test_must_fail env GIT_NO_LAZY_FETCH=0 \ + git clone evil lazy-ok 2>err && - grep "fake-upload-pack running" err && ++ test_grep "fake-upload-pack running" err && + test_path_is_file script-executed + ' + + test_done diff --cc t/t1800-hook.sh index 8b0234cf2d,750011d717..1894ebeb0e --- a/t/t1800-hook.sh +++ b/t/t1800-hook.sh @@@ -185,4 -185,19 +185,19 @@@ test_expect_success 'stdin to hooks' test_cmp expect actual ' + test_expect_success 'clone protections' ' + test_config core.hooksPath "$(pwd)/my-hooks" && + mkdir -p my-hooks && + write_script my-hooks/test-hook <<-\EOF && + echo Hook ran $1 + EOF + + git hook run test-hook 2>err && - grep "Hook ran" err && ++ test_grep "Hook ran" err && + test_must_fail env GIT_CLONE_PROTECTION_ACTIVE=true \ + git hook run test-hook 2>err && - grep "active .core.hooksPath" err && - ! grep "Hook ran" err ++ test_grep "active .core.hooksPath" err && ++ test_grep ! "Hook ran" err + ' + test_done diff --cc t/t5510-fetch.sh index 91e87b1dd3,5399feda92..75ec252087 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@@ -1251,6 -1250,30 +1251,30 @@@ EO test_cmp fatal-expect fatal-actual ' + test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' ' + git init df-conflict && + ( + cd df-conflict && + ln -s .git a && + git add a && + test_tick && + git commit -m symlink && + test_commit a- && + rm a && + mkdir -p a/hooks && + write_script a/hooks/post-checkout <<-EOF && + echo WHOOPSIE >&2 + echo whoopsie >"$TRASH_DIRECTORY"/whoops + EOF + git add a/hooks/post-checkout && + test_tick && + git commit -m post-checkout + ) && + git clone df-conflict clone 2>err && - ! grep WHOOPS err && ++ test_grep ! WHOOPS err && + test_path_is_missing whoops + ' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd diff --cc t/t5601-clone.sh index 47eae641f0,1bcf652b10..5ce7a04f97 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@@ -630,9 -630,24 +630,24 @@@ test_expect_success 'clone on case-inse test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' ' grep X icasefs/warning && grep x icasefs/warning && - test_i18ngrep "the following paths have collided" icasefs/warning + test_grep "the following paths have collided" icasefs/warning ' + test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \ + 'colliding symlink/directory keeps directory' ' + git init icasefs-colliding-symlink && + ( + cd icasefs-colliding-symlink && + a=$(printf a | git hash-object -w --stdin) && + printf "100644 %s 0\tA/dir/b\n120000 %s 0\ta\n" $a $a >idx && + git update-index --index-info &2 + echo I was here >hook.run + EOF + git -C tmpl/hooks add . && + test_tick && + git -C tmpl/hooks commit -m post-checkout && + + test_when_finished "git config --global --unset init.templateDir || :" && + test_when_finished "git config --unset init.templateDir || :" && + ( + sane_unset GIT_TEMPLATE_DIR && + NO_SET_GIT_TEMPLATE_DIR=t && + export NO_SET_GIT_TEMPLATE_DIR && + + git -c core.hooksPath="$(pwd)/tmpl/hooks" \ + clone tmpl/hooks hook-run-hookspath 2>err && - ! grep "active .* hook found" err && ++ test_grep ! "active .* hook found" err && + test_path_is_file hook-run-hookspath/hook.run && + + git -c init.templateDir="$(pwd)/tmpl" \ + clone tmpl/hooks hook-run-config 2>err && - ! grep "active .* hook found" err && ++ test_grep ! "active .* hook found" err && + test_path_is_file hook-run-config/hook.run && + + git clone --template=tmpl tmpl/hooks hook-run-option 2>err && - ! grep "active .* hook found" err && ++ test_grep ! "active .* hook found" err && + test_path_is_file hook-run-option/hook.run && + + git config --global init.templateDir "$(pwd)/tmpl" && + git clone tmpl/hooks hook-run-global-config 2>err && + git config --global --unset init.templateDir && - ! grep "active .* hook found" err && ++ test_grep ! "active .* hook found" err && + test_path_is_file hook-run-global-config/hook.run && + + # clone ignores local `init.templateDir`; need to create + # a new repository because we deleted `.git/` in the + # `setup` test case above + git init local-clone && + cd local-clone && + + git config init.templateDir "$(pwd)/../tmpl" && + git clone ../tmpl/hooks hook-run-local-config 2>err && + git config --unset init.templateDir && - ! grep "active .* hook found" err && ++ test_grep ! "active .* hook found" err && + test_path_is_missing hook-run-local-config/hook.run + ) + ' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd diff --cc t/t7400-submodule-basic.sh index 00c1f1aab1,9918584464..7223c8f74f --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@@ -1452,4 -1452,35 +1452,35 @@@ test_expect_success 'recursive clone re test_must_be_empty actual ' + test_expect_success '`submodule init` and `init.templateDir`' ' + mkdir -p tmpl/hooks && + write_script tmpl/hooks/post-checkout <<-EOF && + echo HOOK-RUN >&2 + echo I was here >hook.run + exit 1 + EOF + + test_config init.templateDir "$(pwd)/tmpl" && + test_when_finished \ + "git config --global --unset init.templateDir || true" && + ( + sane_unset GIT_TEMPLATE_DIR && + NO_SET_GIT_TEMPLATE_DIR=t && + export NO_SET_GIT_TEMPLATE_DIR && + + git config --global init.templateDir "$(pwd)/tmpl" && + test_must_fail git submodule \ + add "$submodurl" sub-global 2>err && + git config --global --unset init.templateDir && - grep HOOK-RUN err && ++ test_grep HOOK-RUN err && + test_path_is_file sub-global/hook.run && + + git config init.templateDir "$(pwd)/tmpl" && + git submodule add "$submodurl" sub-local 2>err && + git config --unset init.templateDir && - ! grep HOOK-RUN err && ++ test_grep ! HOOK-RUN err && + test_path_is_missing sub-local/hook.run + ) + ' + test_done diff --cc t/t7406-submodule-update.sh index 8491b8c58b,fb82f760c3..297c6c3b5c --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@@ -1202,4 -1202,52 +1202,52 @@@ test_expect_success 'commit with stage add_submodule_commit_and_validate ' + test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \ + 'submodule paths must not follow symlinks' ' + + # This is only needed because we want to run this in a self-contained + # test without having to spin up an HTTP server; However, it would not + # be needed in a real-world scenario where the submodule is simply + # hosted on a public site. + test_config_global protocol.file.allow always && + + # Make sure that Git tries to use symlinks on Windows + test_config_global core.symlinks true && + + tell_tale_path="$PWD/tell.tale" && + git init hook && + ( + cd hook && + mkdir -p y/hooks && + write_script y/hooks/post-checkout <<-EOF && + echo HOOK-RUN >&2 + echo hook-run >"$tell_tale_path" + EOF + git add y/hooks/post-checkout && + test_tick && + git commit -m post-checkout + ) && + + hook_repo_path="$(pwd)/hook" && + git init captain && + ( + cd captain && + git submodule add --name x/y "$hook_repo_path" A/modules/x && + test_tick && + git commit -m add-submodule && + + printf .git >dotgit.txt && + git hash-object -w --stdin dot-git.hash && + printf "120000 %s 0\ta\n" "$(cat dot-git.hash)" >index.info && + git update-index --index-info err && - ! grep HOOK-RUN err && ++ test_grep ! HOOK-RUN err && + test_path_is_missing "$tell_tale_path" + ' + test_done diff --cc t/t7450-bad-git-dotfiles.sh index 35a31acd4d,60d627583d..5b845e899b --- a/t/t7450-bad-git-dotfiles.sh +++ b/t/t7450-bad-git-dotfiles.sh @@@ -312,9 -312,39 +312,39 @@@ test_expect_success 'setup submodules w git add .gitmodules thing1 thing2 && test_tick && git commit -m nested - ) && + ) + ' + + test_expect_success 'git dirs of sibling submodules must not be nested' ' test_must_fail git clone --recurse-submodules nested clone 2>err && - test_i18ngrep "is inside git dir" err + test_grep "is inside git dir" err ' + test_expect_success 'submodule git dir nesting detection must work with parallel cloning' ' + test_must_fail git clone --recurse-submodules --jobs=2 nested clone_parallel 2>err && + cat err && + grep -E "(already exists|is inside git dir|not a git repository)" err && + { + test_path_is_missing .git/modules/hippo/HEAD || + test_path_is_missing .git/modules/hippo/hooks/HEAD + } + ' + + test_expect_success 'checkout -f --recurse-submodules must not use a nested gitdir' ' + git clone nested nested_checkout && + ( + cd nested_checkout && + git submodule init && + git submodule update thing1 && + mkdir -p .git/modules/hippo/hooks/refs && + mkdir -p .git/modules/hippo/hooks/objects/info && + echo "../../../../objects" >.git/modules/hippo/hooks/objects/info/alternates && + echo "ref: refs/heads/master" >.git/modules/hippo/hooks/HEAD + ) && + test_must_fail git -C nested_checkout checkout -f --recurse-submodules HEAD 2>err && + cat err && + grep "is inside git dir" err && + test_path_is_missing nested_checkout/thing2/.git + ' + test_done