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
This commit is contained in:
commit
42a9c6c0e2
@ -1451,6 +1451,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
|
|||||||
int fd;
|
int fd;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int save_errno;
|
int save_errno;
|
||||||
|
int remaining_retries = 3;
|
||||||
|
|
||||||
*type = 0;
|
*type = 0;
|
||||||
strbuf_reset(&sb_path);
|
strbuf_reset(&sb_path);
|
||||||
@ -1466,8 +1467,14 @@ stat_ref:
|
|||||||
* <-> symlink) between the lstat() and reading, then
|
* <-> symlink) between the lstat() and reading, then
|
||||||
* we don't want to report that as an error but rather
|
* we don't want to report that as an error but rather
|
||||||
* try again starting with the lstat().
|
* 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 (lstat(path, &st) < 0) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1496,6 +1503,11 @@ stat_ref:
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
goto out;
|
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? */
|
/* Is it a directory? */
|
||||||
@ -1519,7 +1531,7 @@ stat_ref:
|
|||||||
*/
|
*/
|
||||||
fd = open(path, O_RDONLY);
|
fd = open(path, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT && !S_ISLNK(st.st_mode))
|
||||||
/* inconsistent with lstat; retry */
|
/* inconsistent with lstat; retry */
|
||||||
goto stat_ref;
|
goto stat_ref;
|
||||||
else
|
else
|
||||||
|
@ -139,4 +139,9 @@ test_expect_success 'master@{n} for various n' '
|
|||||||
test_must_fail git rev-parse --verify master@{$Np1}
|
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
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user