Skip to content

Commit 4c81ee9

Browse files
avargitster
authored andcommitted
submodule--helper: fix "reference" leak
Fix leaks in the "reference" variable declared in add_submodule() and module_clone(). In preceding commits this variable was refactored out of the "struct module_clone_data", but the leak has been with us since 31224cb (clone: recursive and reference option triggers submodule alternates, 2016-08-17) and 8c8195e (submodule--helper: introduce add-clone subcommand, 2021-07-10). Those commits added an xstrdup()'d member of the STRING_LIST_INIT_NODUP'd "struct string_list". We need to free() those, but not the ones we get from argv, let's make use of the "util" member, if it has a pointer it's the pointer we'll need to free, otherwise it'll be NULL (i.e. from argv). Note that the free() of the "util" member is needed in both module_clone() and add_submodule(). The module_clone() function itself doesn't populate the "util" pointer as add_submodule() does, but module_clone() is upstream of the add_possible_reference_from_superproject() caller we're modifying here, which does do that. This does preclude the use of the "util" pointer for any other reasons for now, but that's OK. If we ever need to use it for something else we could turn it into a small "struct" with an optional "to_free" member, and switch to using string_list_clear_func(). Alternatively we could have another "struct string_list to_free" which would keep a copy of the strings we've dup'd to free(). But for now this is perfectly adequate. Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Reviewed-by: Glen Choo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ae3ef94 commit 4c81ee9

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

builtin/submodule--helper.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,9 @@ static int add_possible_reference_from_superproject(
15631563

15641564
sm_alternate = compute_alternate_path(sb.buf, &err);
15651565
if (sm_alternate) {
1566-
string_list_append(sas->reference, xstrdup(sb.buf));
1566+
char *p = strbuf_detach(&sb, NULL);
1567+
1568+
string_list_append(sas->reference, p)->util = p;
15671569
free(sm_alternate);
15681570
} else {
15691571
switch (sas->error_mode) {
@@ -1795,6 +1797,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
17951797

17961798
clone_submodule(&clone_data, &reference);
17971799
list_objects_filter_release(&filter_options);
1800+
string_list_clear(&reference, 1);
17981801
return 0;
17991802
}
18001803

@@ -3042,6 +3045,7 @@ static int add_submodule(const struct add_data *add_data)
30423045
char *submod_gitdir_path;
30433046
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
30443047
struct string_list reference = STRING_LIST_INIT_NODUP;
3048+
int ret = -1;
30453049

30463050
/* perhaps the path already exists and is already a git repo, else clone it */
30473051
if (is_directory(add_data->sm_path)) {
@@ -3097,15 +3101,17 @@ static int add_submodule(const struct add_data *add_data)
30973101
clone_data.url = add_data->realrepo;
30983102
clone_data.quiet = add_data->quiet;
30993103
clone_data.progress = add_data->progress;
3100-
if (add_data->reference_path)
3101-
string_list_append(&reference,
3102-
xstrdup(add_data->reference_path));
3104+
if (add_data->reference_path) {
3105+
char *p = xstrdup(add_data->reference_path);
3106+
3107+
string_list_append(&reference, p)->util = p;
3108+
}
31033109
clone_data.dissociate = add_data->dissociate;
31043110
if (add_data->depth >= 0)
31053111
clone_data.depth = xstrfmt("%d", add_data->depth);
31063112

31073113
if (clone_submodule(&clone_data, &reference))
3108-
return -1;
3114+
goto cleanup;
31093115

31103116
prepare_submodule_repo_env(&cp.env);
31113117
cp.git_cmd = 1;
@@ -3124,7 +3130,10 @@ static int add_submodule(const struct add_data *add_data)
31243130
if (run_command(&cp))
31253131
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
31263132
}
3127-
return 0;
3133+
ret = 0;
3134+
cleanup:
3135+
string_list_clear(&reference, 1);
3136+
return ret;
31283137
}
31293138

31303139
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)

0 commit comments

Comments
 (0)