Rather than parsing the header manually to find the "author"
field, and then parsing its sub-parts, let's use
find_commit_header and split_ident_line. This is shorter and
easier to read, and should do a more careful parsing job.

For example, the current parser could find the end-of-email
right-bracket across a newline (for a malformed commit), and
calculate a bogus gigantic length for the date (by using
"eol - rb").

As a bonus, this also plugs a memory leak when we pull the
date field from an existing commit (we still leak the name
and email buffers, which will be fixed in a later commit).

Signed-off-by: Jeff King <p...@peff.net>
---
 builtin/commit.c | 51 ++++++++++++++++++++++-----------------------------
 1 file changed, 22 insertions(+), 29 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 8da0a9f..57b046b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -546,42 +546,35 @@ static void determine_author_info(struct strbuf 
*author_ident)
        date = getenv("GIT_AUTHOR_DATE");
 
        if (author_message) {
-               const char *a, *lb, *rb, *eol;
-               size_t len;
+               struct ident_split ident;
+               unsigned long len;
+               const char *a;
 
-               a = strstr(author_message_buffer, "\nauthor ");
+               a = find_commit_header(author_message_buffer, "author", &len);
                if (!a)
-                       die(_("invalid commit: %s"), author_message);
-
-               lb = strchrnul(a + strlen("\nauthor "), '<');
-               rb = strchrnul(lb, '>');
-               eol = strchrnul(rb, '\n');
-               if (!*lb || !*rb || !*eol)
-                       die(_("invalid commit: %s"), author_message);
-
-               if (lb == a + strlen("\nauthor "))
-                       /* \nauthor <f...@example.com> */
-                       name = xcalloc(1, 1);
-               else
-                       name = xmemdupz(a + strlen("\nauthor "),
-                                       (lb - strlen(" ") -
-                                        (a + strlen("\nauthor "))));
-               email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
-               len = eol - (rb + strlen("> "));
-               date = xmalloc(len + 2);
-               *date = '@';
-               memcpy(date + 1, rb + strlen("> "), len);
-               date[len + 1] = '\0';
+                       die(_("commit '%s' lacks author header"), 
author_message);
+               if (split_ident_line(&ident, a, len) < 0)
+                       die(_("commit '%s' has malformed author line"), 
author_message);
+
+               name = xmemdupz(ident.name_begin, ident.name_end - 
ident.name_begin);
+               email = xmemdupz(ident.mail_begin, ident.mail_end - 
ident.mail_begin);
+               if (ident.date_begin) {
+                       strbuf_reset(&date_buf);
+                       strbuf_addch(&date_buf, '@');
+                       strbuf_add(&date_buf, ident.date_begin, ident.date_end 
- ident.date_begin);
+                       strbuf_addch(&date_buf, ' ');
+                       strbuf_add(&date_buf, ident.tz_begin, ident.tz_end - 
ident.tz_begin);
+                       date = date_buf.buf;
+               }
        }
 
        if (force_author) {
-               const char *lb = strstr(force_author, " <");
-               const char *rb = strchr(force_author, '>');
+               struct ident_split ident;
 
-               if (!lb || !rb)
+               if (split_ident_line(&ident, force_author, 
strlen(force_author)) < 0)
                        die(_("malformed --author parameter"));
-               name = xstrndup(force_author, lb - force_author);
-               email = xstrndup(lb + 2, rb - (lb + 2));
+               name = xmemdupz(ident.name_begin, ident.name_end - 
ident.name_begin);
+               email = xmemdupz(ident.mail_begin, ident.mail_end - 
ident.mail_begin);
        }
 
        if (force_date) {
-- 
2.1.0.346.ga0367b9

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to