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

[CGIT PATCH] parsing.c: handle unexpected commit/tag content

From
LHLars Hjemli <hjemli@gmail.com>
Date
Sep 14, 2008, 07:53 UTC
Message-ID
<1221378782-26036-1-git-send-email-hjemli@gmail.com>
In-Reply-To
<8c5c35580809131302w1f51f4ebsede59eb2ae36a99c@mail.gmail.com>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---

Can you test this on top of the current master? It seems to fix the problems with glibc.git.

 cgit.h    |    2 +-
 parsing.c |  108 +++++++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 71 insertions(+), 39 deletions(-)
diff --git a/cgit.h b/cgit.h
index 1615616..08fd95a 100644
--- a/cgit.h
+++ b/cgit.h
@@ -85,7 +85,7 @@ struct commitinfo {
 struct taginfo {
 	char *tagger;
 	char *tagger_email;
-	int tagger_date;
+	unsigned long tagger_date;
 	char *msg;
 };

diff --git a/parsing.c b/parsing.c
index 66e8b3d..0396133 100644
--- a/parsing.c
+++ b/parsing.c
@@ -62,6 +62,40 @@ char *substr(const char *head, const char *tail)
 	return buf;
 }

+char *parse_user(char *t, char **name, char **email, unsigned long *date)
+{
+	char *p = t;
+	int mode = 1;
+
+	while (p && *p) {
+		if (mode == 1 && *p == '<') {
+			*name = substr(t, p - 1);
+			t = p;
+			mode++;
+		} else if (mode == 1 && *p == '\n') {
+			*name = substr(t, p);
+			p++;
+			break;
+		} else if (mode == 2 && *p == '>') {
+			*email = substr(t, p + 1);
+			t = p;
+			mode++;
+		} else if (mode == 2 && *p == '\n') {
+			*email = substr(t, p);
+			p++;
+			break;
+		} else if (mode == 3 && isdigit(*p)) {
+			*date = atol(p);
+			mode++;
+		} else if (*p == '\n') {
+			p++;
+			break;
+		}
+		p++;
+	}
+	return p;
+}
+
 struct commitinfo *cgit_parse_commit(struct commit *commit)
 {
 	struct commitinfo *ret;
@@ -88,29 +122,17 @@ struct commitinfo *cgit_parse_commit(struct commit *commit)
 	while (!strncmp(p, "parent ", 7))
 		p += 48; // "parent " + hex[40] + "\n"

-	if (!strncmp(p, "author ", 7)) {
-		p += 7;
-		t = strchr(p, '<') - 1;
-		ret->author = substr(p, t);
-		p = t;
-		t = strchr(t, '>') + 1;
-		ret->author_email = substr(p, t);
-		ret->author_date = atol(t+1);
-		p = strchr(t, '\n') + 1;
+	if (p && !strncmp(p, "author ", 7)) {
+		p = parse_user(p + 7, &ret->author, &ret->author_email,
+			&ret->author_date);
 	}

-	if (!strncmp(p, "committer ", 9)) {
-		p += 9;
-		t = strchr(p, '<') - 1;
-		ret->committer = substr(p, t);
-		p = t;
-		t = strchr(t, '>') + 1;
-		ret->committer_email = substr(p, t);
-		ret->committer_date = atol(t+1);
-		p = strchr(t, '\n') + 1;
+	if (p && !strncmp(p, "committer ", 9)) {
+		p = parse_user(p + 9, &ret->committer, &ret->committer_email,
+			&ret->committer_date);
 	}

-	if (!strncmp(p, "encoding ", 9)) {
+	if (p && !strncmp(p, "encoding ", 9)) {
 		p += 9;
 		t = strchr(p, '\n') + 1;
 		ret->msg_encoding = substr(p, t);
@@ -118,25 +140,38 @@ struct commitinfo *cgit_parse_commit(struct commit *commit)
 	} else
 		ret->msg_encoding = xstrdup(PAGE_ENCODING);

-	while (*p && (*p != '\n'))
-		p = strchr(p, '\n') + 1; // skip unknown header fields
+	// skip unknown header fields
+	while (p && *p && (*p != '\n')) {
+		p = strchr(p, '\n');
+		if (p)
+			p++;
+	}

-	while (*p == '\n')
-		p = strchr(p, '\n') + 1;
+	// skip extra blank lines between headers and message body
+	while (p && *p == '\n') {
+		p = strchr(p, '\n');
+		if (p)
+			p++;
+	}

 	t = strchr(p, '\n');
 	if (t) {
-		if (*t == '\0')
+		if (*t == '\0') {
 			ret->subject = "** empty **";
-		else
+			return ret;
+		} else {
 			ret->subject = substr(p, t);
-		p = t + 1;
+			p = t + 1;
+		}

-		while (*p == '\n')
-			p = strchr(p, '\n') + 1;
+		while (p && *p == '\n') {
+			p = strchr(p, '\n');
+			if (p)
+				p++;
+		}
 		ret->msg = xstrdup(p);
 	} else
-		ret->subject = substr(p, p+strlen(p));
+		ret->subject = xstrdup(p);

 	if(strcmp(ret->msg_encoding, PAGE_ENCODING)) {
 		t = reencode_string(ret->subject, PAGE_ENCODING,
@@ -163,7 +198,7 @@ struct taginfo *cgit_parse_tag(struct tag *tag)
 	void *data;
 	enum object_type type;
 	unsigned long size;
-	char *p, *t;
+	char *p;
 	struct taginfo *ret;

 	data = read_sha1_file(tag->object.sha1, &type, &size);
@@ -185,15 +220,12 @@ struct taginfo *cgit_parse_tag(struct tag *tag)
 			break;

 		if (!strncmp(p, "tagger ", 7)) {
-			p += 7;
-			t = strchr(p, '<') - 1;
-			ret->tagger = substr(p, t);
-			p = t;
-			t = strchr(t, '>') + 1;
-			ret->tagger_email = substr(p, t);
-			ret->tagger_date = atol(t+1);
+			p = parse_user(p + 7, &ret->tagger, &ret->tagger_email,
+				&ret->tagger_date);
 		}
-		p = strchr(p, '\n') + 1;
+		p = strchr(p, '\n');
+		if (p)
+			p++;
 	}

 	while (p && *p && (*p != '\n'))
--
1.6.0.rc1
Previous: Lars HjemliNext: Lars Hjemli
Message 21 of 26 in “configuring git public repository”
  1. sagi4Sep 12, 2008
  2. Ciprian Dorin CraciunSep 12, 2008
  3. Jakub NarebskiSep 12, 2008
  4. Lars HjemliSep 12, 2008
  5. CGit and repository listPetr Baudis, Sep 12, 2008
  6. Lars HjemliSep 12, 2008
  7. Jakub NarebskiSep 12, 2008
  8. Shawn O. PearceSep 12, 2008
  9. Lars HjemliSep 12, 2008
  10. Petr BaudisSep 12, 2008
  11. Shawn O. PearceSep 12, 2008
  12. Petr BaudisSep 12, 2008
  13. Shawn O. PearceSep 12, 2008
  14. Jakub NarebskiSep 12, 2008
  15. Shawn O. PearceSep 12, 2008
  16. Petr BaudisSep 12, 2008
  17. Petr BaudisSep 12, 2008
  18. Lars HjemliSep 12, 2008
  19. Petr BaudisSep 13, 2008
  20. Lars HjemliSep 13, 2008
  21. parsing.c: handle unexpected commit/tag contentLars Hjemli, Sep 14, 2008
  22. Lars HjemliSep 14, 2008
  23. Lars HjemliSep 15, 2008
  24. Kristian HøgsbergSep 14, 2008
  25. Kristian HøgsbergSep 14, 2008
  26. Lars HjemliSep 14, 2008

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.