THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Browse Source

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 <peff@peff.net>
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Acked-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
tags/v2.24.0-rc0
Emily Shaffer Junio C Hamano 1 month ago
parent
commit
65904b8b2b
2 changed files with 16 additions and 0 deletions
  1. +3
    -0
      promisor-remote.c
  2. +13
    -0
      t/t0410-partial-clone.sh

+ 3
- 0
promisor-remote.c View File

@@ -89,6 +89,9 @@ static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
static void promisor_remote_move_to_tail(struct promisor_remote *r,
struct promisor_remote *previous)
{
if (r->next == NULL)
return;

if (previous)
previous->next = r->next;
else


+ 13
- 0
t/t0410-partial-clone.sh View File

@@ -429,6 +429,19 @@ test_expect_success 'rev-list dies for missing objects on cmd line' '
done
'

test_expect_success 'single promisor remote can be re-initialized gracefully' '
# ensure one promisor is in the promisors list
rm -rf repo &&
test_create_repo repo &&
test_create_repo other &&
git -C repo remote add foo "file://$(pwd)/other" &&
git -C repo config remote.foo.promisor true &&
git -C repo config extensions.partialclone foo &&

# reinitialize the promisors list
git -C repo fetch --filter=blob:none foo
'

test_expect_success 'gc repacks promisor objects separately from non-promisor objects' '
rm -rf repo &&
test_create_repo repo &&


Loading…
Cancel
Save