Skip to content

Update to git 2.2.0 #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 796 commits into from
Closed

Update to git 2.2.0 #20

wants to merge 796 commits into from

Conversation

t-b
Copy link

@t-b t-b commented Nov 27, 2014

The difference to the auto generated shears script is

--- shears-2.2.orig 2014-11-27 18:34:35 +0000
+++ shears-2.2.new  2014-11-27 18:41:52 +0000
@@ -127,11 +127,6 @@
 pick 4b04f46 Config option to disable side-band-64k for transport
 mark t-b/sideband-bug

-# Branch: kasal/tests-no-posix
-bud
-pick 9233472 Revert "test: fix t7001 cp to use POSIX options"
-mark kasal/tests-no-posix
-
 # Branch: kblees/kb/fscache-v4-tentative-1.8.5
 rewind hide-dotgit # mingw: add tests for the hidden attribute on the git directory
 pick 33a1078 Win32: make FILETIME conversion functions public
@@ -171,7 +166,6 @@
 merge refs/rewritten/fix-is-exe -C 3d7d03e # Merge 'fix-is-exe' into HEAD
 merge refs/rewritten/msysgit/tip4commit -C 0ac7ef0 # Merge pull request #115 from msysgit/tip4commit
 merge refs/rewritten/t-b/sideband-bug -C 6c55145 # Merge remote-tracking branch 't-b/sideband-bug'
-merge refs/rewritten/kasal/tests-no-posix -C c9ff21b # Merge pull request #181 from kasal/tests-no-posix
 merge refs/rewritten/kblees/kb/fscache-v4-tentative-1.8.5 -C 52591b9 # Merge remote-tracking branch 'kblees/kb/fscache-v4-tentative-1.8.5' into thicket-1.8.5.2
 merge refs/rewritten/kblees/kb/long-paths-v2 -C 53ee2b9 # Merge pull request #122 from kblees/kb/long-paths-v2
 mark kblees/kb/msysgit-2.1.0

as we finally have a newer cp.
Additionally I had to fix a few conflicts ( no code changes required).

The test suite reports:

Test Summary Report
-------------------
t0050-filesystem.sh                              (Wstat: 0 Tests: 9 Failed: 0)
  TODO passed:   4
t1410-reflog.sh                                  (Wstat: 256 Tests: 15 Failed: 1)
  Failed test:  15
  Non-zero exit status: 1
t3513-revert-submodule.sh                        (Wstat: 0 Tests: 14 Failed: 0)
  TODO passed:   12-14
t3420-rebase-autostash.sh                        (Wstat: 256 Tests: 25 Failed: 6)
  Failed tests:  19-24
  Non-zero exit status: 1
t5000-tar-tree.sh                                (Wstat: 256 Tests: 49 Failed: 1)
  Failed test:  48
  Non-zero exit status: 1
t5503-tagfollow.sh                               (Wstat: 0 Tests: 11 Failed: 0)
  TODO passed:   3, 6, 9
Files=687, Tests=12189, 1401 wallclock secs ( 5.10 usr  6.02 sys + 977.64 cusr 2133.84 csys = 3122.60 CPU)
Result: FAIL

I've not yet come up with fixes for the failures and also don't know when I find time for it.

stefanbeller and others added 30 commits October 21, 2014 11:01
Found by scan.coverity.com (ID: 1248110)

Signed-off-by: Stefan Beller <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
Note that despite the private address being first and primary,
Google owns the copyright on this patch as any other patch I'll be
sending signed off by the [email protected] address.

Signed-off-by: Stefan Beller <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
This "stk" shadows the first declaration at the top. There's currently
no bad effect. But let's avoid it.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
Beyond Compare version 4 works the same way as version 3, so rename
the existing "bc3" adaptor to just "bc", while keeping "bc3" as a
backward compatible wrapper.

Noticed-by: Olivier Croquette <[email protected]>
Helped-by: David Aguilar <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
The API to update refs have been restructured to allow introducing
a true transactional updates later.  We would even allow storing
refs in backends other than the traditional filesystem-based one.

* rs/ref-transaction: (25 commits)
  ref_transaction_commit: bail out on failure to remove a ref
  lockfile: remove unable_to_lock_error
  refs.c: do not permit err == NULL
  remote rm/prune: print a message when writing packed-refs fails
  for-each-ref: skip and warn about broken ref names
  refs.c: allow listing and deleting badly named refs
  test: put tests for handling of bad ref names in one place
  packed-ref cache: forbid dot-components in refnames
  branch -d: simplify by using RESOLVE_REF_READING
  branch -d: avoid repeated symref resolution
  reflog test: test interaction with detached HEAD
  refs.c: change resolve_ref_unsafe reading argument to be a flags field
  refs.c: make write_ref_sha1 static
  fetch.c: change s_update_ref to use a ref transaction
  refs.c: ref_transaction_commit: distinguish name conflicts from other errors
  refs.c: pass a list of names to skip to is_refname_available
  refs.c: call lock_ref_sha1_basic directly from commit
  refs.c: refuse to lock badly named refs in lock_ref_sha1_basic
  rename_ref: don't ask read_ref_full where the ref came from
  refs.c: pass the ref log message to _create/delete/update instead of _commit
  ...
The clean-up of this test script was long overdue and is a very
welcome change.

* da/mergetool-tests:
  test-lib-functions: adjust style to match CodingGuidelines
  t7610-mergetool: use test_config to isolate tests
  t7610-mergetool: add missing && and remove commented-out code
  t7610-mergetool: use tabs instead of a mix of tabs and spaces
Tweak the names of the three throw-away files "git mergetool" comes
up with to feed the merge tool backend, so that a file with a
single dot in its name in the original (e.g. "hello.c") will have
only one dot in these variants (e.g. "hello_BASE_4321.c").

* da/mergetool-temporary-filename:
  mergetool: use more conservative temporary filenames
Allow "git mergetool --help" to run outside a Git repository.

* da/mergetool-tool-help:
  difftool: don't assume that default sh is sane
  mergetool: don't require a work tree for --tool-help
  git-sh-setup: move GIT_DIR initialization into a function
  mergetool: use more conservative temporary filenames
  test-lib-functions: adjust style to match CodingGuidelines
  t7610-mergetool: prefer test_config over git config
Allow a temporary directory specified to be used while running "git
mergetool" backend.

* da/mergetool-temporary-directory:
  t7610-mergetool: add test cases for mergetool.writeToTemp
  mergetool: add an option for writing to a temporary directory
Newer versions of 'meld' breaks the auto-detection we use to see if
they are new enough to support the `--output` option.

* da/mergetool-meld:
  mergetools/meld: make usage of `--output` configurable and more robust
Some internal error messages leaked out of the bash completion when
typing "git cmd <TAB>" and the machinery tried to complete
refnames.

* js/completion-hide-not-a-repo:
  completion: silence "fatal: Not a git repository" error
push --signed promises to take user.signingkey as the signing key but
fails to read the config.

Make it do so.

Signed-off-by: Michael J Gruber <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
Splitting pack-objects output into multiple packs is incompatible
with the use of reachability bitmap.

* jk/pack-objects-no-bitmap-when-splitting:
  pack-objects: turn off bitmaps when we split packs
Update documentation mark-up.

* po/doc-status-markup:
  doc: fix 'git status --help' character quoting
Add managed "env" array to child_process to clarify the lifetime
rules.

* rs/run-command-env-array:
  use env_array member of struct child_process
  run-command: add env_array, an optional argv_array for env
Doc update.

* tb/core-filemode-doc:
  core.filemode may need manual action
* wk/t1304-wo-USER:
  t1304: Set LOGNAME even if USER is unset or null
Allow us build with NO_PTHREADS=NoThanks compilation option.

* eb/no-pthreads:
  Handle atexit list internaly for unthreaded builds
  pack-objects: set number of threads before checking and warning
  index-pack: fix compilation with NO_PTHREADS
Code clean-up.

* nd/dir-prep-exclude-cleanup:
  dir.c: remove the second declaration of "stk" in prep_exclude()
Code clean-up.

* sb/plug-transport-leak:
  .mailmap: add Stefan Bellers corporate mail address
  transport: free leaking head in transport_print_push_status()
* jc/push-cert:
  push: heed user.signingkey for signed pushes
In a Subversion repository where many feature branches are merged into a
trunk, the svn:mergeinfo property can grow very large. This severely
slows down git-svn's make_log_entry() because it is checking all
mergeinfo entries every time the property changes.

In most cases, the additions to svn:mergeinfo since the last commit are
pretty small, and there is nothing to gain by checking merges that were
already checked for the last commit in the branch.

Add a mergeinfo_changes() function which computes the set of interesting
changes to svn:mergeinfo since the last commit. Filter out merged
branches whose ranges haven't changed, and remove a common prefix of
ranges from other merged branches.

This speeds up "git svn fetch" by several orders of magnitude on a large
repository where thousands of feature branches have been merged.

Signed-off-by: Jakob Stoklund Olesen <[email protected]>
Signed-off-by: Eric Wong <[email protected]>
Subversion can put mergeinfo on any sub-directory to track cherry-picks.
Since cherry-picks are not represented explicitly in git, git-svn should
just ignore it.

Signed-off-by: Jakob Stoklund Olesen <[email protected]>
Signed-off-by: Eric Wong <[email protected]>
We do not need to store entire lists of commits, only the
number of incomplete and the first commit for reference.
This reduces the amount of data we need to store in memory
and on disk stores.

Signed-off-by: Eric Wong <[email protected]>
This should reduce excessive memory usage from the new mergeinfo
caches without hurting performance too much, assuming reasonable
latency to the SVN server.

Cc: Hin-Tak Leung <[email protected]>
Suggested-by: Jakob Stoklund Olesen <[email protected]>
Signed-off-by: Eric Wong <[email protected]>
This should further reduce memory usage from the new mergeinfo
speedups without hurting performance too much, assuming
reasonable latency to the SVN server.

Cc: Hin-Tak Leung <[email protected]>
Suggested-by: Jakob Stoklund Olesen <[email protected]>
Signed-off-by: Eric Wong <[email protected]>
Advertise that the svn-remote.<name>.pushurl config key allows specifying
the commit URL for the entire SVN repository in the documentation of the
git svn dcommit command.

Signed-off-by: Sveinung Kvilhaugsvik <[email protected]>
Signed-off-by: Eric Wong <[email protected]>
Despite attempting to use local memory pools everywhere we can,
(including our call to SVN::Ra::do_update and all subsequent reporter
calls), there does not appear to be a way to force the Git::SVN::Fetcher
callbacks to use a pool other than the per-SVN::Ra pool.
Git::SVN::Fetcher ends up using the main RA pool which grows
monotonically in size for the lifetime of the RA object.

Thus the only way to free that memory appears to be to destroy and
recreate the RA connection for at every --log-window-size interval.

This reduces memory usage over the course of fetching 10K revisions
using a test repository created with the script at the end of this
commit message.

As reported by time(1) on my x86-64 system:

	before: 54024k
	 after: 28680k

Unfortunately, there remains some yet-to-be-tracked-down slow memory
growth which would be evident as the `nr' parameter increases in
the repository generation script:
-----------------------------8<------------------------------
set -e
tmp=$(mktemp -d svntestrepo-XXXXXXXX)
svnadmin create "$tmp"
repo=file://"$(cd $tmp && pwd)"
svn co "$repo" "$tmp/wd"
cd "$tmp/wd"
if ! test -f a
then
	> a
	svn add a
	svn commit -m 'A'
fi

nr=10000
while test $nr -gt 0
do
	echo $nr > a
	svn commit -q -m A
	nr=$((nr - 1))
done
echo "repository created in $repo"
-----------------------------8<------------------------------

Signed-off-by: Eric Wong <[email protected]>
@dscho
Copy link
Member

dscho commented Feb 8, 2015

Still no update and Git 2.3.0 is already out.
What is @dscho waiting for?

Whoa, easy now. Did I miss something? Do you pay me? Or do you have acquired bitching rights in any other way?

@t-b
Copy link
Author

t-b commented Feb 10, 2015

I'll make a new PR once I sheared master onto v2.3.
No point in updating to v2.2 now.

@t-b t-b closed this Feb 10, 2015
@t-b t-b deleted the tentative-2.2.0 branch May 5, 2015 21:26
dscho pushed a commit that referenced this pull request Mar 17, 2017
This is the current state of the sha1 collision detection from

    https://github.com/cr-marcstevens/sha1collisiondetection.git

pared down to just the minimal implementation (in lib/) and the
LICENSE.txt file.

Top-of-tree of the source tree is commit 007905a93c97 ("Merge pull
request #20 from cr-marcstevens/feature/performance").  Thanks to both
Marc and Dan for making the code fit our needs by doing both
optimization work, cutting down on the object size, and doing some
syntactic changes to work better with git.

The license of the sha1dc code is the MIT license, which is obviously
compatible with the GPLv2 of git.

Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Jun 11, 2021
ibuf can be reused for multiple iterations of the loop. Specifically:
deflate() overwrites s.avail_in to show how much of the input buffer
has not been processed yet - and sometimes leaves 'avail_in > 0', in
which case ibuf will be processed again during the loop's subsequent
iteration.

But if we declare ibuf within the loop, then (in theory) we get a new
(and uninitialised) buffer for every iteration. In practice, my compiler
seems to resue the same buffer - meaning that this code does work - but
it doesn't seem safe to rely on this behaviour. MSAN correctly catches
this issue - as soon as we hit the 's.avail_in > 0' condition, we end up
reading from what seems to be uninitialised memory.

Therefore, we move ibuf out of the loop, making this reuse safe.

See MSAN output from t1050-large below - the interesting part is the
ibuf creation at the end, although there's a lot of indirection before
we reach the read from unitialised memory:

==11294==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7f75db58fb1c in crc32_little crc32.c:283:9
    #1 0x7f75db58d5b3 in crc32_z crc32.c:220:20
    #2 0x7f75db59668c in crc32 crc32.c:242:12
    #3 0x8c94f8 in hashwrite csum-file.c:101:15
    #4 0x825faf in stream_to_pack bulk-checkin.c:154:5
    #5 0x82467b in deflate_to_pack bulk-checkin.c:225:8
    #6 0x823ff1 in index_bulk_checkin bulk-checkin.c:264:15
    #7 0xa7cff2 in index_stream object-file.c:2234:9
    #8 0xa7bff7 in index_fd object-file.c:2256:9
    #9 0xa7d22d in index_path object-file.c:2274:7
    #10 0xb3c8c9 in add_to_index read-cache.c:802:7
    #11 0xb3e039 in add_file_to_index read-cache.c:835:9
    #12 0x4a99c3 in add_files add.c:458:7
    #13 0x4a7276 in cmd_add add.c:670:18
    #14 0x4a1e76 in run_builtin git.c:461:11
    #15 0x49e1e7 in handle_builtin git.c:714:3
    #16 0x4a0c08 in run_argv git.c:781:4
    #17 0x49d5a8 in cmd_main git.c:912:19
    #18 0x7974da in main common-main.c:52:11
    #19 0x7f75da66f349 in __libc_start_main (/lib64/libc.so.6+0x24349)
    #20 0x421bd9 in _start start.S:120

  Uninitialized value was stored to memory at
    #0 0x7f75db58fa6b in crc32_little crc32.c:283:9
    #1 0x7f75db58d5b3 in crc32_z crc32.c:220:20
    #2 0x7f75db59668c in crc32 crc32.c:242:12
    #3 0x8c94f8 in hashwrite csum-file.c:101:15
    #4 0x825faf in stream_to_pack bulk-checkin.c:154:5
    #5 0x82467b in deflate_to_pack bulk-checkin.c:225:8
    #6 0x823ff1 in index_bulk_checkin bulk-checkin.c:264:15
    #7 0xa7cff2 in index_stream object-file.c:2234:9
    #8 0xa7bff7 in index_fd object-file.c:2256:9
    #9 0xa7d22d in index_path object-file.c:2274:7
    #10 0xb3c8c9 in add_to_index read-cache.c:802:7
    #11 0xb3e039 in add_file_to_index read-cache.c:835:9
    #12 0x4a99c3 in add_files add.c:458:7
    #13 0x4a7276 in cmd_add add.c:670:18
    #14 0x4a1e76 in run_builtin git.c:461:11
    #15 0x49e1e7 in handle_builtin git.c:714:3
    #16 0x4a0c08 in run_argv git.c:781:4
    #17 0x49d5a8 in cmd_main git.c:912:19
    #18 0x7974da in main common-main.c:52:11
    #19 0x7f75da66f349 in __libc_start_main (/lib64/libc.so.6+0x24349)

  Uninitialized value was stored to memory at
    #0 0x447eb9 in __msan_memcpy msan_interceptors.cpp:1558:3
    #1 0x7f75db5c2011 in flush_pending deflate.c:746:5
    #2 0x7f75db5cafa0 in deflate_stored deflate.c:1815:9
    #3 0x7f75db5bb7d2 in deflate deflate.c:1005:34
    #4 0xd80b7f in git_deflate zlib.c:244:12
    #5 0x825dff in stream_to_pack bulk-checkin.c:140:12
    #6 0x82467b in deflate_to_pack bulk-checkin.c:225:8
    #7 0x823ff1 in index_bulk_checkin bulk-checkin.c:264:15
    #8 0xa7cff2 in index_stream object-file.c:2234:9
    #9 0xa7bff7 in index_fd object-file.c:2256:9
    #10 0xa7d22d in index_path object-file.c:2274:7
    #11 0xb3c8c9 in add_to_index read-cache.c:802:7
    #12 0xb3e039 in add_file_to_index read-cache.c:835:9
    #13 0x4a99c3 in add_files add.c:458:7
    #14 0x4a7276 in cmd_add add.c:670:18
    #15 0x4a1e76 in run_builtin git.c:461:11
    #16 0x49e1e7 in handle_builtin git.c:714:3
    #17 0x4a0c08 in run_argv git.c:781:4
    #18 0x49d5a8 in cmd_main git.c:912:19
    #19 0x7974da in main common-main.c:52:11

  Uninitialized value was stored to memory at
    #0 0x447eb9 in __msan_memcpy msan_interceptors.cpp:1558:3
    #1 0x7f75db644241 in _tr_stored_block trees.c:873:5
    #2 0x7f75db5cad7c in deflate_stored deflate.c:1813:9
    #3 0x7f75db5bb7d2 in deflate deflate.c:1005:34
    #4 0xd80b7f in git_deflate zlib.c:244:12
    #5 0x825dff in stream_to_pack bulk-checkin.c:140:12
    #6 0x82467b in deflate_to_pack bulk-checkin.c:225:8
    #7 0x823ff1 in index_bulk_checkin bulk-checkin.c:264:15
    #8 0xa7cff2 in index_stream object-file.c:2234:9
    #9 0xa7bff7 in index_fd object-file.c:2256:9
    #10 0xa7d22d in index_path object-file.c:2274:7
    #11 0xb3c8c9 in add_to_index read-cache.c:802:7
    #12 0xb3e039 in add_file_to_index read-cache.c:835:9
    #13 0x4a99c3 in add_files add.c:458:7
    #14 0x4a7276 in cmd_add add.c:670:18
    #15 0x4a1e76 in run_builtin git.c:461:11
    #16 0x49e1e7 in handle_builtin git.c:714:3
    #17 0x4a0c08 in run_argv git.c:781:4
    #18 0x49d5a8 in cmd_main git.c:912:19
    #19 0x7974da in main common-main.c:52:11

  Uninitialized value was stored to memory at
    #0 0x447eb9 in __msan_memcpy msan_interceptors.cpp:1558:3
    #1 0x7f75db5c8fcf in deflate_stored deflate.c:1783:9
    #2 0x7f75db5bb7d2 in deflate deflate.c:1005:34
    #3 0xd80b7f in git_deflate zlib.c:244:12
    #4 0x825dff in stream_to_pack bulk-checkin.c:140:12
    #5 0x82467b in deflate_to_pack bulk-checkin.c:225:8
    #6 0x823ff1 in index_bulk_checkin bulk-checkin.c:264:15
    #7 0xa7cff2 in index_stream object-file.c:2234:9
    #8 0xa7bff7 in index_fd object-file.c:2256:9
    #9 0xa7d22d in index_path object-file.c:2274:7
    #10 0xb3c8c9 in add_to_index read-cache.c:802:7
    #11 0xb3e039 in add_file_to_index read-cache.c:835:9
    #12 0x4a99c3 in add_files add.c:458:7
    #13 0x4a7276 in cmd_add add.c:670:18
    #14 0x4a1e76 in run_builtin git.c:461:11
    #15 0x49e1e7 in handle_builtin git.c:714:3
    #16 0x4a0c08 in run_argv git.c:781:4
    #17 0x49d5a8 in cmd_main git.c:912:19
    #18 0x7974da in main common-main.c:52:11
    #19 0x7f75da66f349 in __libc_start_main (/lib64/libc.so.6+0x24349)

  Uninitialized value was stored to memory at
    #0 0x447eb9 in __msan_memcpy msan_interceptors.cpp:1558:3
    #1 0x7f75db5ea545 in read_buf deflate.c:1181:5
    #2 0x7f75db5c97f7 in deflate_stored deflate.c:1791:9
    #3 0x7f75db5bb7d2 in deflate deflate.c:1005:34
    #4 0xd80b7f in git_deflate zlib.c:244:12
    #5 0x825dff in stream_to_pack bulk-checkin.c:140:12
    #6 0x82467b in deflate_to_pack bulk-checkin.c:225:8
    #7 0x823ff1 in index_bulk_checkin bulk-checkin.c:264:15
    #8 0xa7cff2 in index_stream object-file.c:2234:9
    #9 0xa7bff7 in index_fd object-file.c:2256:9
    #10 0xa7d22d in index_path object-file.c:2274:7
    #11 0xb3c8c9 in add_to_index read-cache.c:802:7
    #12 0xb3e039 in add_file_to_index read-cache.c:835:9
    #13 0x4a99c3 in add_files add.c:458:7
    #14 0x4a7276 in cmd_add add.c:670:18
    #15 0x4a1e76 in run_builtin git.c:461:11
    #16 0x49e1e7 in handle_builtin git.c:714:3
    #17 0x4a0c08 in run_argv git.c:781:4
    #18 0x49d5a8 in cmd_main git.c:912:19
    #19 0x7974da in main common-main.c:52:11

  Uninitialized value was created by an allocation of 'ibuf' in the stack frame of function 'stream_to_pack'
    #0 0x825710 in stream_to_pack bulk-checkin.c:101

SUMMARY: MemorySanitizer: use-of-uninitialized-value crc32.c:283:9 in crc32_little
Exiting

Signed-off-by: Andrzej Hunt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Oct 6, 2021
In a sparse index it is possible for the tree that is being verified
to be freed while it is being verified. This happens when
index_name_pos() looks up a entry that is missing from the index and
that would be a descendant of a sparse entry. That triggers a call to
ensure_full_index() which frees the cache tree that is being verified.
Carrying on trying to verify the tree after this results in a
use-after-free bug. Instead restart the verification if a sparse index
is converted to a full index. This bug is triggered by a call to
reset_head() in "git rebase --apply". Thanks to René Scharfe for his
help analyzing the problem.

==74345==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000001b20 at pc 0x557cbe82d3a2 bp 0x7ffdfee08090 sp 0x7ffdfee08080
READ of size 4 at 0x606000001b20 thread T0
    #0 0x557cbe82d3a1 in verify_one /home/phil/src/git/cache-tree.c:863
    #1 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #2 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #3 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #4 0x557cbe830a2b in cache_tree_verify /home/phil/src/git/cache-tree.c:910
    #5 0x557cbea53741 in write_locked_index /home/phil/src/git/read-cache.c:3250
    #6 0x557cbeab7fdd in reset_head /home/phil/src/git/reset.c:87
    #7 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #8 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #9 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #10 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #11 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #12 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #13 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
    #14 0x557cbe5bcb8d in _start (/home/phil/src/git/git+0x1b9b8d)

0x606000001b20 is located 0 bytes inside of 56-byte region [0x606000001b20,0x606000001b58)
freed by thread T0 here:
    #0 0x7fdd4bacff19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x557cbe82af60 in cache_tree_free /home/phil/src/git/cache-tree.c:35
    #2 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #3 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #4 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #5 0x557cbeb2557a in ensure_full_index /home/phil/src/git/sparse-index.c:310
    #6 0x557cbea45c4a in index_name_stage_pos /home/phil/src/git/read-cache.c:588
    #7 0x557cbe82ce37 in verify_one /home/phil/src/git/cache-tree.c:850
    #8 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #9 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #10 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #11 0x557cbe830a2b in cache_tree_verify /home/phil/src/git/cache-tree.c:910
    #12 0x557cbea53741 in write_locked_index /home/phil/src/git/read-cache.c:3250
    #13 0x557cbeab7fdd in reset_head /home/phil/src/git/reset.c:87
    #14 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #15 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #16 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #17 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #18 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #19 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #20 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

previously allocated by thread T0 here:
    #0 0x7fdd4bad0459 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x557cbebc1807 in xcalloc /home/phil/src/git/wrapper.c:140
    #2 0x557cbe82b7d8 in cache_tree /home/phil/src/git/cache-tree.c:17
    #3 0x557cbe82b7d8 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:763
    #4 0x557cbe82b837 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:764
    #5 0x557cbe82b837 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:764
    #6 0x557cbe8304e1 in prime_cache_tree /home/phil/src/git/cache-tree.c:779
    #7 0x557cbeab7fa7 in reset_head /home/phil/src/git/reset.c:85
    #8 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #9 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #10 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #11 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #12 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #13 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #14 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

Signed-off-by: Phillip Wood <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Oct 7, 2021
In a sparse index it is possible for the tree that is being verified
to be freed while it is being verified. This happens when the index is
sparse but the cache tree is not and index_name_pos() looks up a path
from the cache tree that is a descendant of a sparse index entry. That
triggers a call to ensure_full_index() which frees the cache tree that
is being verified.  Carrying on trying to verify the tree after this
results in a use-after-free bug. Instead restart the verification if a
sparse index is converted to a full index. This bug is triggered by a
call to reset_head() in "git rebase --apply". Thanks to René Scharfe
and Derrick Stolee for their help analyzing the problem.

==74345==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000001b20 at pc 0x557cbe82d3a2 bp 0x7ffdfee08090 sp 0x7ffdfee08080
READ of size 4 at 0x606000001b20 thread T0
    #0 0x557cbe82d3a1 in verify_one /home/phil/src/git/cache-tree.c:863
    #1 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #2 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #3 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #4 0x557cbe830a2b in cache_tree_verify /home/phil/src/git/cache-tree.c:910
    #5 0x557cbea53741 in write_locked_index /home/phil/src/git/read-cache.c:3250
    #6 0x557cbeab7fdd in reset_head /home/phil/src/git/reset.c:87
    #7 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #8 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #9 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #10 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #11 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #12 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #13 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
    #14 0x557cbe5bcb8d in _start (/home/phil/src/git/git+0x1b9b8d)

0x606000001b20 is located 0 bytes inside of 56-byte region [0x606000001b20,0x606000001b58)
freed by thread T0 here:
    #0 0x7fdd4bacff19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x557cbe82af60 in cache_tree_free /home/phil/src/git/cache-tree.c:35
    #2 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #3 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #4 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #5 0x557cbeb2557a in ensure_full_index /home/phil/src/git/sparse-index.c:310
    #6 0x557cbea45c4a in index_name_stage_pos /home/phil/src/git/read-cache.c:588
    #7 0x557cbe82ce37 in verify_one /home/phil/src/git/cache-tree.c:850
    #8 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #9 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #10 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #11 0x557cbe830a2b in cache_tree_verify /home/phil/src/git/cache-tree.c:910
    #12 0x557cbea53741 in write_locked_index /home/phil/src/git/read-cache.c:3250
    #13 0x557cbeab7fdd in reset_head /home/phil/src/git/reset.c:87
    #14 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #15 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #16 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #17 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #18 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #19 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #20 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

previously allocated by thread T0 here:
    #0 0x7fdd4bad0459 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x557cbebc1807 in xcalloc /home/phil/src/git/wrapper.c:140
    #2 0x557cbe82b7d8 in cache_tree /home/phil/src/git/cache-tree.c:17
    #3 0x557cbe82b7d8 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:763
    #4 0x557cbe82b837 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:764
    #5 0x557cbe82b837 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:764
    #6 0x557cbe8304e1 in prime_cache_tree /home/phil/src/git/cache-tree.c:779
    #7 0x557cbeab7fa7 in reset_head /home/phil/src/git/reset.c:85
    #8 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #9 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #10 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #11 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #12 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #13 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #14 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

Signed-off-by: Phillip Wood <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
jeffhostetler pushed a commit to jeffhostetler/git that referenced this pull request Oct 13, 2021
In a sparse index it is possible for the tree that is being verified
to be freed while it is being verified. This happens when the index is
sparse but the cache tree is not and index_name_pos() looks up a path
from the cache tree that is a descendant of a sparse index entry. That
triggers a call to ensure_full_index() which frees the cache tree that
is being verified.  Carrying on trying to verify the tree after this
results in a use-after-free bug. Instead restart the verification if a
sparse index is converted to a full index. This bug is triggered by a
call to reset_head() in "git rebase --apply". Thanks to René Scharfe
and Derrick Stolee for their help analyzing the problem.

==74345==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000001b20 at pc 0x557cbe82d3a2 bp 0x7ffdfee08090 sp 0x7ffdfee08080
READ of size 4 at 0x606000001b20 thread T0
    #0 0x557cbe82d3a1 in verify_one /home/phil/src/git/cache-tree.c:863
    #1 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #2 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #3 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #4 0x557cbe830a2b in cache_tree_verify /home/phil/src/git/cache-tree.c:910
    #5 0x557cbea53741 in write_locked_index /home/phil/src/git/read-cache.c:3250
    #6 0x557cbeab7fdd in reset_head /home/phil/src/git/reset.c:87
    #7 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #8 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #9 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #10 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #11 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #12 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    #13 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
    git-for-windows#14 0x557cbe5bcb8d in _start (/home/phil/src/git/git+0x1b9b8d)

0x606000001b20 is located 0 bytes inside of 56-byte region [0x606000001b20,0x606000001b58)
freed by thread T0 here:
    #0 0x7fdd4bacff19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x557cbe82af60 in cache_tree_free /home/phil/src/git/cache-tree.c:35
    #2 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #3 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #4 0x557cbe82aee5 in cache_tree_free /home/phil/src/git/cache-tree.c:31
    #5 0x557cbeb2557a in ensure_full_index /home/phil/src/git/sparse-index.c:310
    #6 0x557cbea45c4a in index_name_stage_pos /home/phil/src/git/read-cache.c:588
    #7 0x557cbe82ce37 in verify_one /home/phil/src/git/cache-tree.c:850
    #8 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #9 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #10 0x557cbe82ca9d in verify_one /home/phil/src/git/cache-tree.c:840
    #11 0x557cbe830a2b in cache_tree_verify /home/phil/src/git/cache-tree.c:910
    #12 0x557cbea53741 in write_locked_index /home/phil/src/git/read-cache.c:3250
    #13 0x557cbeab7fdd in reset_head /home/phil/src/git/reset.c:87
    git-for-windows#14 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    git-for-windows#15 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    git-for-windows#16 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    git-for-windows#17 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    git-for-windows#18 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    git-for-windows#19 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    git-for-windows#20 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

previously allocated by thread T0 here:
    #0 0x7fdd4bad0459 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x557cbebc1807 in xcalloc /home/phil/src/git/wrapper.c:140
    #2 0x557cbe82b7d8 in cache_tree /home/phil/src/git/cache-tree.c:17
    #3 0x557cbe82b7d8 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:763
    #4 0x557cbe82b837 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:764
    #5 0x557cbe82b837 in prime_cache_tree_rec /home/phil/src/git/cache-tree.c:764
    #6 0x557cbe8304e1 in prime_cache_tree /home/phil/src/git/cache-tree.c:779
    #7 0x557cbeab7fa7 in reset_head /home/phil/src/git/reset.c:85
    #8 0x557cbe72147f in cmd_rebase builtin/rebase.c:2074
    #9 0x557cbe5bd151 in run_builtin /home/phil/src/git/git.c:461
    #10 0x557cbe5bd151 in handle_builtin /home/phil/src/git/git.c:714
    #11 0x557cbe5c0503 in run_argv /home/phil/src/git/git.c:781
    #12 0x557cbe5c0503 in cmd_main /home/phil/src/git/git.c:912
    #13 0x557cbe5bad28 in main /home/phil/src/git/common-main.c:52
    git-for-windows#14 0x7fdd4b82eb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

Signed-off-by: Phillip Wood <[email protected]>
Signed-off-by: Derrick Stolee <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Oct 30, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:

#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56

Backtrace from the death is:

#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Oct 31, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
Add config option `windows.appendAtomically`

Atomic append on windows is only supported on local disk files, and it may
cause errors in other situations, e.g. network file system. If that is the
case, this config option should be used to turn atomic append off.

With these edits, status for old-style submodules with commondir
needs to be fixed, due to the following.

In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Co-Authored-By: Johannes Schindelin <[email protected]>
Signed-off-by: 孙卓识 <[email protected]>
Signed-off-by: Johannes Schindelin <[email protected]>
Signed-off-by: Andrey Zabavnikov <[email protected]>
sceptical-coder added a commit to sceptical-coder/git that referenced this pull request Nov 3, 2022
Add config option `windows.appendAtomically`

Atomic append on windows is only supported on local disk files, and it may
cause errors in other situations, e.g. network file system. If that is the
case, this config option should be used to turn atomic append off.

With these edits, the status command for old-style submodules with commondir
needs to be fixed, due to the following.

In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, after the addition of the new config option, when
`git status` is run in the root repo of such a setup, it gives an output
akin to this:
```sh
$ git status
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
$ GIT_DIR=.git git -C commonlibs/ status --porcelain=2
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:
```
#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
    at compat/mingw.c:784
git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#8  0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```
Backtrace from the death is:
```
#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
    at usage.c:210
git-for-windows#1  0x<address-41> in access_or_die (
    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
git-for-windows#3  0x<address-38> in config_with_options (
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
    at config.c:2524
git-for-windows#5  0x<address-33> in git_config_check_init (
    repo=0x<address-19> <the_repo>) at config.c:2543
git-for-windows#6  0x<address-32> in repo_config_get_bool (
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
git-for-windows#7  0x<address-31> in git_config_get_bool (
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
git-for-windows#8  0x<address-28> in mingw_open (
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
    gitdir=0x<address-22> ".git") at setup.c:313
git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
    commondir=0x0) at repository.c:57
git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
    at environment.c:179
git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
    at environment.c:334
git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
git-for-windows#16 0x<address-12> in chdir_notify (
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
    argc=2, argv=0x<address-2>) at git.c:458
git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
    at git.c:721
git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
    at git.c:788
git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
    at common-main.c:56
```

Co-Authored-By: Johannes Schindelin <[email protected]>
Co-Authored-By: Andrey Zabavnikov <[email protected]>
Signed-off-by: 孙卓识 <[email protected]>
Signed-off-by: Johannes Schindelin <[email protected]>
Signed-off-by: Andrey Zabavnikov <[email protected]>
dscho pushed a commit to sceptical-coder/git that referenced this pull request Nov 4, 2022
In some setups, old-style submodules (i.e. the ones
with .git directory within theirs worktrees) with commondir
can be of tremendous help. For example, commondir link can be
used to avoid duplication of objects and also to keep branches
in sync with multiple copies of the repo's worktree, while keeping
the .git directory inside the worktree can be (ab?-)used to exploit
the sharing of the same submodule worktree across different projects
(this at least works on Windows with submodule directory being
a directory junction, but having a junction is not relevant for
reproducing the bug described below).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
fatal: unable to access '�??\1?/config': Invalid argument
fatal: 'git status --porcelain=2' failed in submodule commonlibs
```
where `�??\1?` part of '�??\1?/config' varies from run to run, and
`commonlibs` is the name of submodule's directory.

Currently, when Git discovers old-style submodule , it spawns subprocess
to get its status, like this one:
```sh
cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2
```
Unsurprisingly, the following output is also quite unexpected:
```
fatal: unable to access '`??L&?/config': Invalid argument
```

The core reason for these is that global repository field for
commondir is not being cleared to `NULL` after being `free()`'d
in `repo_set_commondir()`, which is precisely what this commit fixes.

Regarding the further details of the case of investigation,
this value of struct pointed by the global `the_repository` pointer is
checked for being not-NULL down in the callstack in compatibility layer
for MinGW in a function that is called by `repo_set_commondir()` before
the `free()`'d value gets assigned in its body (i.e. the body of
`repo_set_commondir()`).

Backtrace from the check is:

	#0  mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
	    at compat/mingw.c:784
	git-for-windows#1  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
	    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
	git-for-windows#2  0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
	    gitdir=0x<address-22> ".git") at setup.c:313
	git-for-windows#3  0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
	    commondir=0x0) at repository.c:57
	git-for-windows#4  0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
	    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
	git-for-windows#5  0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
	    at environment.c:179
	git-for-windows#6  0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
	    at environment.c:334
	git-for-windows#7  0x<address-14> in update_relative_gitdir (name=0x0,
	    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
	    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
	git-for-windows#8  0x<address-12> in chdir_notify (
	    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
	git-for-windows#9  0x<address-10> in setup_work_tree () at setup.c:428
	git-for-windows#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
	    argc=2, argv=0x<address-2>) at git.c:458
	git-for-windows#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
	    at git.c:721
	git-for-windows#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
	    at git.c:788
	git-for-windows#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
	git-for-windows#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
	    at common-main.c:56

Backtrace from the death is:

	#0  die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
	    at usage.c:210
	git-for-windows#1  0x<address-41> in access_or_die (
	    path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
	    at wrapper.c:667
	git-for-windows#2  0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
	    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
	    at config.c:2142
	git-for-windows#3  0x<address-38> in config_with_options (
	    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
	    config_source=0x0, opts=0x<address-35>) at config.c:2198
	git-for-windows#4  0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
	    at config.c:2524
	git-for-windows#5  0x<address-33> in git_config_check_init (
	    repo=0x<address-19> <the_repo>) at config.c:2543
	git-for-windows#6  0x<address-32> in repo_config_get_bool (
	    repo=0x<address-19> <the_repo>,
	    key=0x<address-30> <pad+3116> "windows.appendatomically",
	    dest=0x<address-29> <append_atomically>) at config.c:2612
	git-for-windows#7  0x<address-31> in git_config_get_bool (
	    key=0x<address-30> <pad+3116> "windows.appendatomically",
	    dest=0x<address-29> <append_atomically>) at config.c:2714
	git-for-windows#8  0x<address-28> in mingw_open (
	    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
	git-for-windows#9  0x<address-27> in strbuf_read_file (sb=0x<address-26>,
	    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
	git-for-windows#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
	    gitdir=0x<address-22> ".git") at setup.c:313
	git-for-windows#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
	    commondir=0x0) at repository.c:57
	git-for-windows#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
	    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
	git-for-windows#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
	    at environment.c:179
	git-for-windows#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
	    at environment.c:334
	git-for-windows#15 0x<address-14> in update_relative_gitdir (name=0x0,
	    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
	    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
	git-for-windows#16 0x<address-12> in chdir_notify (
	    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
	git-for-windows#17 0x<address-10> in setup_work_tree () at setup.c:428
	git-for-windows#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
	    argc=2, argv=0x<address-2>) at git.c:458
	git-for-windows#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
	    at git.c:721
	git-for-windows#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
	    at git.c:788
	git-for-windows#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
	git-for-windows#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
	    at common-main.c:56

Signed-off-by: Andrey Zabavnikov <[email protected]>
derrickstolee pushed a commit that referenced this pull request Jan 17, 2023
It is possible to trigger an integer overflow when parsing attribute
names when there are more than 2^31 of them for a single pattern. This
can either lead to us dying due to trying to request too many bytes:

     blob=$(perl -e 'print "f" . " a=" x 2147483649' | git hash-object -w --stdin)
     git update-index --add --cacheinfo 100644,$blob,.gitattributes
     git attr-check --all file

    =================================================================
    ==1022==ERROR: AddressSanitizer: requested allocation size 0xfffffff800000032 (0xfffffff800001038 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)
        #0 0x7fd3efabf411 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
        #1 0x5563a0a1e3d3 in xcalloc wrapper.c:150
        #2 0x5563a058d005 in parse_attr_line attr.c:384
        #3 0x5563a058e661 in handle_attr_line attr.c:660
        #4 0x5563a058eddb in read_attr_from_index attr.c:769
        #5 0x5563a058ef12 in read_attr attr.c:797
        #6 0x5563a058f24c in bootstrap_attr_stack attr.c:867
        #7 0x5563a058f4a3 in prepare_attr_stack attr.c:902
        #8 0x5563a05905da in collect_some_attrs attr.c:1097
        #9 0x5563a059093d in git_all_attrs attr.c:1128
        #10 0x5563a02f636e in check_attr builtin/check-attr.c:67
        #11 0x5563a02f6c12 in cmd_check_attr builtin/check-attr.c:183
        #12 0x5563a02aa993 in run_builtin git.c:466
        #13 0x5563a02ab397 in handle_builtin git.c:721
        #14 0x5563a02abb2b in run_argv git.c:788
        #15 0x5563a02ac991 in cmd_main git.c:926
        #16 0x5563a05432bd in main common-main.c:57
        #17 0x7fd3ef82228f  (/usr/lib/libc.so.6+0x2328f)

    ==1022==HINT: if you don't care about these errors you may set allocator_may_return_null=1
    SUMMARY: AddressSanitizer: allocation-size-too-big /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77 in __interceptor_calloc
    ==1022==ABORTING

Or, much worse, it can lead to an out-of-bounds write because we
underallocate and then memcpy(3P) into an array:

    perl -e '
        print "A " . "\rh="x2000000000;
        print "\rh="x2000000000;
        print "\rh="x294967294 . "\n"
    ' >.gitattributes
    git add .gitattributes
    git commit -am "evil attributes"

    $ git clone --quiet /path/to/repo
    =================================================================
    ==15062==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000002550 at pc 0x5555559884d5 bp 0x7fffffffbc60 sp 0x7fffffffbc58
    WRITE of size 8 at 0x602000002550 thread T0
        #0 0x5555559884d4 in parse_attr_line attr.c:393
        #1 0x5555559884d4 in handle_attr_line attr.c:660
        #2 0x555555988902 in read_attr_from_index attr.c:784
        #3 0x555555988902 in read_attr_from_index attr.c:747
        #4 0x555555988a1d in read_attr attr.c:800
        #5 0x555555989b0c in bootstrap_attr_stack attr.c:882
        #6 0x555555989b0c in prepare_attr_stack attr.c:917
        #7 0x555555989b0c in collect_some_attrs attr.c:1112
        #8 0x55555598b141 in git_check_attr attr.c:1126
        #9 0x555555a13004 in convert_attrs convert.c:1311
        #10 0x555555a95e04 in checkout_entry_ca entry.c:553
        #11 0x555555d58bf6 in checkout_entry entry.h:42
        #12 0x555555d58bf6 in check_updates unpack-trees.c:480
        #13 0x555555d5eb55 in unpack_trees unpack-trees.c:2040
        #14 0x555555785ab7 in checkout builtin/clone.c:724
        #15 0x555555785ab7 in cmd_clone builtin/clone.c:1384
        #16 0x55555572443c in run_builtin git.c:466
        #17 0x55555572443c in handle_builtin git.c:721
        #18 0x555555727872 in run_argv git.c:788
        #19 0x555555727872 in cmd_main git.c:926
        #20 0x555555721fa0 in main common-main.c:57
        #21 0x7ffff73f1d09 in __libc_start_main ../csu/libc-start.c:308
        #22 0x555555723f39 in _start (git+0x1cff39)

    0x602000002552 is located 0 bytes to the right of 2-byte region [0x602000002550,0x602000002552) allocated by thread T0 here:
        #0 0x7ffff768c037 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
        #1 0x555555d7fff7 in xcalloc wrapper.c:150
        #2 0x55555598815f in parse_attr_line attr.c:384
        #3 0x55555598815f in handle_attr_line attr.c:660
        #4 0x555555988902 in read_attr_from_index attr.c:784
        #5 0x555555988902 in read_attr_from_index attr.c:747
        #6 0x555555988a1d in read_attr attr.c:800
        #7 0x555555989b0c in bootstrap_attr_stack attr.c:882
        #8 0x555555989b0c in prepare_attr_stack attr.c:917
        #9 0x555555989b0c in collect_some_attrs attr.c:1112
        #10 0x55555598b141 in git_check_attr attr.c:1126
        #11 0x555555a13004 in convert_attrs convert.c:1311
        #12 0x555555a95e04 in checkout_entry_ca entry.c:553
        #13 0x555555d58bf6 in checkout_entry entry.h:42
        #14 0x555555d58bf6 in check_updates unpack-trees.c:480
        #15 0x555555d5eb55 in unpack_trees unpack-trees.c:2040
        #16 0x555555785ab7 in checkout builtin/clone.c:724
        #17 0x555555785ab7 in cmd_clone builtin/clone.c:1384
        #18 0x55555572443c in run_builtin git.c:466
        #19 0x55555572443c in handle_builtin git.c:721
        #20 0x555555727872 in run_argv git.c:788
        #21 0x555555727872 in cmd_main git.c:926
        #22 0x555555721fa0 in main common-main.c:57
        #23 0x7ffff73f1d09 in __libc_start_main ../csu/libc-start.c:308

    SUMMARY: AddressSanitizer: heap-buffer-overflow attr.c:393 in parse_attr_line
    Shadow bytes around the buggy address:
      0x0c047fff8450: fa fa 00 02 fa fa 00 07 fa fa fd fd fa fa 00 00
      0x0c047fff8460: fa fa 02 fa fa fa fd fd fa fa 00 06 fa fa 05 fa
      0x0c047fff8470: fa fa fd fd fa fa 00 02 fa fa 06 fa fa fa 05 fa
      0x0c047fff8480: fa fa 07 fa fa fa fd fd fa fa 00 01 fa fa 00 02
      0x0c047fff8490: fa fa 00 03 fa fa 00 fa fa fa 00 01 fa fa 00 03
    =>0x0c047fff84a0: fa fa 00 01 fa fa 00 02 fa fa[02]fa fa fa fa fa
      0x0c047fff84b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==15062==ABORTING

Fix this bug by using `size_t` instead to count the number of attributes
so that this value cannot reasonably overflow without running out of
memory before already.

Reported-by: Markus Vervier <[email protected]>
Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
derrickstolee pushed a commit that referenced this pull request Jan 17, 2023
When using a padding specifier in the pretty format passed to git-log(1)
we need to calculate the string length in several places. These string
lengths are stored in `int`s though, which means that these can easily
overflow when the input lengths exceeds 2GB. This can ultimately lead to
an out-of-bounds write when these are used in a call to memcpy(3P):

        ==8340==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f1ec62f97fe at pc 0x7f2127e5f427 bp 0x7ffd3bd63de0 sp 0x7ffd3bd63588
    WRITE of size 1 at 0x7f1ec62f97fe thread T0
        #0 0x7f2127e5f426 in __interceptor_memcpy /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
        #1 0x5628e96aa605 in format_and_pad_commit pretty.c:1762
        #2 0x5628e96aa7f4 in format_commit_item pretty.c:1801
        #3 0x5628e97cdb24 in strbuf_expand strbuf.c:429
        #4 0x5628e96ab060 in repo_format_commit_message pretty.c:1869
        #5 0x5628e96acd0f in pretty_print_commit pretty.c:2161
        #6 0x5628e95a44c8 in show_log log-tree.c:781
        #7 0x5628e95a76ba in log_tree_commit log-tree.c:1117
        #8 0x5628e922bed5 in cmd_log_walk_no_free builtin/log.c:508
        #9 0x5628e922c35b in cmd_log_walk builtin/log.c:549
        #10 0x5628e922f1a2 in cmd_log builtin/log.c:883
        #11 0x5628e9106993 in run_builtin git.c:466
        #12 0x5628e9107397 in handle_builtin git.c:721
        #13 0x5628e9107b07 in run_argv git.c:788
        #14 0x5628e91088a7 in cmd_main git.c:923
        #15 0x5628e939d682 in main common-main.c:57
        #16 0x7f2127c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #17 0x7f2127c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #18 0x5628e91020e4 in _start ../sysdeps/x86_64/start.S:115

    0x7f1ec62f97fe is located 2 bytes to the left of 4831838265-byte region [0x7f1ec62f9800,0x7f1fe62f9839)
    allocated by thread T0 here:
        #0 0x7f2127ebe7ea in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
        #1 0x5628e98774d4 in xrealloc wrapper.c:136
        #2 0x5628e97cb01c in strbuf_grow strbuf.c:99
        #3 0x5628e97ccd42 in strbuf_addchars strbuf.c:327
        #4 0x5628e96aa55c in format_and_pad_commit pretty.c:1761
        #5 0x5628e96aa7f4 in format_commit_item pretty.c:1801
        #6 0x5628e97cdb24 in strbuf_expand strbuf.c:429
        #7 0x5628e96ab060 in repo_format_commit_message pretty.c:1869
        #8 0x5628e96acd0f in pretty_print_commit pretty.c:2161
        #9 0x5628e95a44c8 in show_log log-tree.c:781
        #10 0x5628e95a76ba in log_tree_commit log-tree.c:1117
        #11 0x5628e922bed5 in cmd_log_walk_no_free builtin/log.c:508
        #12 0x5628e922c35b in cmd_log_walk builtin/log.c:549
        #13 0x5628e922f1a2 in cmd_log builtin/log.c:883
        #14 0x5628e9106993 in run_builtin git.c:466
        #15 0x5628e9107397 in handle_builtin git.c:721
        #16 0x5628e9107b07 in run_argv git.c:788
        #17 0x5628e91088a7 in cmd_main git.c:923
        #18 0x5628e939d682 in main common-main.c:57
        #19 0x7f2127c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #20 0x7f2127c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #21 0x5628e91020e4 in _start ../sysdeps/x86_64/start.S:115

    SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
    Shadow bytes around the buggy address:
      0x0fe458c572a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    =>0x0fe458c572f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]
      0x0fe458c57300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==8340==ABORTING

The pretty format can also be used in `git archive` operations via the
`export-subst` attribute. So this is what in our opinion makes this a
critical issue in the context of Git forges which allow to download an
archive of user supplied Git repositories.

Fix this vulnerability by using `size_t` instead of `int` to track the
string lengths. Add tests which detect this vulnerability when Git is
compiled with the address sanitizer.

Reported-by: Joern Schneeweisz <[email protected]>
Original-patch-by: Joern Schneeweisz <[email protected]>
Modified-by: Taylor  Blau <[email protected]>
Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Aug 19, 2024
It was recently reported that concurrent reads and writes may cause the
reftable backend to segfault. The root cause of this is that we do not
properly keep track of reftable readers across reloads.

Suppose that you have a reftable iterator and then decide to reload the
stack while iterating through the iterator. When the stack has been
rewritten since we have created the iterator, then we would end up
discarding a subset of readers that may still be in use by the iterator.
The consequence is that we now try to reference deallocated memory,
which of course segfaults.

One way to trigger this is in t5616, where some background maintenance
jobs have been leaking from one test into another. This leads to stack
traces like the following one:

  + git -c protocol.version=0 -C pc1 fetch --filter=blob:limit=29999 --refetch origin
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==657994==ERROR: AddressSanitizer: SEGV on unknown address 0x7fa0f0ec6089 (pc 0x55f23e52ddf9 bp
0x7ffe7bfa1700 sp 0x7ffe7bfa1700 T0)
  ==657994==The signal is caused by a READ memory access.
      #0 0x55f23e52ddf9 in get_var_int reftable/record.c:29
      #1 0x55f23e53295e in reftable_decode_keylen reftable/record.c:170
      #2 0x55f23e532cc0 in reftable_decode_key reftable/record.c:194
      #3 0x55f23e54e72e in block_iter_next reftable/block.c:398
      #4 0x55f23e5573dc in table_iter_next_in_block reftable/reader.c:240
      #5 0x55f23e5573dc in table_iter_next reftable/reader.c:355
      #6 0x55f23e5573dc in table_iter_next reftable/reader.c:339
      #7 0x55f23e551283 in merged_iter_advance_subiter reftable/merged.c:69
      #8 0x55f23e55169e in merged_iter_next_entry reftable/merged.c:123
      #9 0x55f23e55169e in merged_iter_next_void reftable/merged.c:172
      #10 0x55f23e537625 in reftable_iterator_next_ref reftable/generic.c:175
      #11 0x55f23e2cf9c6 in reftable_ref_iterator_advance refs/reftable-backend.c:464
      #12 0x55f23e2d996e in ref_iterator_advance refs/iterator.c:13
      #13 0x55f23e2d996e in do_for_each_ref_iterator refs/iterator.c:452
      #14 0x55f23dca6767 in get_ref_map builtin/fetch.c:623
      #15 0x55f23dca6767 in do_fetch builtin/fetch.c:1659
      #16 0x55f23dca6767 in fetch_one builtin/fetch.c:2133
      #17 0x55f23dca6767 in cmd_fetch builtin/fetch.c:2432
      #18 0x55f23dba7764 in run_builtin git.c:484
      #19 0x55f23dba7764 in handle_builtin git.c:741
      #20 0x55f23dbab61e in run_argv git.c:805
      #21 0x55f23dbab61e in cmd_main git.c:1000
      #22 0x55f23dba4781 in main common-main.c:64
      #23 0x7fa0f063fc89 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
      #24 0x7fa0f063fd44 in __libc_start_main_impl ../csu/libc-start.c:360
      #25 0x55f23dba6ad0 in _start (git+0xadfad0) (BuildId: 803b2b7f59beb03d7849fb8294a8e2145dd4aa27)

While it is somewhat awkward that the maintenance processes survive
tests in the first place, it is totally expected that reftables should
work alright with concurrent writers. Seemingly they don't.

The only underlying resource that we need to care about in this context
is the reftable reader, which is responsible for reading a single table
from disk. These readers get discarded immediately (unless reused) when
calling `reftable_stack_reload()`, which is wrong. We can only close
them once we know that there are no iterators using them anymore.

Prepare for a fix by converting the reftable readers to be refcounted.

Reported-by: Jeff King <[email protected]>
Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Aug 22, 2024
It was recently reported that concurrent reads and writes may cause the
reftable backend to segfault. The root cause of this is that we do not
properly keep track of reftable readers across reloads.

Suppose that you have a reftable iterator and then decide to reload the
stack while iterating through the iterator. When the stack has been
rewritten since we have created the iterator, then we would end up
discarding a subset of readers that may still be in use by the iterator.
The consequence is that we now try to reference deallocated memory,
which of course segfaults.

One way to trigger this is in t5616, where some background maintenance
jobs have been leaking from one test into another. This leads to stack
traces like the following one:

  + git -c protocol.version=0 -C pc1 fetch --filter=blob:limit=29999 --refetch origin
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==657994==ERROR: AddressSanitizer: SEGV on unknown address 0x7fa0f0ec6089 (pc 0x55f23e52ddf9 bp
0x7ffe7bfa1700 sp 0x7ffe7bfa1700 T0)
  ==657994==The signal is caused by a READ memory access.
      #0 0x55f23e52ddf9 in get_var_int reftable/record.c:29
      #1 0x55f23e53295e in reftable_decode_keylen reftable/record.c:170
      #2 0x55f23e532cc0 in reftable_decode_key reftable/record.c:194
      #3 0x55f23e54e72e in block_iter_next reftable/block.c:398
      #4 0x55f23e5573dc in table_iter_next_in_block reftable/reader.c:240
      #5 0x55f23e5573dc in table_iter_next reftable/reader.c:355
      #6 0x55f23e5573dc in table_iter_next reftable/reader.c:339
      #7 0x55f23e551283 in merged_iter_advance_subiter reftable/merged.c:69
      #8 0x55f23e55169e in merged_iter_next_entry reftable/merged.c:123
      #9 0x55f23e55169e in merged_iter_next_void reftable/merged.c:172
      #10 0x55f23e537625 in reftable_iterator_next_ref reftable/generic.c:175
      #11 0x55f23e2cf9c6 in reftable_ref_iterator_advance refs/reftable-backend.c:464
      #12 0x55f23e2d996e in ref_iterator_advance refs/iterator.c:13
      #13 0x55f23e2d996e in do_for_each_ref_iterator refs/iterator.c:452
      #14 0x55f23dca6767 in get_ref_map builtin/fetch.c:623
      #15 0x55f23dca6767 in do_fetch builtin/fetch.c:1659
      #16 0x55f23dca6767 in fetch_one builtin/fetch.c:2133
      #17 0x55f23dca6767 in cmd_fetch builtin/fetch.c:2432
      #18 0x55f23dba7764 in run_builtin git.c:484
      #19 0x55f23dba7764 in handle_builtin git.c:741
      #20 0x55f23dbab61e in run_argv git.c:805
      #21 0x55f23dbab61e in cmd_main git.c:1000
      #22 0x55f23dba4781 in main common-main.c:64
      #23 0x7fa0f063fc89 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
      #24 0x7fa0f063fd44 in __libc_start_main_impl ../csu/libc-start.c:360
      #25 0x55f23dba6ad0 in _start (git+0xadfad0) (BuildId: 803b2b7f59beb03d7849fb8294a8e2145dd4aa27)

While it is somewhat awkward that the maintenance processes survive
tests in the first place, it is totally expected that reftables should
work alright with concurrent writers. Seemingly they don't.

The only underlying resource that we need to care about in this context
is the reftable reader, which is responsible for reading a single table
from disk. These readers get discarded immediately (unless reused) when
calling `reftable_stack_reload()`, which is wrong. We can only close
them once we know that there are no iterators using them anymore.

Prepare for a fix by converting the reftable readers to be refcounted.

Reported-by: Jeff King <[email protected]>
Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Aug 23, 2024
It was recently reported that concurrent reads and writes may cause the
reftable backend to segfault. The root cause of this is that we do not
properly keep track of reftable readers across reloads.

Suppose that you have a reftable iterator and then decide to reload the
stack while iterating through the iterator. When the stack has been
rewritten since we have created the iterator, then we would end up
discarding a subset of readers that may still be in use by the iterator.
The consequence is that we now try to reference deallocated memory,
which of course segfaults.

One way to trigger this is in t5616, where some background maintenance
jobs have been leaking from one test into another. This leads to stack
traces like the following one:

  + git -c protocol.version=0 -C pc1 fetch --filter=blob:limit=29999 --refetch origin
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==657994==ERROR: AddressSanitizer: SEGV on unknown address 0x7fa0f0ec6089 (pc 0x55f23e52ddf9 bp
0x7ffe7bfa1700 sp 0x7ffe7bfa1700 T0)
  ==657994==The signal is caused by a READ memory access.
      #0 0x55f23e52ddf9 in get_var_int reftable/record.c:29
      #1 0x55f23e53295e in reftable_decode_keylen reftable/record.c:170
      #2 0x55f23e532cc0 in reftable_decode_key reftable/record.c:194
      #3 0x55f23e54e72e in block_iter_next reftable/block.c:398
      #4 0x55f23e5573dc in table_iter_next_in_block reftable/reader.c:240
      #5 0x55f23e5573dc in table_iter_next reftable/reader.c:355
      #6 0x55f23e5573dc in table_iter_next reftable/reader.c:339
      #7 0x55f23e551283 in merged_iter_advance_subiter reftable/merged.c:69
      #8 0x55f23e55169e in merged_iter_next_entry reftable/merged.c:123
      #9 0x55f23e55169e in merged_iter_next_void reftable/merged.c:172
      #10 0x55f23e537625 in reftable_iterator_next_ref reftable/generic.c:175
      #11 0x55f23e2cf9c6 in reftable_ref_iterator_advance refs/reftable-backend.c:464
      #12 0x55f23e2d996e in ref_iterator_advance refs/iterator.c:13
      #13 0x55f23e2d996e in do_for_each_ref_iterator refs/iterator.c:452
      #14 0x55f23dca6767 in get_ref_map builtin/fetch.c:623
      #15 0x55f23dca6767 in do_fetch builtin/fetch.c:1659
      #16 0x55f23dca6767 in fetch_one builtin/fetch.c:2133
      #17 0x55f23dca6767 in cmd_fetch builtin/fetch.c:2432
      #18 0x55f23dba7764 in run_builtin git.c:484
      #19 0x55f23dba7764 in handle_builtin git.c:741
      #20 0x55f23dbab61e in run_argv git.c:805
      #21 0x55f23dbab61e in cmd_main git.c:1000
      #22 0x55f23dba4781 in main common-main.c:64
      #23 0x7fa0f063fc89 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
      #24 0x7fa0f063fd44 in __libc_start_main_impl ../csu/libc-start.c:360
      #25 0x55f23dba6ad0 in _start (git+0xadfad0) (BuildId: 803b2b7f59beb03d7849fb8294a8e2145dd4aa27)

While it is somewhat awkward that the maintenance processes survive
tests in the first place, it is totally expected that reftables should
work alright with concurrent writers. Seemingly they don't.

The only underlying resource that we need to care about in this context
is the reftable reader, which is responsible for reading a single table
from disk. These readers get discarded immediately (unless reused) when
calling `reftable_stack_reload()`, which is wrong. We can only close
them once we know that there are no iterators using them anymore.

Prepare for a fix by converting the reftable readers to be refcounted.

Reported-by: Jeff King <[email protected]>
Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
git-for-windows-ci pushed a commit that referenced this pull request Dec 31, 2024
In 1b9e9be (csum-file.c: use unsafe SHA-1 implementation when
available, 2024-09-26) we have converted our `struct hashfile` to use
the unsafe SHA1 backend, which results in a significant speedup. One
needs to be careful with how to use that structure now though because
callers need to consistently use either the safe or unsafe variants of
SHA1, as otherwise one can easily trigger corruption.

As it turns out, we have one inconsistent usage in our tree because we
directly initialize `struct hashfile_checkpoint::ctx` with the safe
variant of SHA1, but end up writing to that context with the unsafe
ones. This went unnoticed so far because our CI systems do not exercise
different hash functions for these two backends, and consequently safe
and unsafe variants are equivalent. But when using SHA1DC as safe and
OpenSSL as unsafe backend this leads to a crash an t1050:

    ++ git -c core.compression=0 add large1
    AddressSanitizer:DEADLYSIGNAL
    =================================================================
    ==1367==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000040 (pc 0x7ffff7a01a99 bp 0x507000000db0 sp 0x7fffffff5690 T0)
    ==1367==The signal is caused by a READ memory access.
    ==1367==Hint: address points to the zero page.
        #0 0x7ffff7a01a99 in EVP_MD_CTX_copy_ex (/nix/store/h1ydpxkw9qhjdxjpic1pdc2nirggyy6f-openssl-3.3.2/lib/libcrypto.so.3+0x201a99) (BuildId: 41746a580d39075fc85e8c8065b6c07fb34e97d4)
        #1 0x555555ddde56 in openssl_SHA1_Clone ../sha1/openssl.h:40:2
        #2 0x555555dce2fc in git_hash_sha1_clone_unsafe ../object-file.c:123:2
        #3 0x555555c2d5f8 in hashfile_checkpoint ../csum-file.c:211:2
        #4 0x555555b9905d in deflate_blob_to_pack ../bulk-checkin.c:286:4
        #5 0x555555b98ae9 in index_blob_bulk_checkin ../bulk-checkin.c:362:15
        #6 0x555555ddab62 in index_blob_stream ../object-file.c:2756:9
        #7 0x555555dda420 in index_fd ../object-file.c:2778:9
        #8 0x555555ddad76 in index_path ../object-file.c:2796:7
        #9 0x555555e947f3 in add_to_index ../read-cache.c:771:7
        #10 0x555555e954a4 in add_file_to_index ../read-cache.c:804:9
        #11 0x5555558b5c39 in add_files ../builtin/add.c:355:7
        #12 0x5555558b412e in cmd_add ../builtin/add.c:578:18
        #13 0x555555b1f493 in run_builtin ../git.c:480:11
        #14 0x555555b1bfef in handle_builtin ../git.c:740:9
        #15 0x555555b1e6f4 in run_argv ../git.c:807:4
        #16 0x555555b1b87a in cmd_main ../git.c:947:19
        #17 0x5555561649e6 in main ../common-main.c:64:11
        #18 0x7ffff742a1fb in __libc_start_call_main (/nix/store/65h17wjrrlsj2rj540igylrx7fqcd6vq-glibc-2.40-36/lib/libc.so.6+0x2a1fb) (BuildId: bf320110569c8ec2425e9a0c5e4eb7e97f1fb6e4)
        #19 0x7ffff742a2b8 in __libc_start_main@GLIBC_2.2.5 (/nix/store/65h17wjrrlsj2rj540igylrx7fqcd6vq-glibc-2.40-36/lib/libc.so.6+0x2a2b8) (BuildId: bf320110569c8ec2425e9a0c5e4eb7e97f1fb6e4)
        #20 0x555555772c84 in _start (git+0x21ec84)

    ==1367==Register values:
    rax = 0x0000511000001080  rbx = 0x0000000000000000  rcx = 0x000000000000000c  rdx = 0x0000000000000000
    rdi = 0x0000000000000000  rsi = 0x0000507000000db0  rbp = 0x0000507000000db0  rsp = 0x00007fffffff5690
     r8 = 0x0000000000000000   r9 = 0x0000000000000000  r10 = 0x0000000000000000  r11 = 0x00007ffff7a01a30
    r12 = 0x0000000000000000  r13 = 0x00007fffffff6b38  r14 = 0x00007ffff7ffd000  r15 = 0x00005555563b9910
    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV (/nix/store/h1ydpxkw9qhjdxjpic1pdc2nirggyy6f-openssl-3.3.2/lib/libcrypto.so.3+0x201a99) (BuildId: 41746a580d39075fc85e8c8065b6c07fb34e97d4) in EVP_MD_CTX_copy_ex
    ==1367==ABORTING
    ./test-lib.sh: line 1023:  1367 Aborted                 git $config add large1
    error: last command exited with $?=134
    not ok 4 - add with -c core.compression=0

Fix the issue by using the unsafe variant instead.

Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
mjcheetham pushed a commit to mjcheetham/git that referenced this pull request Jan 20, 2025
An internal customer reported a segfault when running `git
sparse-checkout set` with the `index.sparse` config enabled. I was
unable to reproduce it locally, but with their help we debugged into the
failing process and discovered the following stacktrace:

```
#0  0x00007ff6318fb7b0 in rehash (map=0x3dfb00d0440, newsize=1048576) at hashmap.c:125
git-for-windows#1  0x00007ff6318fbc66 in hashmap_add (map=0x3dfb00d0440, entry=0x3dfb5c58bc8) at hashmap.c:247
git-for-windows#2  0x00007ff631937a70 in hash_index_entry (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:122
git-for-windows#3  0x00007ff631938a2f in add_name_hash (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:638
git-for-windows#4  0x00007ff631a064de in set_index_entry (istate=0x3dfb00d0400, nr=8291, ce=0x3dfb5c58bc8) at sparse-index.c:255
git-for-windows#5  0x00007ff631a06692 in add_path_to_index (oid=0x5ff130, base=0x5ff580, path=0x3dfb4b725da "<redacted>", mode=33188, context=0x5ff570)    at sparse-index.c:307
git-for-windows#6  0x00007ff631a3b48c in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41f60, base=0x5ff580, depth=2, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:46
git-for-windows#7  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41e80, base=0x5ff580, depth=1, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#8  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41ac8, base=0x5ff580, depth=0, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#9  0x00007ff631a06a95 in expand_index (istate=0x3dfb00d0100, pl=0x0) at sparse-index.c:422
git-for-windows#10 0x00007ff631a06cbd in ensure_full_index (istate=0x3dfb00d0100) at sparse-index.c:456
git-for-windows#11 0x00007ff631990d08 in index_name_stage_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21, stage=0,    search_mode=EXPAND_SPARSE) at read-cache.c:556
git-for-windows#12 0x00007ff631990d6c in index_name_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21) at read-cache.c:566
git-for-windows#13 0x00007ff63180dbb5 in sanitize_paths (argc=185, argv=0x3dfb0030018, prefix=0x0, skip_checks=0) at builtin/sparse-checkout.c:756
git-for-windows#14 0x00007ff63180de50 in sparse_checkout_set (argc=185, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:860
git-for-windows#15 0x00007ff63180e6c5 in cmd_sparse_checkout (argc=186, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:1063
git-for-windows#16 0x00007ff6317234cb in run_builtin (p=0x7ff631ad9b38 <commands+2808>, argc=187, argv=0x3dfb0030018) at git.c:548
git-for-windows#17 0x00007ff6317239c0 in handle_builtin (argc=187, argv=0x3dfb0030018) at git.c:808
git-for-windows#18 0x00007ff631723c7d in run_argv (argcp=0x5ffdd0, argv=0x5ffd78) at git.c:877
git-for-windows#19 0x00007ff6317241d1 in cmd_main (argc=187, argv=0x3dfb0030018) at git.c:1017
git-for-windows#20 0x00007ff631838b60 in main (argc=190, argv=0x3dfb0030000) at common-main.c:64 
```

The very bottom of the stack being the `rehash()` method from
`hashmap.c` as called within the `name-hash` API made me look at where
these hashmaps were being used in the sparse index logic. These were
being copied across indexes, which seems dangerous. Indeed, clearing
these hashmaps and setting them as not initialized fixes the segfault.

The second commit is a response to a test failure that happens in
`t1092-sparse-checkout-compatibility.sh` where `git stash pop` starts to
fail because the underlying `git checkout-index` process fails due to
colliding files. Passing the `-f` flag appears to work, but it's unclear
why this name-hash change causes that change in behavior.
mjcheetham pushed a commit to mjcheetham/git that referenced this pull request Mar 6, 2025
An internal customer reported a segfault when running `git
sparse-checkout set` with the `index.sparse` config enabled. I was
unable to reproduce it locally, but with their help we debugged into the
failing process and discovered the following stacktrace:

```
#0  0x00007ff6318fb7b0 in rehash (map=0x3dfb00d0440, newsize=1048576) at hashmap.c:125
git-for-windows#1  0x00007ff6318fbc66 in hashmap_add (map=0x3dfb00d0440, entry=0x3dfb5c58bc8) at hashmap.c:247
git-for-windows#2  0x00007ff631937a70 in hash_index_entry (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:122
git-for-windows#3  0x00007ff631938a2f in add_name_hash (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:638
git-for-windows#4  0x00007ff631a064de in set_index_entry (istate=0x3dfb00d0400, nr=8291, ce=0x3dfb5c58bc8) at sparse-index.c:255
git-for-windows#5  0x00007ff631a06692 in add_path_to_index (oid=0x5ff130, base=0x5ff580, path=0x3dfb4b725da "<redacted>", mode=33188, context=0x5ff570)    at sparse-index.c:307
git-for-windows#6  0x00007ff631a3b48c in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41f60, base=0x5ff580, depth=2, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:46
git-for-windows#7  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41e80, base=0x5ff580, depth=1, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#8  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41ac8, base=0x5ff580, depth=0, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#9  0x00007ff631a06a95 in expand_index (istate=0x3dfb00d0100, pl=0x0) at sparse-index.c:422
git-for-windows#10 0x00007ff631a06cbd in ensure_full_index (istate=0x3dfb00d0100) at sparse-index.c:456
git-for-windows#11 0x00007ff631990d08 in index_name_stage_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21, stage=0,    search_mode=EXPAND_SPARSE) at read-cache.c:556
git-for-windows#12 0x00007ff631990d6c in index_name_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21) at read-cache.c:566
git-for-windows#13 0x00007ff63180dbb5 in sanitize_paths (argc=185, argv=0x3dfb0030018, prefix=0x0, skip_checks=0) at builtin/sparse-checkout.c:756
git-for-windows#14 0x00007ff63180de50 in sparse_checkout_set (argc=185, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:860
git-for-windows#15 0x00007ff63180e6c5 in cmd_sparse_checkout (argc=186, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:1063
git-for-windows#16 0x00007ff6317234cb in run_builtin (p=0x7ff631ad9b38 <commands+2808>, argc=187, argv=0x3dfb0030018) at git.c:548
git-for-windows#17 0x00007ff6317239c0 in handle_builtin (argc=187, argv=0x3dfb0030018) at git.c:808
git-for-windows#18 0x00007ff631723c7d in run_argv (argcp=0x5ffdd0, argv=0x5ffd78) at git.c:877
git-for-windows#19 0x00007ff6317241d1 in cmd_main (argc=187, argv=0x3dfb0030018) at git.c:1017
git-for-windows#20 0x00007ff631838b60 in main (argc=190, argv=0x3dfb0030000) at common-main.c:64 
```

The very bottom of the stack being the `rehash()` method from
`hashmap.c` as called within the `name-hash` API made me look at where
these hashmaps were being used in the sparse index logic. These were
being copied across indexes, which seems dangerous. Indeed, clearing
these hashmaps and setting them as not initialized fixes the segfault.

The second commit is a response to a test failure that happens in
`t1092-sparse-checkout-compatibility.sh` where `git stash pop` starts to
fail because the underlying `git checkout-index` process fails due to
colliding files. Passing the `-f` flag appears to work, but it's unclear
why this name-hash change causes that change in behavior.
mjcheetham pushed a commit to mjcheetham/git that referenced this pull request Mar 13, 2025
An internal customer reported a segfault when running `git
sparse-checkout set` with the `index.sparse` config enabled. I was
unable to reproduce it locally, but with their help we debugged into the
failing process and discovered the following stacktrace:

```
#0  0x00007ff6318fb7b0 in rehash (map=0x3dfb00d0440, newsize=1048576) at hashmap.c:125
git-for-windows#1  0x00007ff6318fbc66 in hashmap_add (map=0x3dfb00d0440, entry=0x3dfb5c58bc8) at hashmap.c:247
git-for-windows#2  0x00007ff631937a70 in hash_index_entry (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:122
git-for-windows#3  0x00007ff631938a2f in add_name_hash (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:638
git-for-windows#4  0x00007ff631a064de in set_index_entry (istate=0x3dfb00d0400, nr=8291, ce=0x3dfb5c58bc8) at sparse-index.c:255
git-for-windows#5  0x00007ff631a06692 in add_path_to_index (oid=0x5ff130, base=0x5ff580, path=0x3dfb4b725da "<redacted>", mode=33188, context=0x5ff570)    at sparse-index.c:307
git-for-windows#6  0x00007ff631a3b48c in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41f60, base=0x5ff580, depth=2, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:46
git-for-windows#7  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41e80, base=0x5ff580, depth=1, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#8  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41ac8, base=0x5ff580, depth=0, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#9  0x00007ff631a06a95 in expand_index (istate=0x3dfb00d0100, pl=0x0) at sparse-index.c:422
git-for-windows#10 0x00007ff631a06cbd in ensure_full_index (istate=0x3dfb00d0100) at sparse-index.c:456
git-for-windows#11 0x00007ff631990d08 in index_name_stage_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21, stage=0,    search_mode=EXPAND_SPARSE) at read-cache.c:556
git-for-windows#12 0x00007ff631990d6c in index_name_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21) at read-cache.c:566
git-for-windows#13 0x00007ff63180dbb5 in sanitize_paths (argc=185, argv=0x3dfb0030018, prefix=0x0, skip_checks=0) at builtin/sparse-checkout.c:756
git-for-windows#14 0x00007ff63180de50 in sparse_checkout_set (argc=185, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:860
git-for-windows#15 0x00007ff63180e6c5 in cmd_sparse_checkout (argc=186, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:1063
git-for-windows#16 0x00007ff6317234cb in run_builtin (p=0x7ff631ad9b38 <commands+2808>, argc=187, argv=0x3dfb0030018) at git.c:548
git-for-windows#17 0x00007ff6317239c0 in handle_builtin (argc=187, argv=0x3dfb0030018) at git.c:808
git-for-windows#18 0x00007ff631723c7d in run_argv (argcp=0x5ffdd0, argv=0x5ffd78) at git.c:877
git-for-windows#19 0x00007ff6317241d1 in cmd_main (argc=187, argv=0x3dfb0030018) at git.c:1017
git-for-windows#20 0x00007ff631838b60 in main (argc=190, argv=0x3dfb0030000) at common-main.c:64 
```

The very bottom of the stack being the `rehash()` method from
`hashmap.c` as called within the `name-hash` API made me look at where
these hashmaps were being used in the sparse index logic. These were
being copied across indexes, which seems dangerous. Indeed, clearing
these hashmaps and setting them as not initialized fixes the segfault.

The second commit is a response to a test failure that happens in
`t1092-sparse-checkout-compatibility.sh` where `git stash pop` starts to
fail because the underlying `git checkout-index` process fails due to
colliding files. Passing the `-f` flag appears to work, but it's unclear
why this name-hash change causes that change in behavior.
mjcheetham pushed a commit to mjcheetham/git that referenced this pull request Mar 26, 2025
An internal customer reported a segfault when running `git
sparse-checkout set` with the `index.sparse` config enabled. I was
unable to reproduce it locally, but with their help we debugged into the
failing process and discovered the following stacktrace:

```
#0  0x00007ff6318fb7b0 in rehash (map=0x3dfb00d0440, newsize=1048576) at hashmap.c:125
git-for-windows#1  0x00007ff6318fbc66 in hashmap_add (map=0x3dfb00d0440, entry=0x3dfb5c58bc8) at hashmap.c:247
git-for-windows#2  0x00007ff631937a70 in hash_index_entry (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:122
git-for-windows#3  0x00007ff631938a2f in add_name_hash (istate=0x3dfb00d0400, ce=0x3dfb5c58bc8) at name-hash.c:638
git-for-windows#4  0x00007ff631a064de in set_index_entry (istate=0x3dfb00d0400, nr=8291, ce=0x3dfb5c58bc8) at sparse-index.c:255
git-for-windows#5  0x00007ff631a06692 in add_path_to_index (oid=0x5ff130, base=0x5ff580, path=0x3dfb4b725da "<redacted>", mode=33188, context=0x5ff570)    at sparse-index.c:307
git-for-windows#6  0x00007ff631a3b48c in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41f60, base=0x5ff580, depth=2, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:46
git-for-windows#7  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41e80, base=0x5ff580, depth=1, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#8  0x00007ff631a3b60b in read_tree_at (r=0x7ff631c026a0 <the_repo>, tree=0x3dfb5b41ac8, base=0x5ff580, depth=0, pathspec=0x5ff5a0,    fn=0x7ff631a064e5 <add_path_to_index>, context=0x5ff570) at tree.c:80
git-for-windows#9  0x00007ff631a06a95 in expand_index (istate=0x3dfb00d0100, pl=0x0) at sparse-index.c:422
git-for-windows#10 0x00007ff631a06cbd in ensure_full_index (istate=0x3dfb00d0100) at sparse-index.c:456
git-for-windows#11 0x00007ff631990d08 in index_name_stage_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21, stage=0,    search_mode=EXPAND_SPARSE) at read-cache.c:556
git-for-windows#12 0x00007ff631990d6c in index_name_pos (istate=0x3dfb00d0100, name=0x3dfb0020080 "algorithm/levenshtein", namelen=21) at read-cache.c:566
git-for-windows#13 0x00007ff63180dbb5 in sanitize_paths (argc=185, argv=0x3dfb0030018, prefix=0x0, skip_checks=0) at builtin/sparse-checkout.c:756
git-for-windows#14 0x00007ff63180de50 in sparse_checkout_set (argc=185, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:860
git-for-windows#15 0x00007ff63180e6c5 in cmd_sparse_checkout (argc=186, argv=0x3dfb0030018, prefix=0x0) at builtin/sparse-checkout.c:1063
git-for-windows#16 0x00007ff6317234cb in run_builtin (p=0x7ff631ad9b38 <commands+2808>, argc=187, argv=0x3dfb0030018) at git.c:548
git-for-windows#17 0x00007ff6317239c0 in handle_builtin (argc=187, argv=0x3dfb0030018) at git.c:808
git-for-windows#18 0x00007ff631723c7d in run_argv (argcp=0x5ffdd0, argv=0x5ffd78) at git.c:877
git-for-windows#19 0x00007ff6317241d1 in cmd_main (argc=187, argv=0x3dfb0030018) at git.c:1017
git-for-windows#20 0x00007ff631838b60 in main (argc=190, argv=0x3dfb0030000) at common-main.c:64 
```

The very bottom of the stack being the `rehash()` method from
`hashmap.c` as called within the `name-hash` API made me look at where
these hashmaps were being used in the sparse index logic. These were
being copied across indexes, which seems dangerous. Indeed, clearing
these hashmaps and setting them as not initialized fixes the segfault.

The second commit is a response to a test failure that happens in
`t1092-sparse-checkout-compatibility.sh` where `git stash pop` starts to
fail because the underlying `git checkout-index` process fails due to
colliding files. Passing the `-f` flag appears to work, but it's unclear
why this name-hash change causes that change in behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.