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

[PATCH v3 1/3] refs/files-backend: add longer-scoped copy of string to list

From
MÅMartin Ågren <martin.agren@gmail.com>
Date
Aug 29, 2017, 17:18 UTC
Message-ID
<4b4c0d178ad2216eecbc49fb6f54dd8a1d1ac119.1504024261.git.martin.agren@gmail.com>
In-Reply-To
<CAN0heSqn59sFF3A-eQ593G+ZDWnO9pKM5F=sgiSQk+prUr-nSQ@mail.gmail.com>

split_symref_update() receives a string-pointer `referent` and adds it to the list of `affected_refnames`. The list simply holds on to the pointers it is given, it does not copy the strings and it does not ever free them. The `referent` string in split_symref_update() belongs to a string buffer in the caller. After we return, the string will be leaked.

In the next patch, we want to properly release the string buffer in the caller, but we can't safely do so until we've made sure that `affected_refnames` will not be holding on to a pointer to the string. We could configure the list to handle its own resources, but it would mean some alloc/free-churning. The list is already handling other strings (through other code paths) which we do not need to worry about, and we'd be memory-churning those strings too, completely unnecessary.

Observe that split_symref_update() creates a `new_update`-object through ref_transaction_add_update(), after which `new_update->refname` is a copy of `referent`. The difference is, this copy will be freed, and it will be freed *after* `affected_refnames` has been cleared.

Rearrange the handling of `referent`, so that we don't add it directly to `affected_refnames`. Instead, first just check whether `referent` exists in the string list, and later add `new_update->refname`.

Helped-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Martin Ågren <martin.agren@gmail.com>
---
v3: "O(lg N)" in comment; if-BUG() instead of assert()
 refs/files-backend.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index fccbc24ac..73615d869 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2144,13 +2144,12 @@ static int split_symref_update(struct files_ref_store *refs,
 
 	/*
 	 * First make sure that referent is not already in the
-	 * transaction. This insertion is O(N) in the transaction
+	 * transaction. This check is O(lg N) in the transaction
 	 * size, but it happens at most once per symref in a
 	 * transaction.
 	 */
-	item = string_list_insert(affected_refnames, referent);
-	if (item->util) {
-		/* An entry already existed */
+	if (string_list_has_string(affected_refnames, referent)) {
+		/* An entry already exists */
 		strbuf_addf(err,
 			    "multiple updates for '%s' (including one "
 			    "via symref '%s') are not allowed",
@@ -2185,6 +2184,17 @@ static int split_symref_update(struct files_ref_store *refs,
 	update->flags |= REF_LOG_ONLY | REF_NODEREF;
 	update->flags &= ~REF_HAVE_OLD;
 
+	/*
+	 * Add the referent. This insertion is O(N) in the transaction
+	 * size, but it happens at most once per symref in a
+	 * transaction. Make sure to add new_update->refname, which will
+	 * be valid as long as affected_refnames is in use, and NOT
+	 * referent, which might soon be freed by our caller.
+	 */
+	item = string_list_insert(affected_refnames, new_update->refname);
+	if (item->util)
+		BUG("%s unexpectedly found in affected_refnames",
+		    new_update->refname);
 	item->util = new_update;
 
 	return 0;
-- 
2.14.1.151.g45c1275a3.dirty
Previous: Martin ÅgrenNext: Michael Haggerty
Message 12 of 34 in “refs/files-backend: duplicate strings added to affected_refnames”
  1. 1/2 refs/files-backend: duplicate strings added to affected_refnamesMartin Ågren, Aug 25, 2017
  2. 2/2 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Aug 25, 2017
  3. Junio C HamanoAug 25, 2017
  4. Martin ÅgrenAug 26, 2017
  5. Michael HaggertyAug 28, 2017
  6. Martin ÅgrenAug 28, 2017
  7. 1/2 refs/files-backend: add longer-scoped copy of string to listMartin Ågren, Aug 28, 2017
  8. Michael HaggertyAug 29, 2017
  9. 2/2 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Aug 28, 2017
  10. Michael HaggertyAug 29, 2017
  11. Martin ÅgrenAug 29, 2017
  12. 1/3 refs/files-backend: add longer-scoped copy of string to listMartin Ågren, Aug 29, 2017
  13. Michael HaggertyAug 30, 2017
  14. Martin ÅgrenAug 30, 2017
  15. Junio C HamanoSep 5, 2017
  16. Martin ÅgrenSep 5, 2017
  17. Jeff KingSep 5, 2017
  18. Junio C HamanoSep 5, 2017
  19. Martin ÅgrenSep 6, 2017
  20. Junio C HamanoSep 6, 2017
  21. Jeff KingSep 6, 2017
  22. 0/4 Rerolling ma/split-symref-update-fixMartin Ågren, Sep 9, 2017
  23. 1/4 refs/files-backend: add longer-scoped copy of string to listMartin Ågren, Sep 9, 2017
  24. 2/4 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Sep 9, 2017
  25. 3/4 refs/files-backend: correct return value in lock_ref_for_updateMartin Ågren, Sep 9, 2017
  26. 4/4 refs/files-backend: add `refname`, not "HEAD", to listMartin Ågren, Sep 9, 2017
  27. Jeff KingSep 9, 2017
  28. Jeff KingSep 5, 2017
  29. Michael HaggertySep 5, 2017
  30. Jeff KingSep 5, 2017
  31. 2/3 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Aug 29, 2017
  32. Jeff KingSep 5, 2017
  33. Martin ÅgrenSep 5, 2017
  34. 3/3 refs/files-backend: correct return value in lock_ref_for_updateMartin Ågren, Aug 29, 2017

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.