ref-filter: fix leak with %(describe) arguments
When we parse a %(describe) placeholder, we stuff its arguments into a strvec, which is then detached into the used_atom struct. But later, when ref_array_clear() frees the atom, we never free the memory. To solve this, we just need to add the appropriate free() calls. But it's a little awkward, since we have to free each element of the array, in addition to the array itself. Instead, let's store the actual strvec, which lets us do a simple strvec_clear(). This clears up one case that LSan finds in t6300, but there are more. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
f6ba781903
commit
ec007cde94
11
ref-filter.c
11
ref-filter.c
|
@ -233,7 +233,7 @@ static struct used_atom {
|
||||||
enum { S_BARE, S_GRADE, S_SIGNER, S_KEY,
|
enum { S_BARE, S_GRADE, S_SIGNER, S_KEY,
|
||||||
S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;
|
S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;
|
||||||
} signature;
|
} signature;
|
||||||
const char **describe_args;
|
struct strvec describe_args;
|
||||||
struct refname_atom refname;
|
struct refname_atom refname;
|
||||||
char *head;
|
char *head;
|
||||||
} u;
|
} u;
|
||||||
|
@ -693,7 +693,7 @@ static int describe_atom_parser(struct ref_format *format UNUSED,
|
||||||
struct used_atom *atom,
|
struct used_atom *atom,
|
||||||
const char *arg, struct strbuf *err)
|
const char *arg, struct strbuf *err)
|
||||||
{
|
{
|
||||||
struct strvec args = STRVEC_INIT;
|
strvec_init(&atom->u.describe_args);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
@ -702,13 +702,12 @@ static int describe_atom_parser(struct ref_format *format UNUSED,
|
||||||
if (!arg || !*arg)
|
if (!arg || !*arg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
found = describe_atom_option_parser(&args, &arg, err);
|
found = describe_atom_option_parser(&atom->u.describe_args, &arg, err);
|
||||||
if (found < 0)
|
if (found < 0)
|
||||||
return found;
|
return found;
|
||||||
if (!found)
|
if (!found)
|
||||||
return err_bad_arg(err, "describe", bad_arg);
|
return err_bad_arg(err, "describe", bad_arg);
|
||||||
}
|
}
|
||||||
atom->u.describe_args = strvec_detach(&args);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1941,7 +1940,7 @@ static void grab_describe_values(struct atom_value *val, int deref,
|
||||||
|
|
||||||
cmd.git_cmd = 1;
|
cmd.git_cmd = 1;
|
||||||
strvec_push(&cmd.args, "describe");
|
strvec_push(&cmd.args, "describe");
|
||||||
strvec_pushv(&cmd.args, atom->u.describe_args);
|
strvec_pushv(&cmd.args, atom->u.describe_args.v);
|
||||||
strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
|
strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
|
||||||
if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
|
if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
|
||||||
error(_("failed to run 'describe'"));
|
error(_("failed to run 'describe'"));
|
||||||
|
@ -3004,6 +3003,8 @@ void ref_array_clear(struct ref_array *array)
|
||||||
struct used_atom *atom = &used_atom[i];
|
struct used_atom *atom = &used_atom[i];
|
||||||
if (atom->atom_type == ATOM_HEAD)
|
if (atom->atom_type == ATOM_HEAD)
|
||||||
free(atom->u.head);
|
free(atom->u.head);
|
||||||
|
else if (atom->atom_type == ATOM_DESCRIBE)
|
||||||
|
strvec_clear(&atom->u.describe_args);
|
||||||
else if (atom->atom_type == ATOM_TRAILERS ||
|
else if (atom->atom_type == ATOM_TRAILERS ||
|
||||||
(atom->atom_type == ATOM_CONTENTS &&
|
(atom->atom_type == ATOM_CONTENTS &&
|
||||||
atom->u.contents.option == C_TRAILERS)) {
|
atom->u.contents.option == C_TRAILERS)) {
|
||||||
|
|
Loading…
Reference in New Issue