summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2020-06-30 10:13:26 +0200
committerPatrick Steinhardt <ps@pks.im>2020-07-12 16:01:21 +0200
commit349874474896d69979338961ee5813c146f561fb (patch)
treebbc47294d6f8a231c5a55140455dbb29f116e6ab
parentb895547ca135158bf1582b50f6c09f8f78066e87 (diff)
downloadlibgit2-pks/refdb-refactorings.tar.gz
refdb: avoid unlimited spinning in case of symref cyclespks/refdb-refactorings
To determine whether another reflog entry needs to be written for HEAD on a reference update, we need to see whether HEAD directly or indirectly points to the reference we're updating. The resolve logic is currently completely unbounded except an error occurs, which effectively means that we'd be spinning forever in case we have a symref loop in the repository refdb. Let's fix the issue by using `git_refdb_resolve` instead, which is always bounded.
-rw-r--r--src/refdb.c19
1 files changed, 6 insertions, 13 deletions
diff --git a/src/refdb.c b/src/refdb.c
index 6879b6aab..fb86d5ccb 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -326,7 +326,7 @@ int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *
int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_reference *ref)
{
- git_reference *head = NULL, *peeled = NULL;
+ git_reference *head = NULL, *resolved = NULL;
const char *name;
int error;
@@ -344,22 +344,15 @@ int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_refere
goto out;
/* Go down the symref chain until we find the branch */
- while (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC) {
- if ((error = git_refdb_lookup(&peeled, db, git_reference_symbolic_target(head))) < 0)
- break;
-
- git_reference_free(head);
- head = peeled;
- peeled = NULL;
- }
-
- if (error < 0) {
+ if ((error = git_refdb_resolve(&resolved, db, git_reference_symbolic_target(head), -1)) < 0) {
if (error != GIT_ENOTFOUND)
goto out;
error = 0;
name = git_reference_symbolic_target(head);
+ } else if (git_reference_type(resolved) == GIT_REFERENCE_SYMBOLIC) {
+ name = git_reference_symbolic_target(resolved);
} else {
- name = git_reference_name(head);
+ name = git_reference_name(resolved);
}
if (strcmp(name, ref->name))
@@ -368,7 +361,7 @@ int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_refere
*out = 1;
out:
- git_reference_free(peeled);
+ git_reference_free(resolved);
git_reference_free(head);
return error;
}