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>
This commit is contained in:
Jeff King
2014-08-27 03:57:28 -04:00
committed by Junio C Hamano
parent c33ddc2e33
commit f0f9662ae9

View File

@ -546,42 +546,35 @@ static void determine_author_info(struct strbuf *author_ident)
date = getenv("GIT_AUTHOR_DATE"); date = getenv("GIT_AUTHOR_DATE");
if (author_message) { if (author_message) {
const char *a, *lb, *rb, *eol; struct ident_split ident;
size_t len; size_t len;
const char *a;
a = strstr(author_message_buffer, "\nauthor "); a = find_commit_header(author_message_buffer, "author", &len);
if (!a) if (!a)
die(_("invalid commit: %s"), author_message); 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);
lb = strchrnul(a + strlen("\nauthor "), '<'); name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
rb = strchrnul(lb, '>'); email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
eol = strchrnul(rb, '\n'); if (ident.date_begin) {
if (!*lb || !*rb || !*eol) strbuf_reset(&date_buf);
die(_("invalid commit: %s"), author_message); strbuf_addch(&date_buf, '@');
strbuf_add(&date_buf, ident.date_begin, ident.date_end - ident.date_begin);
if (lb == a + strlen("\nauthor ")) strbuf_addch(&date_buf, ' ');
/* \nauthor <foo@example.com> */ strbuf_add(&date_buf, ident.tz_begin, ident.tz_end - ident.tz_begin);
name = xcalloc(1, 1); date = date_buf.buf;
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';
} }
if (force_author) { if (force_author) {
const char *lb = strstr(force_author, " <"); struct ident_split ident;
const char *rb = strchr(force_author, '>');
if (!lb || !rb) if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
die(_("malformed --author parameter")); die(_("malformed --author parameter"));
name = xstrndup(force_author, lb - force_author); name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
email = xstrndup(lb + 2, rb - (lb + 2)); email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
} }
if (force_date) { if (force_date) {