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)