Skip to content

Commit cf8c423

Browse files
pks-tgitster
authored andcommitted
parse-options: free previous value of OPTION_FILENAME
The `OPTION_FILENAME` option always assigns either an allocated string or `NULL` to the value. In case it is passed multiple times it does not know to free the previous value though, which causes a memory leak. Refactor the function to always free the previous value. None of the sites where this option is used pass a string constant, so this change is safe. While at it, fix the argument of `fix_filename()` to be a string constant. The only reason why it's not is because we use it as an in-out-parameter, where the input is a constant and the output is not. This is weird and unnecessary, as we can just return the result instead of using the parameter for this. This leak is being hit in t7621, but plugging it alone does not make the test suite pass. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 76c7e70 commit cf8c423

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

parse-options.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p,
6060
return 0;
6161
}
6262

63-
static void fix_filename(const char *prefix, char **file)
63+
static char *fix_filename(const char *prefix, const char *file)
6464
{
6565
if (!file || !*file)
66-
; /* leave as NULL */
66+
return NULL;
6767
else
68-
*file = prefix_filename_except_for_dash(prefix, *file);
68+
return prefix_filename_except_for_dash(prefix, file);
6969
}
7070

7171
static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
@@ -129,18 +129,24 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
129129
return 0;
130130

131131
case OPTION_FILENAME:
132+
{
133+
const char *value;
134+
135+
FREE_AND_NULL(*(char **)opt->value);
136+
132137
err = 0;
138+
133139
if (unset)
134-
*(const char **)opt->value = NULL;
140+
value = NULL;
135141
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
136-
*(const char **)opt->value = (const char *)opt->defval;
142+
value = (const char *) opt->defval;
137143
else
138-
err = get_arg(p, opt, flags, (const char **)opt->value);
144+
err = get_arg(p, opt, flags, &value);
139145

140146
if (!err)
141-
fix_filename(p->prefix, (char **)opt->value);
147+
*(char **)opt->value = fix_filename(p->prefix, value);
142148
return err;
143-
149+
}
144150
case OPTION_CALLBACK:
145151
{
146152
const char *p_arg = NULL;

0 commit comments

Comments
 (0)