summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2014-08-27 03:57:56 -0400
committerJunio C Hamano <gitster@pobox.com>2014-08-29 10:33:28 -0700
commitf4ef51739343f80c7cb0467244925b3725d65730 (patch)
tree8e97ad99b286cf2e68150ca48df5d37a526e44b2
parentf0f9662ae9d1c7f58a95397d1c6d5f31760b14be (diff)
downloadgit-jk/commit-author-parsing.tar.gz
determine_author_info(): copy getenv outputjk/commit-author-parsing
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>
-rw-r--r--builtin/commit.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/builtin/commit.c b/builtin/commit.c
index bc03a1c40d..8c6372038b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -535,15 +535,26 @@ static int parse_force_date(const char *in, struct strbuf *out)
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;
- 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;
@@ -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);
- 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) {
- 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);
- 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"));
- 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) {
- 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);
- date = date_buf.buf;
+ set_ident_var(&date, strbuf_detach(&date_buf, NULL));
}
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, '@');
}
- strbuf_release(&date_buf);
+ free(name);
+ free(email);
+ free(date);
}
static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)