git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [RFC/PATCH 1/2] commit: add parse_commit_repl() to replace commits at parsing time
@ 2010-08-17  1:58 Christian Couder
  2010-08-17 21:18 ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Couder @ 2010-08-17  1:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Nguyen Thai Ngoc Duy

The function parse_commit() is not safe regarding replaced commits
because it uses the buffer of the replacement commit but the object
part of the commit struct stay the same. Especially the sha1 is not
changed so it doesn't match the content of the commit.

To fix that, this patch adds a new function that takes a
"struct commit **" instead of a "struct commit *" so we can
change the commit pointer that is passed to us.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 commit.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 commit.h |    6 ++++++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/commit.c b/commit.c
index 652c1ba..f170179 100644
--- a/commit.c
+++ b/commit.c
@@ -316,6 +316,49 @@ int parse_commit(struct commit *item)
 	return ret;
 }
 
+int parse_commit_repl(struct commit **commit)
+{
+	enum object_type type;
+	void *buffer;
+	unsigned long size;
+	int ret;
+	const unsigned char *repl;
+	struct commit *item = *commit;
+
+	if (!item)
+		return -1;
+	if (item->object.parsed)
+		return 0;
+	buffer = read_sha1_file_repl(item->object.sha1, &type, &size, &repl);
+	if (!buffer)
+		return error("Could not read %s",
+			     sha1_to_hex(item->object.sha1));
+
+	if (item->object.sha1 != repl) {
+		struct commit *repl_item = lookup_commit(repl);
+		if (!repl_item) {
+			free(buffer);
+			return error("Bad replacement %s for commit %s",
+				     sha1_to_hex(repl),
+				     sha1_to_hex(item->object.sha1));
+		}
+		repl_item->object.flags = item->object.flags;
+		*commit = item = repl_item;
+	} else if (type != OBJ_COMMIT) {
+		free(buffer);
+		return error("Object %s not a commit",
+			     sha1_to_hex(item->object.sha1));
+	}
+
+	ret = parse_commit_buffer(item, buffer, size);
+	if (save_commit_buffer && !ret) {
+		item->buffer = buffer;
+		return 0;
+	}
+	free(buffer);
+	return ret;
+}
+
 int find_commit_subject(const char *commit_buffer, const char **subject)
 {
 	const char *eol;
diff --git a/commit.h b/commit.h
index a3618f8..d3dfebb 100644
--- a/commit.h
+++ b/commit.h
@@ -39,6 +39,12 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
 
 int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
 
+int parse_commit_repl(struct commit **item);
+
+/*
+ * parse_commit() is deprecated, because it's buggy regarding replacements.
+ * Use parse_commit_repl() instead.
+ */
 int parse_commit(struct commit *item);
 
 /* Find beginning and length of commit subject. */
-- 
1.7.2.1.351.g275bf

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-08-20  4:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-17  1:58 [RFC/PATCH 1/2] commit: add parse_commit_repl() to replace commits at parsing time Christian Couder
2010-08-17 21:18 ` Junio C Hamano
2010-08-18  3:17   ` Nguyen Thai Ngoc Duy
2010-08-18  4:07     ` Christian Couder
2010-08-18  4:24       ` Jonathan Nieder
2010-08-18  4:37         ` Nguyen Thai Ngoc Duy
2010-08-18 14:50       ` Junio C Hamano
2010-08-20  4:04         ` Christian Couder

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).