determine_author_info(): copy getenv output
authorJeff King <peff@peff.net>
Wed, 27 Aug 2014 07:57:56 +0000 (03:57 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 29 Aug 2014 17:33:28 +0000 (10:33 -0700)
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>
builtin/commit.c
index bc03a1c40de085f431a300e0d1021ab1eff0357e..8c6372038bc9827e2d4e462228e79fa66e13c220 100644 (file)
@@ -535,15 +535,26 @@ static int parse_force_date(const char *in, struct strbuf *out)
        return 0;
 }
 
        return 0;
 }
 
+static void set_ident_var(char **buf, char *val)
+{
+       free(*buf);
+       *buf = val;
+}
+
+static char *envdup(const char *var)
+{
+       const char *val = getenv(var);
+       return val ? xstrdup(val) : NULL;
+}
+
 static void determine_author_info(struct strbuf *author_ident)
 {
        char *name, *email, *date;
        struct ident_split author;
 static void determine_author_info(struct strbuf *author_ident)
 {
        char *name, *email, *date;
        struct ident_split author;
-       struct strbuf date_buf = STRBUF_INIT;
 
 
-       name = getenv("GIT_AUTHOR_NAME");
-       email = getenv("GIT_AUTHOR_EMAIL");
-       date = getenv("GIT_AUTHOR_DATE");
+       name = envdup("GIT_AUTHOR_NAME");
+       email = envdup("GIT_AUTHOR_EMAIL");
+       date = envdup("GIT_AUTHOR_DATE");
 
        if (author_message) {
                struct ident_split ident;
 
        if (author_message) {
                struct ident_split ident;
@@ -556,15 +567,16 @@ static void determine_author_info(struct strbuf *author_ident)
                if (split_ident_line(&ident, a, len) < 0)
                        die(_("commit '%s' has malformed author line"), 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);
+               set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
+               set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
+
                if (ident.date_begin) {
                if (ident.date_begin) {
-                       strbuf_reset(&date_buf);
+                       struct strbuf date_buf = STRBUF_INIT;
                        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);
                        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;
+                       set_ident_var(&date, strbuf_detach(&date_buf, NULL));
                }
        }
 
                }
        }
 
@@ -573,15 +585,15 @@ static void determine_author_info(struct strbuf *author_ident)
 
                if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
                        die(_("malformed --author parameter"));
 
                if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
                        die(_("malformed --author parameter"));
-               name = xmemdupz(ident.name_begin, ident.name_end - ident.name_begin);
-               email = xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin);
+               set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
+               set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
        }
 
        if (force_date) {
        }
 
        if (force_date) {
-               strbuf_reset(&date_buf);
+               struct strbuf date_buf = STRBUF_INIT;
                if (parse_force_date(force_date, &date_buf))
                        die(_("invalid date format: %s"), force_date);
                if (parse_force_date(force_date, &date_buf))
                        die(_("invalid date format: %s"), force_date);
-               date = date_buf.buf;
+               set_ident_var(&date, strbuf_detach(&date_buf, NULL));
        }
 
        strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
        }
 
        strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
@@ -592,7 +604,9 @@ static void determine_author_info(struct strbuf *author_ident)
                export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
        }
 
                export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
        }
 
-       strbuf_release(&date_buf);
+       free(name);
+       free(email);
+       free(date);
 }
 
 static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)
 }
 
 static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)