summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-10-28 09:01:15 -0700
committerJunio C Hamano <gitster@pobox.com>2016-10-28 09:01:15 -0700
commit42a9c6c0e2060327def808d9c4c2aa167d6d8934 (patch)
treeaeaf7616738519ed6e8e930b0e57060713156836
parente2f1d2c3179cae92c9502d10c13e25624726caa2 (diff)
parente8c42cb9ce6a566aad797cc6c5bc1279d608d819 (diff)
downloadgit-42a9c6c0e2060327def808d9c4c2aa167d6d8934.tar.gz
Merge branch 'jk/ref-symlink-loop' into maint
A stray symbolic link in $GIT_DIR/refs/ directory could make name resolution loop forever, which has been corrected. * jk/ref-symlink-loop: files_read_raw_ref: prevent infinite retry loops in general files_read_raw_ref: avoid infinite loop on broken symlinks
-rw-r--r--refs/files-backend.c14
-rwxr-xr-xt/t1503-rev-parse-verify.sh5
2 files changed, 18 insertions, 1 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 12290d2496..2455564352 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1451,6 +1451,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
int fd;
int ret = -1;
int save_errno;
+ int remaining_retries = 3;
*type = 0;
strbuf_reset(&sb_path);
@@ -1466,8 +1467,14 @@ stat_ref:
* <-> symlink) between the lstat() and reading, then
* we don't want to report that as an error but rather
* try again starting with the lstat().
+ *
+ * We'll keep a count of the retries, though, just to avoid
+ * any confusing situation sending us into an infinite loop.
*/
+ if (remaining_retries-- <= 0)
+ goto out;
+
if (lstat(path, &st) < 0) {
if (errno != ENOENT)
goto out;
@@ -1496,6 +1503,11 @@ stat_ref:
ret = 0;
goto out;
}
+ /*
+ * It doesn't look like a refname; fall through to just
+ * treating it like a non-symlink, and reading whatever it
+ * points to.
+ */
}
/* Is it a directory? */
@@ -1519,7 +1531,7 @@ stat_ref:
*/
fd = open(path, O_RDONLY);
if (fd < 0) {
- if (errno == ENOENT)
+ if (errno == ENOENT && !S_ISLNK(st.st_mode))
/* inconsistent with lstat; retry */
goto stat_ref;
else
diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh
index ab27d0db5c..492edffa9c 100755
--- a/t/t1503-rev-parse-verify.sh
+++ b/t/t1503-rev-parse-verify.sh
@@ -139,4 +139,9 @@ test_expect_success 'master@{n} for various n' '
test_must_fail git rev-parse --verify master@{$Np1}
'
+test_expect_success SYMLINKS 'ref resolution not confused by broken symlinks' '
+ ln -s does-not-exist .git/refs/heads/broken &&
+ test_must_fail git rev-parse --verify broken
+'
+
test_done