Go to file
Jeff King 613bef56b8 shorten_unambiguous_ref(): avoid sscanf()
To shorten a fully qualified ref (e.g., taking "refs/heads/foo" to just
"foo"), we munge the usual lookup rules ("refs/heads/%.*s", etc) to drop
the ".*" modifier (so "refs/heads/%s"), and then use sscanf() to match
that against the refname, pulling the "%s" content into a separate
buffer.

This has a few downsides:

  - sscanf("%s") reportedly misbehaves on macOS with some input and
    locale combinations, returning a partial or garbled string. See
    this thread:

      https://lore.kernel.org/git/CAGF3oAcCi+fG12j-1U0hcrWwkF5K_9WhOi6ZPHBzUUzfkrZDxA@mail.gmail.com/

  - scanf's matching of "%s" is greedy. So the "refs/remotes/%s/HEAD"
    rule would never pull "origin" out of "refs/remotes/origin/HEAD".
    Instead it always produced "origin/HEAD", which is redundant with
    the "refs/remotes/%s" rule.

  - scanf in general is an error-prone interface. For example, scanning
    for "%s" will copy bytes into a destination string, which must have
    been correctly sized ahead of time to avoid a buffer overflow. In
    this case, the code is OK (the buffer is pessimistically sized to
    match the original string, which should give us a maximum). But in
    general, we do not want to encourage people to use scanf at all.

So instead, let's note that our lookup rules are not arbitrary format
strings, but all contain exactly one "%.*s" placeholder. We already rely
on this, both for lookup (we feed the lookup format along with exactly
one int/ptr combo to snprintf, etc) and for shortening (we munge "%.*s"
to "%s", and then insist that sscanf() finds exactly one result).

We can parse this manually by just matching the bytes that occur before
and after the "%.*s" placeholder. While we have a few extra lines of
parsing code, the result is arguably simpler, as can skip the
preprocessing step and its tricky memory management entirely.

The in-code comments should explain the parsing strategy, but there's
one subtle change here. The original code allocated a single buffer, and
then overwrote it in each loop iteration, since that's the only option
sscanf() gives us. But our parser can actually return a ptr/len combo
for the matched string, which is all we need (since we just feed it back
to the lookup rules with "%.*s"), and then copy it only when returning
to the caller.

There are a few new tests here, all using symbolic-ref (the code can be
triggered in many ways, but symrefs are convenient in that we don't need
to create a real ref, which avoids any complications from the filesystem
munging the name):

  - the first covers the real-world case which misbehaved on macOS.
    Setting LC_ALL is required to trigger the problem there (since
    otherwise our tests use LC_ALL=C), and hopefully is at worst simply
    ignored on other systems (and doesn't cause libc to complain, etc,
    on systems without that locale).

  - the second covers the "origin/HEAD" case as discussed above, which
    is now fixed

  - the remainder are for "weird" cases that work both before and after
    this patch, but would be easy to get wrong with off-by-one problems
    in the parsing (and came out of discussions and earlier iterations
    of the patch that did get them wrong).

  - absent here are tests of boring, expected-to-work cases like
    "refs/heads/foo", etc. Those are covered all over the test suite
    both explicitly (for-each-ref's refname:short) and implicitly (in
    the output of git-status, etc).

Reported-by: 孟子易 <mengziyi540841@gmail.com>
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-02-15 08:53:17 -08:00
.github ci: use a newer `github-script` version 2022-12-10 16:32:16 +09:00
Documentation Git 2.39.2 2023-02-06 09:43:41 +01:00
block-sha1
builtin Sync with 2.38.4 2023-02-06 09:43:39 +01:00
ci Merge branch 'jx/ci-ubuntu-fix' into maint-2.38 2022-12-10 16:17:47 +09:00
compat Merge branch 'sz/macos-fsmonitor-symlinks' 2022-11-23 11:22:25 +09:00
contrib Merge branch 'ab/fewer-the-index-macros' 2022-12-01 18:38:07 +09:00
ewah
git-gui Makefiles: change search through $(MAKEFLAGS) for GNU make 4.4 2022-12-01 07:24:12 +09:00
gitk-git
gitweb
mergetools
negotiator negotiator/skipping: avoid stack overflow 2022-10-25 17:14:40 -07:00
oss-fuzz
perl Git.pm: trust rev-parse to find bare repositories 2022-10-22 16:39:48 -07:00
po l10n: zh_TW.po: Git 2.39-rc2 2022-12-11 01:27:25 +08:00
refs
reftable
sha1collisiondetection@855827c583
sha1dc
sha256
t shorten_unambiguous_ref(): avoid sscanf() 2023-02-15 08:53:17 -08:00
templates
trace2 trace2: add global counter mechanism 2022-10-24 12:45:26 -07:00
xdiff
.cirrus.yml
.clang-format
.editorconfig
.gitattributes
.gitignore Merge branch 'ab/coccicheck-incremental' 2022-11-23 11:22:23 +09:00
.gitmodules
.mailmap mailmap: update email address of Matheus Tavares 2022-12-10 09:17:36 +09:00
.tsan-suppressions
CODE_OF_CONDUCT.md
COPYING
GIT-VERSION-GEN Git 2.39.2 2023-02-06 09:43:41 +01:00
INSTALL Sync with 2.38.4 2023-02-06 09:43:39 +01:00
LGPL-2.1
Makefile Merge branch 'ab/coccicheck-incremental' 2022-11-23 11:22:23 +09:00
README.md
RelNotes Git 2.39.2 2023-02-06 09:43:41 +01:00
SECURITY.md
abspath.c
aclocal.m4
add-interactive.c read-cache API & users: make discard_index() return void 2022-11-21 12:06:15 +09:00
add-interactive.h
add-patch.c read-cache API & users: make discard_index() return void 2022-11-21 12:06:15 +09:00
advice.c
advice.h
alias.c
alias.h
alloc.c
alloc.h
apply.c Sync with 2.38.4 2023-02-06 09:43:39 +01:00
apply.h
archive-tar.c archive-tar: report filter start error only once 2022-10-30 19:50:43 -04:00
archive-zip.c
archive.c Merge branch 'rs/archive-dedup-printf' into maint-2.38 2022-10-27 15:24:14 -07:00
archive.h
attr.c Sync with maint-2.37 2023-01-19 13:48:26 -08:00
attr.h Merge branch 'maint-2.35' into maint-2.36 2022-12-13 21:19:11 +09:00
banned.h
base85.c
bisect.c replace and remove run_command_v_opt() 2022-10-30 14:04:51 -04:00
bisect.h
blame.c
blame.h
blob.c
blob.h
bloom.c
bloom.h
branch.c
branch.h
builtin.h
bulk-checkin.c
bulk-checkin.h
bundle-uri.c
bundle-uri.h
bundle.c
bundle.h Merge branch 'ds/bundle-uri-3' 2022-10-30 21:04:44 -04:00
cache-tree.c
cache-tree.h
cache.h cocci: apply "pending" index-compatibility to some "builtin/*.c" 2022-11-21 12:06:15 +09:00
cbtree.c
cbtree.h
chdir-notify.c
chdir-notify.h
check-builtins.sh
checkout.c
checkout.h
chunk-format.c
chunk-format.h
color.c
color.h
column.c utf8: fix truncated string lengths in `utf8_strnwidth()` 2022-12-09 14:26:21 +09:00
column.h
combine-diff.c
command-list.txt
commit-graph.c
commit-graph.h
commit-reach.c
commit-reach.h
commit-slab-decl.h
commit-slab-impl.h
commit-slab.h
commit.c Merge branch 'pw/rebase-keep-base-fixes' 2022-10-30 21:04:42 -04:00
commit.h rebase: be stricter when reading state files containing oids 2022-10-17 11:53:00 -07:00
common-main.c
config.c Merge branch 'pw/config-int-parse-fixes' 2022-11-28 12:13:43 +09:00
config.h
config.mak.dev
config.mak.in
config.mak.uname
configure.ac
connect.c
connect.h
connected.c receive-pack: only use visible refs for connectivity check 2022-11-17 16:22:52 -05:00
connected.h receive-pack: only use visible refs for connectivity check 2022-11-17 16:22:52 -05:00
convert.c convert: mark unused parameter in null stream filter 2022-10-17 21:24:04 -07:00
convert.h
copy.c
credential.c
credential.h
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c date: mark unused parameters in handler functions 2022-10-17 21:24:04 -07:00
date.h
decorate.c
decorate.h
delta-islands.c delta-islands: free island-related data after use 2022-11-18 18:30:49 -05:00
delta-islands.h
delta.h
detect-compiler
diagnose.c
diagnose.h
diff-delta.c
diff-lib.c
diff-merges.c
diff-merges.h
diff-no-index.c
diff.c Merge branch 'sg/plug-line-log-leaks' 2022-11-28 12:13:46 +09:00
diff.h patch-id: use stable patch-id for rebases 2022-10-24 15:44:19 -07:00
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c diffcore-pickaxe: mark unused parameters in pickaxe functions 2022-10-17 21:24:04 -07:00
diffcore-rename.c
diffcore-rotate.c
diffcore.h line-log: free diff queue when processing non-merge commits 2022-11-02 20:16:34 -04:00
dir-iterator.c dir-iterator: prevent top-level symlinks without FOLLOW_SYMLINKS 2023-01-24 16:52:16 -08:00
dir-iterator.h dir-iterator: prevent top-level symlinks without FOLLOW_SYMLINKS 2023-01-24 16:52:16 -08:00
dir.c Merge branch 'rs/use-fspathncmp' into maint-2.38 2022-10-27 15:24:13 -07:00
dir.h
editor.c
entry.c
entry.h
environment.c
environment.h
exec-cmd.c mark unused parameters in trivial compat functions 2022-10-17 21:24:03 -07:00
exec-cmd.h
fetch-negotiator.c
fetch-negotiator.h
fetch-pack.c
fetch-pack.h
fmt-merge-msg.c
fmt-merge-msg.h
fsck.c Merge branch 'maint-2.36' into maint-2.37 2022-12-13 21:20:35 +09:00
fsck.h Sync with 2.38.3 2022-12-13 21:25:15 +09:00
fsmonitor--daemon.h
fsmonitor-ipc.c replace and remove run_command_v_opt_tr2() 2022-10-30 14:04:48 -04:00
fsmonitor-ipc.h
fsmonitor-path-utils.h
fsmonitor-settings.c
fsmonitor-settings.h
fsmonitor.c
fsmonitor.h
generate-cmdlist.sh
generate-configlist.sh
generate-hooklist.sh
gettext.c
gettext.h
git-add--interactive.perl
git-archimport.perl
git-bisect.sh bisect--helper: parse subcommand with OPT_SUBCOMMAND 2022-11-11 17:04:57 -05:00
git-compat-util.h Sync with 2.38.3 2022-12-13 21:25:15 +09:00
git-curl-compat.h http: support CURLOPT_PROTOCOLS_STR 2023-02-06 09:27:09 +01:00
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-filter-branch.sh
git-instaweb.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-p4.py
git-quiltimport.sh
git-request-pull.sh
git-send-email.perl
git-sh-i18n.sh
git-sh-setup.sh
git-submodule.sh submodule--helper: drop "update --prefix <pfx>" for "-C <pfx> update" 2022-11-08 14:55:30 -05:00
git-svn.perl
git-web--browse.sh
git.c Merge branch 'ab/submodule-helper-prep-only' 2022-11-23 11:22:22 +09:00
git.rc
gpg-interface.c Merge branch 'pw/ssh-sign-report-errors' into maint-2.38 2022-10-25 17:11:35 -07:00
gpg-interface.h
graph.c
graph.h
grep.c Merge branch 'ab/grep-simplify-extended-expression' 2022-10-21 11:37:28 -07:00
grep.h Merge branch 'ab/grep-simplify-extended-expression' 2022-10-21 11:37:28 -07:00
hash-lookup.c
hash-lookup.h
hash.h
hashmap.c
hashmap.h
help.c Merge branch 'ab/doc-synopsis-and-cmd-usage' 2022-10-28 11:26:54 -07:00
help.h
hex.c
hook.c
hook.h
http-backend.c
http-fetch.c
http-push.c Sync with 2.36.5 2023-02-06 09:38:31 +01:00
http-walker.c
http.c Sync with 2.38.4 2023-02-06 09:43:39 +01:00
http.h Sync with 2.37.6 2023-02-06 09:43:28 +01:00
ident.c
imap-send.c
iterator.h
json-writer.c
json-writer.h
khash.h
kwset.c
kwset.h
levenshtein.c
levenshtein.h
line-log.c line-log: free the diff queues' arrays when processing merge commits 2022-11-02 20:16:34 -04:00
line-log.h
line-range.c
line-range.h
linear-assignment.c
linear-assignment.h
list-objects-filter-options.c
list-objects-filter-options.h
list-objects-filter.c list-objects-filter: plug combine_filter_data leak 2022-11-21 16:43:26 +09:00
list-objects-filter.h
list-objects.c
list-objects.h
list.h
ll-merge.c Merge branch 'rs/no-more-run-command-v' 2022-11-08 17:15:12 -05:00
ll-merge.h
lockfile.c
lockfile.h
log-tree.c
log-tree.h
ls-refs.c refs: get rid of global list of hidden refs 2022-11-17 16:22:51 -05:00
ls-refs.h
mailinfo.c
mailinfo.h
mailmap.c
mailmap.h
match-trees.c
mem-pool.c
mem-pool.h
merge-blobs.c
merge-blobs.h
merge-ort-wrappers.c
merge-ort-wrappers.h
merge-ort.c Merge branch 'en/ort-dir-rename-and-symlink-fix' 2022-10-30 21:04:43 -04:00
merge-ort.h
merge-recursive.c merge-recursive: fix variable typo in error message 2022-11-27 10:26:10 +09:00
merge-recursive.h
merge.c use child_process members "args" and "env" directly 2022-10-30 14:04:40 -04:00
mergesort.h
midx.c Merge branch 'tb/midx-bitmap-selection-fix' 2022-10-27 14:51:52 -07:00
midx.h
name-hash.c
notes-cache.c
notes-cache.h
notes-merge.c
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
object-file.c object-file: use real paths when adding alternates 2022-11-25 09:44:08 +09:00
object-name.c
object-store.h
object.c parse_object(): simplify blob conditional 2022-11-22 10:13:54 +09:00
object.h
oid-array.c
oid-array.h
oidmap.c
oidmap.h
oidset.c
oidset.h
oidtree.c
oidtree.h
pack-bitmap-write.c pack-bitmap-write.c: instrument number of reused bitmaps 2022-10-13 13:35:08 -07:00
pack-bitmap.c
pack-bitmap.h
pack-check.c
pack-mtimes.c
pack-mtimes.h
pack-objects.c
pack-objects.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
packfile.c
packfile.h
pager.c
parallel-checkout.c
parallel-checkout.h
parse-options-cb.c
parse-options.c
parse-options.h
patch-delta.c
patch-ids.c Merge branch 'jz/patch-id' 2022-10-30 21:04:41 -04:00
patch-ids.h patch-id: use stable patch-id for rebases 2022-10-24 15:44:19 -07:00
path.c adjust_shared_perm(): leave g+s alone when the group does not matter 2022-10-28 14:55:27 -07:00
path.h
pathspec.c
pathspec.h
pkt-line.c
pkt-line.h
preload-index.c
pretty.c Sync with Git 2.37.5 2022-12-13 21:23:36 +09:00
pretty.h
prio-queue.c
prio-queue.h
progress.c
progress.h
promisor-remote.c
promisor-remote.h
prompt.c
prompt.h
protocol-caps.c
protocol-caps.h
protocol.c
protocol.h
prune-packed.c
prune-packed.h
quote.c
quote.h
range-diff.c
range-diff.h
reachable.c
reachable.h
read-cache.c read-cache API & users: make discard_index() return void 2022-11-21 12:06:15 +09:00
rebase-interactive.c
rebase-interactive.h
rebase.c
rebase.h
ref-filter.c ref-filter: fix parsing of signatures with CRLF and no body 2022-11-02 21:36:04 -04:00
ref-filter.h
reflog-walk.c string-list: mark unused callback parameters 2022-10-17 21:24:04 -07:00
reflog-walk.h
reflog.c
reflog.h
refs.c shorten_unambiguous_ref(): avoid sscanf() 2023-02-15 08:53:17 -08:00
refs.h refs: get rid of global list of hidden refs 2022-11-17 16:22:51 -05:00
refspec.c
refspec.h
remote-curl.c Sync with 2.37.6 2023-02-06 09:43:28 +01:00
remote.c
remote.h
replace-object.c
replace-object.h
repo-settings.c Merge branch 'es/mark-gc-cruft-as-experimental' 2022-11-08 17:14:48 -05:00
repository.c {builtin/*,repository}.c: add & use "USE_THE_INDEX_VARIABLE" 2022-11-21 12:06:15 +09:00
repository.h Merge branch 'es/mark-gc-cruft-as-experimental' 2022-11-08 17:14:48 -05:00
rerere.c
rerere.h
reset.c rebase: use 'skip_cache_tree_update' option 2022-11-10 21:49:34 -05:00
reset.h
resolve-undo.c
resolve-undo.h
revision.c Merge branch 'ps/receive-use-only-advertised' 2022-11-23 11:22:25 +09:00
revision.h Merge branch 'ps/receive-use-only-advertised' 2022-11-23 11:22:25 +09:00
run-command.c Merge branch 'rs/no-more-run-command-v' 2022-11-08 17:15:12 -05:00
run-command.h Merge branch 'rs/no-more-run-command-v' 2022-11-08 17:15:12 -05:00
scalar.c Merge branch 'js/remove-stale-scalar-repos' 2022-11-23 11:22:23 +09:00
send-pack.c
send-pack.h
sequencer.c rebase --update-refs: avoid unintended ref deletion 2022-12-09 19:31:45 +09:00
sequencer.h sequencer: stop exporting GIT_REFLOG_ACTION 2022-11-09 18:15:43 -05:00
serve.c
serve.h
server-info.c
setup.c
sh-i18n--envsubst.c
sha1dc_git.c
sha1dc_git.h Makefile & test-tool: replace "DC_SHA1" variable with a "define" 2022-11-07 22:11:51 -05:00
shallow.c
shallow.h
shared.mak Merge branch 'ab/gnumake-4.4-fix' 2022-12-01 18:38:07 +09:00
shell.c replace and remove run_command_v_opt() 2022-10-30 14:04:51 -04:00
shortlog.h shortlog: extract `shortlog_finish_setup()` 2022-10-24 14:48:05 -07:00
sideband.c
sideband.h
sigchain.c
sigchain.h
simple-ipc.h
sparse-index.c index: raise a bug if the index is materialised more than once 2022-11-04 20:28:28 -04:00
sparse-index.h
split-index.c
split-index.h
stable-qsort.c
strbuf.c
strbuf.h
streaming.c
streaming.h
string-list.c string-list: mark unused callback parameters 2022-10-17 21:24:04 -07:00
string-list.h
strmap.c
strmap.h
strvec.c
strvec.h
sub-process.c
sub-process.h
submodule-config.c
submodule-config.h
submodule.c Merge branch 'jt/submodule-on-demand' 2022-11-23 11:22:25 +09:00
submodule.h submodule API & "absorbgitdirs": remove "----recursive" option 2022-11-08 14:55:30 -05:00
symlinks.c
tag.c
tag.h
tar.h
tempfile.c
tempfile.h
thread-utils.c
thread-utils.h
tmp-objdir.c
tmp-objdir.h replace and remove run_command_v_opt_cd_env() 2022-10-30 14:04:47 -04:00
trace.c
trace.h
trace2.c trace2: add global counter mechanism 2022-10-24 12:45:26 -07:00
trace2.h trace2: add global counter mechanism 2022-10-24 12:45:26 -07:00
trailer.c
trailer.h
transport-helper.c
transport-internal.h
transport.c Merge branch 'ds/bundle-uri-3' 2022-10-30 21:04:44 -04:00
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unicode-width.h
unimplemented.sh
unix-socket.c
unix-socket.h
unix-stream-server.c
unix-stream-server.h
unpack-trees.c unpack-trees: add 'skip_cache_tree_update' option 2022-11-10 21:49:34 -05:00
unpack-trees.h unpack-trees: add 'skip_cache_tree_update' option 2022-11-10 21:49:34 -05:00
upload-pack.c refs: get rid of global list of hidden refs 2022-11-17 16:22:51 -05:00
upload-pack.h
url.c
url.h
urlmatch.c
urlmatch.h
usage.c
userdiff.c
userdiff.h
utf8.c Sync with Git 2.31.6 2022-12-13 21:09:40 +09:00
utf8.h Sync with Git 2.31.6 2022-12-13 21:09:40 +09:00
varint.c
varint.h
version.c
version.h
versioncmp.c
walker.c
walker.h
wildmatch.c
wildmatch.h
worktree.c
worktree.h
wrap-for-bin.sh
wrapper.c
write-or-die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
zlib.c

README.md

Build status

Git - fast, scalable, distributed revision control system

Git is a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals.

Git is an Open Source project covered by the GNU General Public License version 2 (some parts of it are under different licenses, compatible with the GPLv2). It was originally written by Linus Torvalds with help of a group of hackers around the net.

Please read the file INSTALL for installation instructions.

Many Git online resources are accessible from https://git-scm.com/ including full documentation and Git related tools.

See Documentation/gittutorial.txt to get started, then see Documentation/giteveryday.txt for a useful minimum set of commands, and Documentation/git-<commandname>.txt for documentation of each command. If git has been correctly installed, then the tutorial can also be read with man gittutorial or git help tutorial, and the documentation of each command with man git-<commandname> or git help <commandname>.

CVS users may also want to read Documentation/gitcvs-migration.txt (man gitcvs-migration or git help cvs-migration if git is installed).

The user discussion and development of Git take place on the Git mailing list -- everyone is welcome to post bug reports, feature requests, comments and patches to git@vger.kernel.org (read Documentation/SubmittingPatches for instructions on patch submission and Documentation/CodingGuidelines).

Those wishing to help with error message, usage and informational message string translations (localization l10) should see po/README.md (a po file is a Portable Object file that holds the translations).

To subscribe to the list, send an email with just "subscribe git" in the body to majordomo@vger.kernel.org (not the Git list). The mailing list archives are available at https://lore.kernel.org/git/, http://marc.info/?l=git and other archival sites.

Issues which are security relevant should be disclosed privately to the Git Security mailing list git-security@googlegroups.com.

The maintainer frequently sends the "What's cooking" reports that list the current status of various development topics to the mailing list. The discussion following them give a good reference for project status, development direction and remaining tasks.

The name "git" was given by Linus Torvalds when he wrote the very first version. He described the tool as "the stupid content tracker" and the name as (depending on your mood):

  • random three-letter combination that is pronounceable, and not actually used by any common UNIX command. The fact that it is a mispronunciation of "get" may or may not be relevant.
  • stupid. contemptible and despicable. simple. Take your pick from the dictionary of slang.
  • "global information tracker": you're in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room.
  • "goddamn idiotic truckload of sh*t": when it breaks