]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Sync with 2.42.2
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Wed, 10 Apr 2024 20:04:48 +0000 (22:04 +0200)
committerJohannes Schindelin <johannes.schindelin@gmx.de>
Fri, 19 Apr 2024 10:38:50 +0000 (12:38 +0200)
* 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 < '/'
  ...

25 files changed:
1  2 
Documentation/fsck-msgids.txt
Documentation/git-upload-pack.txt
Documentation/git.txt
INSTALL
builtin/clone.c
builtin/submodule--helper.c
config.c
dir.c
dir.h
entry.c
fsck.c
fsck.h
http.c
read-cache.c
remote-curl.c
setup.c
submodule.c
t/t0411-clone-from-partial.sh
t/t1450-fsck.sh
t/t1800-hook.sh
t/t5510-fetch.sh
t/t5601-clone.sh
t/t7400-submodule-basic.sh
t/t7406-submodule-update.sh
t/t7450-bad-git-dotfiles.sh

Simple merge
Simple merge
Simple merge
diff --cc INSTALL
Simple merge
diff --cc builtin/clone.c
Simple merge
Simple merge
diff --cc config.c
Simple merge
diff --cc dir.c
Simple merge
diff --cc dir.h
Simple merge
diff --cc entry.c
Simple merge
diff --cc fsck.c
Simple merge
diff --cc fsck.h
index e3adf9d91159878ae09b35a9fe12370fdbf85f98,82ba7afedd74c2e615dd87cbac8f8d41c8635907..17fa2dda5dee3de5553da16fc9f9d337087701ea
--- 1/fsck.h
--- 2/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 http.c
Simple merge
diff --cc read-cache.c
Simple merge
diff --cc remote-curl.c
Simple merge
diff --cc setup.c
Simple merge
diff --cc submodule.c
Simple merge
index 0000000000000000000000000000000000000000,b3d6ddc4bc2d99993dc1ba37edd55c5beff3fd2b..c98d5018695a137b57cc9634312f220cff897cce
mode 000000,100755..100755
--- /dev/null
@@@ -1,0 -1,78 +1,78 @@@
 -      grep "detected dubious ownership" err &&
 -      ! grep "fake-upload-pack running" err &&
+ #!/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 "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 "lazy fetching disabled" 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 "fake-upload-pack running" 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 &&
++      test_grep "fake-upload-pack running" err &&
+       test_path_is_file script-executed
+ '
+ test_done
diff --cc t/t1450-fsck.sh
Simple merge
diff --cc t/t1800-hook.sh
index 8b0234cf2d5d96980403d65b844639715acfe91b,750011d717f109f61b30b12653eb46c78faf0baa..1894ebeb0e8ff3f3e8d4febeb77dd0bce32a2b2b
@@@ -185,4 -185,19 +185,19 @@@ test_expect_success 'stdin to hooks' 
        test_cmp expect actual
  '
  
 -      grep "Hook ran" err &&
+ 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 "active .core.hooksPath" 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 &&
++      test_grep "active .core.hooksPath" err &&
++      test_grep ! "Hook ran" err
+ '
  test_done
index 91e87b1dd3a5dceb8af2ab614e1d968866dc8b28,5399feda928db3a1561b01c96b0d00151e3a98fe..75ec252087b9282cfddb9a7cb7e0e12ffa8dda30
        test_cmp fatal-expect fatal-actual
  '
  
 -      ! grep WHOOPS err &&
+ 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 &&
++      test_grep ! WHOOPS err &&
+       test_path_is_missing whoops
+ '
  . "$TEST_DIRECTORY"/lib-httpd.sh
  start_httpd
  
index 47eae641f018055f2200ef6e2581d8ac60364cdb,1bcf652b1096003e236c37526de507991258a9f9..5ce7a04f97df3543caee0f2ed57e6843e58d8a8c
@@@ -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 <idx &&
+               test_tick &&
+               git commit -m initial
+       ) &&
+       git clone icasefs-colliding-symlink icasefs-colliding-symlink-clone &&
+       test_file_not_empty icasefs-colliding-symlink-clone/A/dir/b
+ '
  test_expect_success 'clone with GIT_DEFAULT_HASH' '
        (
                sane_unset GIT_DEFAULT_HASH &&
@@@ -756,6 -771,57 +771,57 @@@ test_expect_success 'batch missing blo
        git clone --filter=blob:limit=0 "file://$(pwd)/server" client
  '
  
 -              ! grep "active .* hook found" err &&
+ test_expect_success 'clone with init.templatedir runs hooks' '
+       git init tmpl/hooks &&
+       write_script tmpl/hooks/post-checkout <<-EOF &&
+       echo HOOK-RUN >&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 &&
++              test_grep ! "active .* hook found" err &&
+               test_path_is_missing hook-run-local-config/hook.run
+       )
+ '
  . "$TEST_DIRECTORY"/lib-httpd.sh
  start_httpd
  
index 00c1f1aab1304c127a5dccdaeff62d7213b7a9e5,9918584464c8ab9ab6a32c2dabdcd60658523bb8..7223c8f74fc788f584d20379e64ab2bc1310d2a7
@@@ -1452,4 -1452,35 +1452,35 @@@ test_expect_success 'recursive clone re
        test_must_be_empty actual
  '
  
 -              grep HOOK-RUN err &&
+ 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 &&
++              test_grep ! HOOK-RUN err &&
+               test_path_is_missing sub-local/hook.run
+       )
+ '
  test_done
index 8491b8c58b97f0597a5fcc27448b3d99abdbe9c9,fb82f760c3d7759198aa9baa392a1d05fedb684b..297c6c3b5cc4b8889941f81422c5544db0ac2243
@@@ -1202,4 -1202,52 +1202,52 @@@ test_expect_success 'commit with stage
        add_submodule_commit_and_validate
  '
  
 -      ! grep HOOK-RUN err &&
+ 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 <dotgit.txt >dot-git.hash &&
+               printf "120000 %s 0\ta\n" "$(cat dot-git.hash)" >index.info &&
+               git update-index --index-info <index.info &&
+               test_tick &&
+               git commit -m add-symlink
+       ) &&
+       test_path_is_missing "$tell_tale_path" &&
+       git clone --recursive captain hooked 2>err &&
++      test_grep ! HOOK-RUN err &&
+       test_path_is_missing "$tell_tale_path"
+ '
  test_done
index 35a31acd4d7e26bc3bf8f42853d80593488c9227,60d627583dff39c3bd98573b0443f5a247c4acca..5b845e899bf17caec8e26cff4fb329e8701fb77b
@@@ -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