determine_author_info(): copy getenv output

When figuring out the author name for a commit, we may end up either pointing to const storage from getenv("GIT_AUTHOR_*"), or to newly allocated storage based on an existing commit or the --author option. Using const pointers to getenv's return has two problems: 1. It is not guaranteed that the return value from getenv remains valid across multiple calls. 2. We do not know whether to free the values at the end, so we just leak them. We can solve both by duplicating the string returned by getenv(). 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 f4ef51739343f80c7cb0467244925b3725d65730
1 file changed +27 -13
builtin/commit.c
+27 -13
@@ -535,15 +535,26 @@ static int parse_force_date(const char *in, struct strbuf *out)
535 return 0;
536 }
537
538 +static void set_ident_var(char **buf, char *val)
539 +{
540 + free(*buf);
541 + *buf = val;
542 +}
543 +
544 +static char *envdup(const char *var)
545 +{
546 + const char *val = getenv(var);
547 + return val ? xstrdup(val) : NULL;
548 +}
549 +
550 static void determine_author_info(struct strbuf *author_ident)
551 {
552 char *name, *email, *date;
553 struct ident_split author;
542 - struct strbuf date_buf = STRBUF_INIT;
554
544 - name = getenv("GIT_AUTHOR_NAME");
545 - email = getenv("GIT_AUTHOR_EMAIL");
546 - date = getenv("GIT_AUTHOR_DATE");
555 + name = envdup("GIT_AUTHOR_NAME");
556 + email = envdup("GIT_AUTHOR_EMAIL");
557 + date = envdup("GIT_AUTHOR_DATE");
558
559 if (author_message) {
560 struct ident_split ident;
@@ -556,15 +567,16 @@ static void determine_author_info(struct strbuf *author_ident)
567 if (split_ident_line(&ident, a, len) < 0)
568 die(_("commit '%s' has malformed author line"), author_message);
569
559 - name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
560 - email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
570 + set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
571 + set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
572 +
573 if (ident.date_begin) {
562 - strbuf_reset(&date_buf);
574 + struct strbuf date_buf = STRBUF_INIT;
575 strbuf_addch(&date_buf, '@');
576 strbuf_add(&date_buf, ident.date_begin, ident.date_end - ident.date_begin);
577 strbuf_addch(&date_buf, ' ');
578 strbuf_add(&date_buf, ident.tz_begin, ident.tz_end - ident.tz_begin);
567 - date = date_buf.buf;
579 + set_ident_var(&date, strbuf_detach(&date_buf, NULL));
580 }
581 }
582
@@ -573,15 +585,15 @@ static void determine_author_info(struct strbuf *author_ident)
585
586 if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
587 die(_("malformed --author parameter"));
576 - name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
577 - email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
588 + set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
589 + set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
590 }
591
592 if (force_date) {
581 - strbuf_reset(&date_buf);
593 + struct strbuf date_buf = STRBUF_INIT;
594 if (parse_force_date(force_date, &date_buf))
595 die(_("invalid date format: %s"), force_date);
584 - date = date_buf.buf;
596 + set_ident_var(&date, strbuf_detach(&date_buf, NULL));
597 }
598
599 strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
@@ -592,7 +604,9 @@ static void determine_author_info(struct strbuf *author_ident)
604 export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
605 }
606
595 - strbuf_release(&date_buf);
607 + free(name);
608 + free(email);
609 + free(date);
610 }
611
612 static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)