Blame SOURCES/0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch

3de368
From 5bc590cd3ce202243cd1c3ee22104bcb4f3b6c4e Mon Sep 17 00:00:00 2001
3de368
From: Michael Haggerty <mhagger@alum.mit.edu>
3de368
Date: Wed, 25 Mar 2015 22:33:11 +0100
3de368
Subject: [PATCH 2/2] resolve_ref_unsafe(): limit the number of "stat_ref"
3de368
 retries
3de368
3de368
If there is a broken symlink where a loose reference file is expected,
3de368
then the attempt to open() it fails with ENOENT. This error is
3de368
misinterpreted to mean that the loose reference file itself has
3de368
disappeared due to a race, causing the lookup to be retried. But in
3de368
this scenario, the retries all suffer from the same problem, causing
3de368
an infinite loop.
3de368
3de368
So put a limit (of 5) on the number of times that the stat_ref step
3de368
can be retried.
3de368
3de368
Based-on-patch-by: Petr Stodulka <pstodulk@redhat.com>
3de368
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
3de368
---
3de368
 refs/files-backend.c | 6 ++++--
3de368
 refs/refs-internal.h | 6 ++++++
3de368
 2 files changed, 10 insertions(+), 2 deletions(-)
3de368
3de368
diff --git a/refs/files-backend.c b/refs/files-backend.c
3de368
index d16feb1..245a0b5 100644
3de368
--- a/refs/files-backend.c
3de368
+++ b/refs/files-backend.c
3de368
@@ -1353,6 +1353,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
3de368
 	int fd;
3de368
 	int ret = -1;
3de368
 	int save_errno;
3de368
+	int retries = 0;
3de368
 
3de368
 	strbuf_reset(&sb_path);
3de368
 	strbuf_git_path(&sb_path, "%s", refname);
3de368
@@ -1390,7 +1391,8 @@ static int files_read_raw_ref(struct ref_store *ref_store,
3de368
 	if (S_ISLNK(st.st_mode)) {
3de368
 		strbuf_reset(&sb_contents);
3de368
 		if (strbuf_readlink(&sb_contents, path, 0) < 0) {
3de368
-			if (errno == ENOENT || errno == EINVAL)
3de368
+			if ((errno == ENOENT || errno == EINVAL) &&
3de368
+				retries++ < MAXRETRIES) 
3de368
 				/* inconsistent with lstat; retry */
3de368
 				goto stat_ref;
3de368
 			else
3de368
@@ -1426,7 +1428,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
3de368
 	 */
3de368
 	fd = open(path, O_RDONLY);
3de368
 	if (fd < 0) {
3de368
-		if (errno == ENOENT)
3de368
+		if (errno == ENOENT && retries++ < MAXRETRIES)
3de368
 			/* inconsistent with lstat; retry */
3de368
 			goto stat_ref;
3de368
 		else
3de368
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
3de368
index 708b260..37e6b99 100644
3de368
--- a/refs/refs-internal.h
3de368
+++ b/refs/refs-internal.h
3de368
@@ -255,6 +255,12 @@ int rename_ref_available(const char *old_refname, const char *new_refname);
3de368
 /* We allow "recursive" symbolic refs. Only within reason, though */
3de368
 #define SYMREF_MAXDEPTH 5
3de368
 
3de368
+/* 
3de368
+ * We allow only MAXRETRIES tries to jump on stat_ref, because of possible
3de368
+ * infinite loop
3de368
+ */
3de368
+#define MAXRETRIES 5
3de368
+
3de368
 /* Include broken references in a do_for_each_ref*() iteration: */
3de368
 #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
3de368
 
3de368
-- 
3de368
2.5.5
3de368