pretty: fix memory leaks when parsing pretty formats

When parsing pretty formats from the config we leak the name and user
format whenever these are set multiple times. This is because we do not
free any already-set value in case there is one.

Plugging this leak for the name is trivial. For the user format we need
to be a bit more careful, because we may end up assigning a pointer into
the allocated region when the string is prefixed with either "format" or
"tformat:". In order to make it safe to unconditionally free the user
format we thus strdup the stripped string into the field instead of a
pointer into the string.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt
2024-08-22 11:17:16 +02:00
committed by Junio C Hamano
parent 643c6f576c
commit 60289b50d0

View File

@ -63,7 +63,7 @@ static int git_pretty_formats_config(const char *var, const char *value,
void *cb UNUSED)
{
struct cmt_fmt_map *commit_format = NULL;
const char *name;
const char *name, *stripped;
char *fmt;
int i;
@ -90,15 +90,21 @@ static int git_pretty_formats_config(const char *var, const char *value,
commit_formats_len++;
}
free((char *)commit_format->name);
commit_format->name = xstrdup(name);
commit_format->format = CMIT_FMT_USERFORMAT;
if (git_config_string(&fmt, var, value))
return -1;
if (skip_prefix(fmt, "format:", &commit_format->user_format)) {
free((char *)commit_format->user_format);
if (skip_prefix(fmt, "format:", &stripped)) {
commit_format->is_tformat = 0;
} else if (skip_prefix(fmt, "tformat:", &commit_format->user_format)) {
commit_format->user_format = xstrdup(stripped);
free(fmt);
} else if (skip_prefix(fmt, "tformat:", &stripped)) {
commit_format->is_tformat = 1;
commit_format->user_format = xstrdup(stripped);
free(fmt);
} else if (strchr(fmt, '%')) {
commit_format->is_tformat = 1;
commit_format->user_format = fmt;