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

[PATCH v5 08/12] bundle: properly clear all revision flags

From
Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
Date
Oct 12, 2022, 12:52 UTC
Message-ID
<8dc5a8e4e63dc98642176e5b78be739ef721d2d8.1665579160.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1333.v5.git.1665579160.gitgitgadget@gmail.com>
From: Derrick Stolee <derrickstolee@github.com>

The verify_bundle() method checks two things for a bundle's prerequisites:

 1. Are these objects in the object store?
 2. Are these objects reachable from our references?

In this second question, multiple uses of verify_bundle() in the same process can report an invalid bundle even though it is correct. The reason is due to not clearing all of the commit marks on the commits previously walked.

The revision walk machinery was first introduced in-process by fb9a54150d3 (git-bundle: avoid fork() in verify_bundle(), 2007-02-22). This implementation used "-1" as the set of flags to clear. The next meaningful change came in 2b064697a5b (revision traversal: retire BOUNDARY_SHOW, 2007-03-05), which introduced the PREREQ_MARK flag instead of a flag normally controlled by the revision-walk machinery.

In 86a0a408b90 (commit: factor out clear_commit_marks_for_object_array, 2011-10-01), the loop over the array of commits was replaced with a new clear_commit_marks_for_object_array(), but simultaneously the "-1" value was replaced with "ALL_REV_FLAGS", which stopped un-setting the PREREQ_MARK flag. This means that if multiple commits were marked by the PREREQ_MARK in a previous run of verify_bundle(), then this loop could terminate early due to 'i' going to zero:

	while (i && (commit = get_revision(&revs)))
		if (commit->object.flags & PREREQ_MARK)
			i--;

The flag clearing work was changed again in 63647391e6c (bundle: avoid using the rev_info flag leak_pending, 2017-12-25), but that was only cosmetic and did not change the behavior.

It may seem that it would be sufficient to add the PREREQ_MARK flag to the clear_commit_marks() call in its current location. However, we actually need to do it in the "cleanup:" step, since the first loop checking "Are these objects in the object store?" might add the PREREQ_MARK flag to some objects and then terminate without performing a walk due to one missing object. By clearing the flags in all cases, we avoid this issue when running verify_bundle() multiple times in the same process.

Moving this loop to the cleanup step alone would cause a segfault when running 'git bundle verify' outside of a repository, but this is because of that error condition using "goto cleanup" when returning is perfectly safe. Nothing has been initialized at that point, so we can return immediately without causing any leaks.

This behavior is verified carefully by a test that will be added soon when Git learns to download bundle lists in a 'git clone --bundle-uri' command.

Signed-off-by: Derrick Stolee <derrickstolee@github.com>
---
 bundle.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/bundle.c b/bundle.c
index 0208e6d90d3..c277f3b9360 100644
--- a/bundle.c
+++ b/bundle.c
@@ -202,10 +202,8 @@ int verify_bundle(struct repository *r,
 	int i, ret = 0, req_nr;
 	const char *message = _("Repository lacks these prerequisite commits:");
 
-	if (!r || !r->objects || !r->objects->odb) {
-		ret = error(_("need a repository to verify a bundle"));
-		goto cleanup;
-	}
+	if (!r || !r->objects || !r->objects->odb)
+		return error(_("need a repository to verify a bundle"));
 
 	repo_init_revisions(r, &revs, NULL);
 	for (i = 0; i < p->nr; i++) {
@@ -250,15 +248,6 @@ int verify_bundle(struct repository *r,
 		error("%s %s", oid_to_hex(oid), name);
 	}
 
-	/* Clean up objects used, as they will be reused. */
-	for (i = 0; i < p->nr; i++) {
-		struct string_list_item *e = p->items + i;
-		struct object_id *oid = e->util;
-		commit = lookup_commit_reference_gently(r, oid, 1);
-		if (commit)
-			clear_commit_marks(commit, ALL_REV_FLAGS);
-	}
-
 	if (verbose) {
 		struct string_list *r;
 
@@ -287,6 +276,14 @@ int verify_bundle(struct repository *r,
 				  list_objects_filter_spec(&header->filter));
 	}
 cleanup:
+	/* Clean up objects used, as they will be reused. */
+	for (i = 0; i < p->nr; i++) {
+		struct string_list_item *e = p->items + i;
+		struct object_id *oid = e->util;
+		commit = lookup_commit_reference_gently(r, oid, 1);
+		if (commit)
+			clear_commit_marks(commit, ALL_REV_FLAGS | PREREQ_MARK);
+	}
 	release_revisions(&revs);
 	return ret;
 }
-- 
gitgitgadget
Previous: Derrick Stolee via GitGitGadgetNext: Junio C Hamano
Message 85 of 94 in “Bundle URIs III: Parse and download from bundle lists”
  1. 0/7 Bundle URIs III: Parse and download from bundle listsDerrick Stolee via GitGitGadget, Aug 22, 2022
  2. 1/7 bundle-uri: create bundle_list struct and helpersDerrick Stolee via GitGitGadget, Aug 22, 2022
  3. Junio C HamanoAug 22, 2022
  4. 3/7 bundle-uri: create "key=value" line parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Aug 22, 2022
  5. Junio C HamanoAug 22, 2022
  6. Derrick StoleeAug 23, 2022
  7. Josh SteadmonSep 2, 2022
  8. 6/7 bundle-uri: limit recursion depth for bundle listsDerrick Stolee via GitGitGadget, Aug 22, 2022
  9. 4/7 bundle-uri: unit test "key=value" parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Aug 22, 2022
  10. 4/7 bundle-uri: unit test "key=value" parsingTeng Long, Sep 1, 2022
  11. 5/7 bundle-uri: parse bundle list in config formatDerrick Stolee via GitGitGadget, Aug 22, 2022
  12. Junio C HamanoAug 22, 2022
  13. Derrick StoleeAug 23, 2022
  14. Jonathan TanAug 31, 2022
  15. 5/7 bundle-uri: parse bundle list in config formatTeng Long, Sep 1, 2022
  16. 2/7 bundle-uri: create base key-value pair parsingDerrick Stolee via GitGitGadget, Aug 22, 2022
  17. Junio C HamanoAug 22, 2022
  18. Derrick StoleeAug 23, 2022
  19. Jonathan TanAug 31, 2022
  20. Glen ChooAug 31, 2022
  21. 4/7 bundle-uri: unit test "key=value" parsingTeng Long, Sep 1, 2022
  22. 7/7 bundle-uri: fetch a list of bundlesDerrick Stolee via GitGitGadget, Aug 22, 2022
  23. Josh SteadmonSep 2, 2022
  24. 7/7 bundle-uri: fetch a list of bundlesTeng Long, Sep 5, 2022
  25. Derrick StoleeSep 8, 2022
  26. 0/9 Bundle URIs III: Parse and download from bundle listsDerrick Stolee via GitGitGadget, Sep 9, 2022
  27. 1/9 bundle-uri: short-circuit capability parsingDerrick Stolee via GitGitGadget, Sep 9, 2022
  28. Junio C HamanoSep 9, 2022
  29. Derrick StoleeSep 19, 2022
  30. 2/9 bundle-uri: use plain string in find_temp_filename()Derrick Stolee via GitGitGadget, Sep 9, 2022
  31. Junio C HamanoSep 9, 2022
  32. Derrick StoleeSep 19, 2022
  33. Junio C HamanoSep 19, 2022
  34. 4/9 bundle-uri: create base key-value pair parsingDerrick Stolee via GitGitGadget, Sep 9, 2022
  35. Jonathan TanSep 29, 2022
  36. 3/9 bundle-uri: create bundle_list struct and helpersDerrick Stolee via GitGitGadget, Sep 9, 2022
  37. 5/9 bundle-uri: create "key=value" line parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Sep 9, 2022
  38. 6/9 bundle-uri: unit test "key=value" parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Sep 9, 2022
  39. 7/9 bundle-uri: parse bundle list in config formatDerrick Stolee via GitGitGadget, Sep 9, 2022
  40. 8/9 bundle-uri: limit recursion depth for bundle listsDerrick Stolee via GitGitGadget, Sep 9, 2022
  41. 9/9 bundle-uri: fetch a list of bundlesDerrick Stolee via GitGitGadget, Sep 9, 2022
  42. Jonathan TanSep 29, 2022
  43. Derrick StoleeSep 30, 2022
  44. Derrick StoleeSep 26, 2022
  45. Junio C HamanoSep 26, 2022
  46. Jonathan TanSep 29, 2022
  47. Derrick StoleeSep 30, 2022
  48. 0/9 Bundle URIs III: Parse and download from bundle listsDerrick Stolee via GitGitGadget, Oct 4, 2022
  49. 1/9 bundle-uri: use plain string in find_temp_filename()Derrick Stolee via GitGitGadget, Oct 4, 2022
  50. 2/9 bundle-uri: create bundle_list struct and helpersDerrick Stolee via GitGitGadget, Oct 4, 2022
  51. 4/9 bundle-uri: create "key=value" line parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Oct 4, 2022
  52. 3/9 bundle-uri: create base key-value pair parsingDerrick Stolee via GitGitGadget, Oct 4, 2022
  53. 5/9 bundle-uri: unit test "key=value" parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Oct 4, 2022
  54. 6/9 bundle-uri: parse bundle list in config formatDerrick Stolee via GitGitGadget, Oct 4, 2022
  55. 9/9 bundle-uri: suppress stderr from remote-httpsDerrick Stolee via GitGitGadget, Oct 4, 2022
  56. 7/9 bundle-uri: limit recursion depth for bundle listsDerrick Stolee via GitGitGadget, Oct 4, 2022
  57. 8/9 bundle-uri: fetch a list of bundlesDerrick Stolee via GitGitGadget, Oct 4, 2022
  58. Jonathan TanOct 4, 2022
  59. Derrick StoleeOct 7, 2022
  60. 00/11 Bundle URIs III: Parse and download from bundle listsDerrick Stolee via GitGitGadget, Oct 10, 2022
  61. 02/11 bundle-uri: create bundle_list struct and helpersDerrick Stolee via GitGitGadget, Oct 10, 2022
  62. 01/11 bundle-uri: use plain string in find_temp_filename()Derrick Stolee via GitGitGadget, Oct 10, 2022
  63. 03/11 bundle-uri: create base key-value pair parsingDerrick Stolee via GitGitGadget, Oct 10, 2022
  64. 04/11 bundle-uri: create "key=value" line parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Oct 10, 2022
  65. 05/11 bundle-uri: unit test "key=value" parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Oct 10, 2022
  66. 06/11 bundle-uri: parse bundle list in config formatDerrick Stolee via GitGitGadget, Oct 10, 2022
  67. 07/11 bundle-uri: limit recursion depth for bundle listsDerrick Stolee via GitGitGadget, Oct 10, 2022
  68. 08/11 bundle: add flags to verify_bundle(), skip walkDerrick Stolee via GitGitGadget, Oct 10, 2022
  69. Junio C HamanoOct 10, 2022
  70. Derrick StoleeOct 10, 2022
  71. Junio C HamanoOct 10, 2022
  72. Derrick StoleeOct 11, 2022
  73. 09/11 bundle-uri: fetch a list of bundlesDerrick Stolee via GitGitGadget, Oct 10, 2022
  74. 10/11 bundle-uri: quiet failed unbundlingsDerrick Stolee via GitGitGadget, Oct 10, 2022
  75. 11/11 bundle-uri: suppress stderr from remote-httpsDerrick Stolee via GitGitGadget, Oct 10, 2022
  76. 00/12 Bundle URIs III: Parse and download from bundle listsDerrick Stolee via GitGitGadget, Oct 12, 2022
  77. 01/12 bundle-uri: use plain string in find_temp_filename()Derrick Stolee via GitGitGadget, Oct 12, 2022
  78. 02/12 bundle-uri: create bundle_list struct and helpersDerrick Stolee via GitGitGadget, Oct 12, 2022
  79. 03/12 bundle-uri: create base key-value pair parsingDerrick Stolee via GitGitGadget, Oct 12, 2022
  80. 05/12 bundle-uri: unit test "key=value" parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Oct 12, 2022
  81. 04/12 bundle-uri: create "key=value" line parsingÆvar Arnfjörð Bjarmason via GitGitGadget, Oct 12, 2022
  82. 06/12 bundle-uri: parse bundle list in config formatDerrick Stolee via GitGitGadget, Oct 12, 2022
  83. 07/12 bundle-uri: limit recursion depth for bundle listsDerrick Stolee via GitGitGadget, Oct 12, 2022
  84. 10/12 bundle: add flags to verify_bundle()Derrick Stolee via GitGitGadget, Oct 12, 2022
  85. 08/12 bundle: properly clear all revision flagsDerrick Stolee via GitGitGadget, Oct 12, 2022
  86. Junio C HamanoOct 12, 2022
  87. 09/12 bundle-uri: fetch a list of bundlesDerrick Stolee via GitGitGadget, Oct 12, 2022
  88. Junio C HamanoOct 26, 2022
  89. 12/12 bundle-uri: suppress stderr from remote-httpsDerrick Stolee via GitGitGadget, Oct 12, 2022
  90. Junio C HamanoOct 26, 2022
  91. 11/12 bundle-uri: quiet failed unbundlingsDerrick Stolee via GitGitGadget, Oct 12, 2022
  92. Junio C HamanoOct 12, 2022
  93. Derrick StoleeOct 26, 2022
  94. Junio C HamanoOct 26, 2022

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.