Skip to content

Commit 3498744

Browse files
committed
refdb: avoid unlimited spinning in case of symref cycles
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.
1 parent b895547 commit 3498744

File tree

1 file changed

+6
-13
lines changed

1 file changed

+6
-13
lines changed

src/refdb.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *
326326

327327
int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_reference *ref)
328328
{
329-
git_reference *head = NULL, *peeled = NULL;
329+
git_reference *head = NULL, *resolved = NULL;
330330
const char *name;
331331
int error;
332332

@@ -344,22 +344,15 @@ int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_refere
344344
goto out;
345345

346346
/* Go down the symref chain until we find the branch */
347-
while (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC) {
348-
if ((error = git_refdb_lookup(&peeled, db, git_reference_symbolic_target(head))) < 0)
349-
break;
350-
351-
git_reference_free(head);
352-
head = peeled;
353-
peeled = NULL;
354-
}
355-
356-
if (error < 0) {
347+
if ((error = git_refdb_resolve(&resolved, db, git_reference_symbolic_target(head), -1)) < 0) {
357348
if (error != GIT_ENOTFOUND)
358349
goto out;
359350
error = 0;
360351
name = git_reference_symbolic_target(head);
352+
} else if (git_reference_type(resolved) == GIT_REFERENCE_SYMBOLIC) {
353+
name = git_reference_symbolic_target(resolved);
361354
} else {
362-
name = git_reference_name(head);
355+
name = git_reference_name(resolved);
363356
}
364357

365358
if (strcmp(name, ref->name))
@@ -368,7 +361,7 @@ int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_refere
368361
*out = 1;
369362

370363
out:
371-
git_reference_free(peeled);
364+
git_reference_free(resolved);
372365
git_reference_free(head);
373366
return error;
374367
}

0 commit comments

Comments
 (0)