Skip to content

Commit 5a8c069

Browse files
committed
clean: do not pass strbuf by value
When you pass a structure by value, the callee can modify the contents of the structure that was passed in without having to worry about changing the structure the caller has. Passing structure by value sometimes (but not very often) can be a valid way to give callee a temporary variable it can freely modify. But not a structure with members that are pointers, like a strbuf. builtin/clean.c:list_and_choose() reads a line interactively from the user, and passes the line (in a strbuf) to parse_choice() by value, which then munges by replacing ',' with ' ' (to accept both comma and space separated list of choices). But because the strbuf passed by value still shares the underlying character array buf[], this ends up munging the caller's strbuf contents. This is a catastrophe waiting to happen. If the callee causes the strbuf to be reallocated, the buf[] the caller has will become dangling, and when the caller does strbuf_release(), it would result in double-free. Stop calling the function with misleading call-by-value with strbuf. Signed-off-by: Junio C Hamano <[email protected]>
1 parent f2e85c2 commit 5a8c069

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

builtin/clean.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,22 +477,22 @@ static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
477477
*/
478478
static int parse_choice(struct menu_stuff *menu_stuff,
479479
int is_single,
480-
struct strbuf input,
480+
struct strbuf *input,
481481
int **chosen)
482482
{
483483
struct strbuf **choice_list, **ptr;
484484
int nr = 0;
485485
int i;
486486

487487
if (is_single) {
488-
choice_list = strbuf_split_max(&input, '\n', 0);
488+
choice_list = strbuf_split_max(input, '\n', 0);
489489
} else {
490-
char *p = input.buf;
490+
char *p = input->buf;
491491
do {
492492
if (*p == ',')
493493
*p = ' ';
494494
} while (*p++);
495-
choice_list = strbuf_split_max(&input, ' ', 0);
495+
choice_list = strbuf_split_max(input, ' ', 0);
496496
}
497497

498498
for (ptr = choice_list; *ptr; ptr++) {
@@ -630,7 +630,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
630630

631631
nr = parse_choice(stuff,
632632
opts->flags & MENU_OPTS_SINGLETON,
633-
choice,
633+
&choice,
634634
&chosen);
635635

636636
if (opts->flags & MENU_OPTS_SINGLETON) {

0 commit comments

Comments
 (0)