Skip to content

Commit 04d9744

Browse files
pks-tgitster
authored andcommitted
ref-filter: fix leak with unterminated %(if) atoms
When parsing `%(if)` atoms we expect a few other atoms to exist to complete it, like `%(then)` and `%(end)`. Whether or not we have seen these other atoms is tracked in an allocated `if_then_else` structure, which gets free'd by the `if_then_else_handler()` once we have parsed the complete conditional expression. This results in a memory leak when the `%(if)` atom is not terminated correctly and thus incomplete. We never end up executing its handler and thus don't end up freeing the structure. Plug this memory leak by introducing a new `at_end_data_free` callback function. If set, we'll execute it in `pop_stack_element()` and pass it the `at_end_data` variable with the intent to free its state. Wire it up for the `%(if)` atom accordingly. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent db629c6 commit 04d9744

File tree

2 files changed

+6
-3
lines changed

2 files changed

+6
-3
lines changed

ref-filter.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ struct ref_formatting_stack {
10011001
struct ref_formatting_stack *prev;
10021002
struct strbuf output;
10031003
void (*at_end)(struct ref_formatting_stack **stack);
1004+
void (*at_end_data_free)(void *data);
10041005
void *at_end_data;
10051006
};
10061007

@@ -1169,6 +1170,8 @@ static void pop_stack_element(struct ref_formatting_stack **stack)
11691170
if (prev)
11701171
strbuf_addbuf(&prev->output, &current->output);
11711172
strbuf_release(&current->output);
1173+
if (current->at_end_data_free)
1174+
current->at_end_data_free(current->at_end_data);
11721175
free(current);
11731176
*stack = prev;
11741177
}
@@ -1228,15 +1231,13 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
12281231
}
12291232

12301233
*stack = cur;
1231-
free(if_then_else);
12321234
}
12331235

12341236
static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
12351237
struct strbuf *err UNUSED)
12361238
{
12371239
struct ref_formatting_stack *new_stack;
1238-
struct if_then_else *if_then_else = xcalloc(1,
1239-
sizeof(struct if_then_else));
1240+
struct if_then_else *if_then_else = xcalloc(1, sizeof(*if_then_else));
12401241

12411242
if_then_else->str = atomv->atom->u.if_then_else.str;
12421243
if_then_else->cmp_status = atomv->atom->u.if_then_else.cmp_status;
@@ -1245,6 +1246,7 @@ static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state
12451246
new_stack = state->stack;
12461247
new_stack->at_end = if_then_else_handler;
12471248
new_stack->at_end_data = if_then_else;
1249+
new_stack->at_end_data_free = free;
12481250
return 0;
12491251
}
12501252

t/t6302-for-each-ref-filter.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
test_description='test for-each-refs usage of ref-filter APIs'
44

5+
TEST_PASSES_SANITIZE_LEAK=true
56
. ./test-lib.sh
67
. "$TEST_DIRECTORY"/lib-gpg.sh
78

0 commit comments

Comments
 (0)