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

[PATCH] object_as_type: initialize commit-graph-related fields of 'struct commit'

From
SZEDER Gábor <szeder.dev@gmail.com>
Date
Jan 27, 2019, 13:08 UTC
Message-ID
<20190127130832.23652-1-szeder.dev@gmail.com>
In-Reply-To
<20190125222126.GH6702@szeder.dev>

When the commit graph and generation numbers were introduced in commits 177722b344 (commit: integrate commit graph with commit parsing, 2018-04-10) and 83073cc994 (commit: add generation number to struct commit, 2018-04-25), they tried to make sure that the corresponding 'graph_pos' and 'generation' fields of 'struct commit' are initialized conservatively, as if the commit were not included in the commit-graph file.

Alas, initializing those fields only in alloc_commit_node() missed the case when an object that happens to be a commit is first looked up via lookup_unknown_object(), and is then later converted to a 'struct commit' via the object_as_type() helper function (either calling it directly, or as part of a subsequent lookup_commit() call). Consequently, both of those fields incorrectly remain set to zero, which means e.g. that the commit is present in and is the first entry of the commit-graph file. This will result in wrong timestamp, parent and root tree hashes, if such a 'struct commit' instance is later filled from the commit-graph.

Extract the initialization of 'struct commit's fields from alloc_commit_node() into a helper function, and call it from object_as_type() as well, to make sure that it properly initializes the two commit-graph-related fields, too. With this helper function it is hopefully less likely that any new fields added to 'struct commit' in the future would remain uninitialized.

With this change alloc_commit_index() won't have any remaining callers outside of 'alloc.c', so mark it as static.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
---

So, it turns out that ec0c5798ee (revision: use commit graph in get_reference(), 2018-12-04) is not the culprit after all, it merely highlighted a bug that is as old as the commit-graph feature itself. This patch fixes this and all other related issues I reported upthread.

I couldn't find any other place where an object of unknown type is turned into a 'struct commit', so this might have been the only place that needed fixing.

Other object types seem to be fine, because they contain only fields that should be zero initialized. At least for now, because a similar issue might arise in the future, if one of them gains a new field that should not be initialized to zero... but will they ever get such a field? So I'm not too keen on introducing similar init_tree_node(), etc. helper funcions at the moment.

 alloc.c  | 11 ++++++++---
 alloc.h  |  2 +-
 object.c |  5 +++--
 3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/alloc.c b/alloc.c
index e7aa81b7aa..1c64c4dd16 100644
--- a/alloc.c
+++ b/alloc.c
@@ -99,18 +99,23 @@ void *alloc_object_node(struct repository *r)
 	return obj;
 }
 
-unsigned int alloc_commit_index(struct repository *r)
+static unsigned int alloc_commit_index(struct repository *r)
 {
 	return r->parsed_objects->commit_count++;
 }
 
-void *alloc_commit_node(struct repository *r)
+void init_commit_node(struct repository *r, struct commit *c)
 {
-	struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit));
 	c->object.type = OBJ_COMMIT;
 	c->index = alloc_commit_index(r);
 	c->graph_pos = COMMIT_NOT_FROM_GRAPH;
 	c->generation = GENERATION_NUMBER_INFINITY;
+}
+
+void *alloc_commit_node(struct repository *r)
+{
+	struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit));
+	init_commit_node(r, c);
 	return c;
 }
 
diff --git a/alloc.h b/alloc.h
index ba356ed847..ed1071c11e 100644
--- a/alloc.h
+++ b/alloc.h
@@ -9,11 +9,11 @@ struct repository;
 
 void *alloc_blob_node(struct repository *r);
 void *alloc_tree_node(struct repository *r);
+void init_commit_node(struct repository *r, struct commit *c);
 void *alloc_commit_node(struct repository *r);
 void *alloc_tag_node(struct repository *r);
 void *alloc_object_node(struct repository *r);
 void alloc_report(struct repository *r);
-unsigned int alloc_commit_index(struct repository *r);
 
 struct alloc_state *allocate_alloc_state(void);
 void clear_alloc_state(struct alloc_state *s);
diff --git a/object.c b/object.c
index c4170d2d0c..7bccfd5d8e 100644
--- a/object.c
+++ b/object.c
@@ -164,8 +164,9 @@ void *object_as_type(struct repository *r, struct object *obj, enum object_type
 		return obj;
 	else if (obj->type == OBJ_NONE) {
 		if (type == OBJ_COMMIT)
-			((struct commit *)obj)->index = alloc_commit_index(r);
-		obj->type = type;
+			init_commit_node(r, (struct commit *) obj);
+		else
+			obj->type = type;
 		return obj;
 	}
 	else {
-- 
2.20.1.642.gc55a771460
Previous: SZEDER GáborNext: SZEDER Gábor
Message 24 of 28 in “revision: use commit graph in get_reference()”
  1. revision: use commit graph in get_reference()Jonathan Tan, Dec 4, 2018
  2. Stefan BellerDec 4, 2018
  3. Jonathan TanDec 6, 2018
  4. Derrick StoleeDec 7, 2018
  5. Jeff KingDec 5, 2018
  6. Jonathan TanDec 6, 2018
  7. Jeff KingDec 7, 2018
  8. Junio C HamanoDec 5, 2018
  9. revision: use commit graph in get_reference()Jonathan Tan, Dec 7, 2018
  10. Junio C HamanoDec 9, 2018
  11. Junio C HamanoDec 9, 2018
  12. Jeff KingDec 11, 2018
  13. Jonathan TanDec 12, 2018
  14. Jeff KingDec 13, 2018
  15. Derrick StoleeDec 13, 2018
  16. revision: use commit graph in get_reference()Jonathan Tan, Dec 13, 2018
  17. Junio C HamanoDec 14, 2018
  18. Jeff KingDec 14, 2018
  19. Regression in: [PATCH on sb/more-repo-in-api] revision: use commit graph in get_reference()SZEDER Gábor, Jan 25, 2019
  20. Stefan BellerJan 25, 2019
  21. Jonathan TanJan 25, 2019
  22. SZEDER GáborJan 25, 2019
  23. SZEDER GáborJan 25, 2019
  24. object_as_type: initialize commit-graph-related fields of 'struct commit'SZEDER Gábor, Jan 27, 2019
  25. SZEDER GáborJan 27, 2019
  26. Derrick StoleeJan 27, 2019
  27. Jonathan TanJan 28, 2019
  28. Jeff KingJan 28, 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.