determine_author_info(): reuse parsing functions
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 <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Aug 27, 2014 at 03:57 UTC
f0f9662ae9d1c7f58a95397d1c6d5f31760b14be
1 file changed
+21
-28
builtin/commit.c
+21
-28
@@ -546,42 +546,35 @@ static void determine_author_info(struct strbuf *author_ident)
546
date = getenv("GIT_AUTHOR_DATE");
547
548
if (author_message) {
549
- const char *a, *lb, *rb, *eol;
549
+ struct ident_split ident;
550
size_t len;
551
+ const char *a;
552
552
- a = strstr(author_message_buffer, "\nauthor ");
553
+ a = find_commit_header(author_message_buffer, "author", &len);
554
if (!a)
554
- die(_("invalid commit: %s"), author_message);
555
-
556
- lb = strchrnul(a + strlen("\nauthor "), '<');
557
- rb = strchrnul(lb, '>');
558
- eol = strchrnul(rb, '\n');
559
- if (!*lb || !*rb || !*eol)
560
- die(_("invalid commit: %s"), author_message);
561
-
562
- if (lb == a + strlen("\nauthor "))
563
- /* \nauthor <foo@example.com> */
564
- name = xcalloc(1, 1);
565
- else
566
- name = xmemdupz(a + strlen("\nauthor "),
567
- (lb - strlen(" ") -
568
- (a + strlen("\nauthor "))));
569
- email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
570
- len = eol - (rb + strlen("> "));
571
- date = xmalloc(len + 2);
572
- *date = '@';
573
- memcpy(date + 1, rb + strlen("> "), len);
574
- date[len + 1] = '\0';
555
+ die(_("commit '%s' lacks author header"), author_message);
556
+ if (split_ident_line(&ident, a, len) < 0)
557
+ die(_("commit '%s' has malformed author line"), author_message);
558
+
559
+ name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
560
+ email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
561
+ if (ident.date_begin) {
562
+ strbuf_reset(&date_buf);
563
+ strbuf_addch(&date_buf, '@');
564
+ strbuf_add(&date_buf, ident.date_begin, ident.date_end - ident.date_begin);
565
+ strbuf_addch(&date_buf, ' ');
566
+ strbuf_add(&date_buf, ident.tz_begin, ident.tz_end - ident.tz_begin);
567
+ date = date_buf.buf;
568
+ }
569
}
570
571
if (force_author) {
578
- const char *lb = strstr(force_author, " <");
579
- const char *rb = strchr(force_author, '>');
572
+ struct ident_split ident;
573
581
- if (!lb || !rb)
574
+ if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
575
die(_("malformed --author parameter"));
583
- name = xstrndup(force_author, lb - force_author);
584
- email = xstrndup(lb + 2, rb - (lb + 2));
576
+ name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
577
+ email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
578
}
579
580
if (force_date) {