Commit Diff


commit - 2ac2a2665daf27c69c6cc6ad637ade3c7f03d6fe
commit + 29e86f7a5a094e0e5e9ca231e615a13c0c2e6ed0
blob - 5f009d7c9cfb1874b2d260ba7df35257cb60d768
blob + eb58d3c6002c347a9d8d66ea1c9aedd658be84db
--- lib/reference.c
+++ lib/reference.c
@@ -63,6 +63,8 @@ struct got_symref {
 	char *name;
 	char *ref;
 };
+
+#define GOT_REF_RECURSE_MAX	20
 
 /* A non-symbolic reference (there is no better designation). */
 struct got_ref {
@@ -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;
@@ -566,6 +572,13 @@ got_ref_resolve(struct got_object_id **id, struct got_
 		return got_error_from_errno("calloc");
 	memcpy((*id)->sha1, ref->ref.ref.sha1, sizeof((*id)->sha1));
 	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 *