Commit 29e86f7a5a094e0e5e9ca231e615a13c0c2e6ed0

Stefan Sperling 2019-08-13T00:32:42

introuce a hard limit on recursion through symbolic references

diff --git a/lib/reference.c b/lib/reference.c
index 5f009d7..eb58d3c 100644
--- a/lib/reference.c
+++ b/lib/reference.c
@@ -64,6 +64,8 @@ struct got_symref {
 	char *ref;
 };
 
+#define GOT_REF_RECURSE_MAX	20
+
 /* A non-symbolic reference (there is no better designation). */
 struct got_ref {
 	char *name;
@@ -545,17 +547,21 @@ resolve_symbolic_ref(struct got_reference **resolved,
 	return err;
 }
 
-const struct got_error *
-got_ref_resolve(struct got_object_id **id, struct got_repository *repo,
-    struct got_reference *ref)
+static const struct got_error *
+ref_resolve(struct got_object_id **id, struct got_repository *repo,
+    struct got_reference *ref, int recursion)
 {
 	const struct got_error *err;
 
+	if (recursion <= 0)
+		return got_error_msg(GOT_ERR_RECURSION,
+		    "reference recursion limit reached");
+
 	if (ref->flags & GOT_REF_IS_SYMBOLIC) {
 		struct got_reference *resolved = NULL;
 		err = resolve_symbolic_ref(&resolved, repo, ref);
 		if (err == NULL)
-			err = got_ref_resolve(id, repo, resolved);
+			err = ref_resolve(id, repo, resolved, --recursion);
 		if (resolved)
 			got_ref_close(resolved);
 		return err;
@@ -568,6 +574,13 @@ got_ref_resolve(struct got_object_id **id, struct got_repository *repo,
 	return NULL;
 }
 
+const struct got_error *
+got_ref_resolve(struct got_object_id **id, struct got_repository *repo,
+    struct got_reference *ref)
+{
+	return ref_resolve(id, repo, ref, GOT_REF_RECURSE_MAX);
+}
+
 char *
 got_ref_to_str(struct got_reference *ref)
 {