git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2] promisor-remote: skip move_to_tail when no-op

From
Emily Shaffer <emilyshaffer@google.com>
Date
Sep 26, 2019, 21:31 UTC
Message-ID
<20190926213156.88185-1-emilyshaffer@google.com>
In-Reply-To
<20190925213718.231231-1-emilyshaffer@google.com>

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.

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Helped-by: Jeff King <peff@peff.net>
---
Thanks Peff for pointing out this bug occurs any time the tail is being
moved to tail in the promisors list. Modified patch to check just for
"already at tail" condition.

Added a test case based on Peff's reproduction steps (thanks!) and confirmed it failed before the patch, exiting gracelessly with a SIGABRT, and now fails gracefully (and passes test_must_fail condition).

 - Emily
 promisor-remote.c        |  3 +++
 t/t0410-partial-clone.sh | 12 ++++++++++++
 2 files changed, 15 insertions(+)
diff --git a/promisor-remote.c b/promisor-remote.c
index 9bc296cdde..9bd5b79d59 100644
--- a/promisor-remote.c
+++ b/promisor-remote.c
@@ -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
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index d4b7e535ea..4db4d488c8 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -429,6 +429,18 @@ 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 &&
+	git -C repo remote add foo /wherever &&
+	git -C repo config remote.foo.promisor true &&
+	git -C repo config extensions.partialclone foo &&
+
+	# reinitialize the promisors list; this must fail gracefully
+	test_must_fail git -C repo fetch --filter=blob:none foo 2>fetch_err
+'
+
 test_expect_success 'gc repacks promisor objects separately from non-promisor objects' '
 	rm -rf repo &&
 	test_create_repo repo &&
-- 
2.23.0.444.g18eeb5a265-goog
Previous: Jeff KingNext: Jeff King
Message 5 of 10 in “promisor-remote: skip move_to_tail when n=1”
  1. promisor-remote: skip move_to_tail when n=1Emily Shaffer, Sep 25, 2019
  2. Jeff KingSep 26, 2019
  3. Emily ShafferSep 26, 2019
  4. Jeff KingSep 26, 2019
  5. promisor-remote: skip move_to_tail when no-opEmily Shaffer, Sep 26, 2019
  6. Jeff KingSep 27, 2019
  7. promisor-remote: skip move_to_tail when no-opEmily Shaffer, Sep 30, 2019
  8. Jeff KingSep 30, 2019
  9. promisor-remote: skip move_to_tail when no-opEmily Shaffer, Sep 30, 2019
  10. Christian CouderOct 1, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.