Skip to content

Commit 65904b8

Browse files
nasamuffingitster
authored andcommitted
promisor-remote: skip move_to_tail when no-op
Previously, when promisor_remote_move_to_tail() is called for a promisor_remote which is currently the final element in promisors, a cycle is created in the promisors linked list. This cycle leads to a double free later on in promisor_remote_clear() when the final element of the promisors list is removed: promisors is set to promisors->next (a no-op, as promisors->next == promisors); the previous value of promisors is free()'d; then the new value of promisors (which is equal to the previous value of promisors) is also free()'d. This double-free error was unrecoverable for the user without removing the filter or re-cloning the repo and hoping to miss this edge case. Now, when promisor_remote_move_to_tail() would be a no-op, just do a no-op. In cases of promisor_remote_move_to_tail() where r is not already at the tail of the list, it works as before. Helped-by: Jeff King <[email protected]> Signed-off-by: Emily Shaffer <[email protected]> Acked-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8464f94 commit 65904b8

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

promisor-remote.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
8989
static void promisor_remote_move_to_tail(struct promisor_remote *r,
9090
struct promisor_remote *previous)
9191
{
92+
if (r->next == NULL)
93+
return;
94+
9295
if (previous)
9396
previous->next = r->next;
9497
else

t/t0410-partial-clone.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,19 @@ test_expect_success 'rev-list dies for missing objects on cmd line' '
429429
done
430430
'
431431

432+
test_expect_success 'single promisor remote can be re-initialized gracefully' '
433+
# ensure one promisor is in the promisors list
434+
rm -rf repo &&
435+
test_create_repo repo &&
436+
test_create_repo other &&
437+
git -C repo remote add foo "file://$(pwd)/other" &&
438+
git -C repo config remote.foo.promisor true &&
439+
git -C repo config extensions.partialclone foo &&
440+
441+
# reinitialize the promisors list
442+
git -C repo fetch --filter=blob:none foo
443+
'
444+
432445
test_expect_success 'gc repacks promisor objects separately from non-promisor objects' '
433446
rm -rf repo &&
434447
test_create_repo repo &&

0 commit comments

Comments
 (0)