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

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

From
Emily Shaffer <emilyshaffer@google.com>
Date
Sep 30, 2019, 22:03 UTC
Message-ID
<20190930220355.108394-1-emilyshaffer@google.com>
In-Reply-To
<20190930202818.2172-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.

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
---
Since v3 missed a small comment change.
 promisor-remote.c        |  3 +++
 t/t0410-partial-clone.sh | 13 +++++++++++++
 2 files changed, 16 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..5c676c71a5 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -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 &&
-- 
2.23.0.444.g18eeb5a265-goog
Previous: Jeff KingNext: Christian Couder
Message 9 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.