* [PATCH v3 01/26] submodule--helper: replace memset() with { 0 }-initialization
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:12 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:12 ` [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
` (25 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:12 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Use the less verbose { 0 }-initialization syntax rather than memset()
in builtin/submodule--helper.c, this doesn't make a difference in
terms of behavior, but as we're about to modify adjacent code makes
this more consistent, and lets us avoid worrying about when the
memset() happens v.s. a "goto cleanup".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fac52ade5e1..73717be957c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1744,7 +1744,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
{
int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
- struct list_objects_filter_options filter_options;
+ struct list_objects_filter_options filter_options = { 0 };
struct option module_clone_options[] = {
OPT_STRING(0, "prefix", &clone_data.prefix,
@@ -1786,7 +1786,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
NULL
};
- memset(&filter_options, 0, sizeof(filter_options));
argc = parse_options(argc, argv, prefix, module_clone_options,
git_submodule_helper_usage, 0);
@@ -2563,7 +2562,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec;
struct update_data opt = UPDATE_DATA_INIT;
- struct list_objects_filter_options filter_options;
+ struct list_objects_filter_options filter_options = { 0 };
int ret;
struct option module_update_options[] = {
@@ -2623,7 +2622,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
update_clone_config_from_gitmodules(&opt.max_jobs);
git_config(git_update_clone_config, &opt.max_jobs);
- memset(&filter_options, 0, sizeof(filter_options));
argc = parse_options(argc, argv, prefix, module_update_options,
git_submodule_helper_usage, 0);
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-07-21 19:12 ` [PATCH v3 01/26] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:12 ` Ævar Arnfjörð Bjarmason
2022-07-21 21:16 ` Junio C Hamano
2022-07-21 19:12 ` [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
` (24 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:12 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Refactor the three uses of a "struct strbuf sb" such that each of them
exists in its own scope. This makes the control flow clearer.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 73717be957c..29641690c8c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1638,18 +1638,28 @@ static void prepare_possible_alternates(const char *sm_name,
free(error_strategy);
}
-static int clone_submodule(struct module_clone_data *clone_data)
+static char *clone_submodule_sm_gitdir(const char *name)
{
- char *p, *sm_gitdir;
- char *sm_alternate = NULL, *error_strategy = NULL;
struct strbuf sb = STRBUF_INIT;
- struct child_process cp = CHILD_PROCESS_INIT;
+ char *sm_gitdir;
- submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
+ submodule_name_to_gitdir(&sb, the_repository, name);
sm_gitdir = absolute_pathdup(sb.buf);
- strbuf_reset(&sb);
+ strbuf_release(&sb);
+
+ return sm_gitdir;
+}
+
+static int clone_submodule(struct module_clone_data *clone_data)
+{
+ char *p;
+ char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
+ char *sm_alternate = NULL, *error_strategy = NULL;
+ struct child_process cp = CHILD_PROCESS_INIT;
if (!is_absolute_path(clone_data->path)) {
+ struct strbuf sb = STRBUF_INIT;
+
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
clone_data->path = strbuf_detach(&sb, NULL);
} else {
@@ -1705,6 +1715,8 @@ static int clone_submodule(struct module_clone_data *clone_data)
die(_("clone of '%s' into submodule path '%s' failed"),
clone_data->url, clone_data->path);
} else {
+ struct strbuf sb = STRBUF_INIT;
+
if (clone_data->require_init && !access(clone_data->path, X_OK) &&
!is_empty_dir(clone_data->path))
die(_("directory not empty: '%s'"), clone_data->path);
@@ -1712,7 +1724,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
die(_("could not create directory '%s'"), clone_data->path);
strbuf_addf(&sb, "%s/index", sm_gitdir);
unlink_or_warn(sb.buf);
- strbuf_reset(&sb);
+ strbuf_release(&sb);
}
connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
@@ -1734,7 +1746,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
free(sm_alternate);
free(error_strategy);
- strbuf_release(&sb);
free(sm_gitdir);
free(p);
return 0;
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule()
2022-07-21 19:12 ` [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-21 21:16 ` Junio C Hamano
2022-07-22 13:50 ` Ævar Arnfjörð Bjarmason
0 siblings, 1 reply; 186+ messages in thread
From: Junio C Hamano @ 2022-07-21 21:16 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> -static int clone_submodule(struct module_clone_data *clone_data)
> +static char *clone_submodule_sm_gitdir(const char *name)
> {
> - char *p, *sm_gitdir;
> - char *sm_alternate = NULL, *error_strategy = NULL;
> struct strbuf sb = STRBUF_INIT;
> - struct child_process cp = CHILD_PROCESS_INIT;
> + char *sm_gitdir;
>
> - submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
> + submodule_name_to_gitdir(&sb, the_repository, name);
> sm_gitdir = absolute_pathdup(sb.buf);
> - strbuf_reset(&sb);
> + strbuf_release(&sb);
> +
> + return sm_gitdir;
> +}
OK.
> +static int clone_submodule(struct module_clone_data *clone_data)
> +{
> + char *p;
> + char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
> + char *sm_alternate = NULL, *error_strategy = NULL;
> + struct child_process cp = CHILD_PROCESS_INIT;
>
> if (!is_absolute_path(clone_data->path)) {
> + struct strbuf sb = STRBUF_INIT;
> +
> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
> clone_data->path = strbuf_detach(&sb, NULL);
This looks like a roundabout way to say xstrfmt().
> } else {
> @@ -1705,6 +1715,8 @@ static int clone_submodule(struct module_clone_data *clone_data)
> die(_("clone of '%s' into submodule path '%s' failed"),
> clone_data->url, clone_data->path);
> } else {
> + struct strbuf sb = STRBUF_INIT;
> +
> if (clone_data->require_init && !access(clone_data->path, X_OK) &&
> !is_empty_dir(clone_data->path))
> die(_("directory not empty: '%s'"), clone_data->path);
> @@ -1712,7 +1724,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
> die(_("could not create directory '%s'"), clone_data->path);
> strbuf_addf(&sb, "%s/index", sm_gitdir);
> unlink_or_warn(sb.buf);
> - strbuf_reset(&sb);
> + strbuf_release(&sb);
Ditto.
> }
>
> connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
> @@ -1734,7 +1746,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
> free(sm_alternate);
> free(error_strategy);
>
> - strbuf_release(&sb);
> free(sm_gitdir);
> free(p);
> return 0;
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule()
2022-07-21 21:16 ` Junio C Hamano
@ 2022-07-22 13:50 ` Ævar Arnfjörð Bjarmason
2022-07-22 16:48 ` Glen Choo
2022-07-22 18:47 ` Junio C Hamano
0 siblings, 2 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-22 13:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
On Thu, Jul 21 2022, Junio C Hamano wrote:
>> +static int clone_submodule(struct module_clone_data *clone_data)
>> +{
>> + char *p;
>> + char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
>> + char *sm_alternate = NULL, *error_strategy = NULL;
>> + struct child_process cp = CHILD_PROCESS_INIT;
>>
>> if (!is_absolute_path(clone_data->path)) {
>> + struct strbuf sb = STRBUF_INIT;
>> +
>> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
>> clone_data->path = strbuf_detach(&sb, NULL);
>
> This looks like a roundabout way to say xstrfmt().
Yes, I can fix this and others while I'm at it, but a lot of things like
that in this code are funny uses of APIs that we could improve.
I think it's probably best to just leave these for now.
But I also don't mind adding another commit to this already large series
to search/replace the relevant strbuf_detach() with xstrfmt()....
Just let me know...
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule()
2022-07-22 13:50 ` Ævar Arnfjörð Bjarmason
@ 2022-07-22 16:48 ` Glen Choo
2022-07-22 18:47 ` Junio C Hamano
1 sibling, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-07-22 16:48 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, Junio C Hamano
Cc: git, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> On Thu, Jul 21 2022, Junio C Hamano wrote:
>
>>> +static int clone_submodule(struct module_clone_data *clone_data)
>>> +{
>>> + char *p;
>>> + char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
>>> + char *sm_alternate = NULL, *error_strategy = NULL;
>>> + struct child_process cp = CHILD_PROCESS_INIT;
>>>
>>> if (!is_absolute_path(clone_data->path)) {
>>> + struct strbuf sb = STRBUF_INIT;
>>> +
>>> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
>>> clone_data->path = strbuf_detach(&sb, NULL);
>>
>> This looks like a roundabout way to say xstrfmt().
>
> Yes, I can fix this and others while I'm at it, but a lot of things like
> that in this code are funny uses of APIs that we could improve.
>
> I think it's probably best to just leave these for now.
Yes, this series is already pretty long. For reviewability, perhaps we
could to keep this one focused on "leaks fixes" and leave the style
fixes and refactoring for another series (which might include things
like [1]). As a bonus, with this series in place, we'll know that our
refactoring won't introduce more leaks :)
[1] https://lore.kernel.org/git/kl6lbktitf6e.fsf@chooglen-macbookpro.roam.corp.google.com
> But I also don't mind adding another commit to this already large series
> to search/replace the relevant strbuf_detach() with xstrfmt()....
>
> Just let me know...
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule()
2022-07-22 13:50 ` Ævar Arnfjörð Bjarmason
2022-07-22 16:48 ` Glen Choo
@ 2022-07-22 18:47 ` Junio C Hamano
2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
1 sibling, 1 reply; 186+ messages in thread
From: Junio C Hamano @ 2022-07-22 18:47 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>> This looks like a roundabout way to say xstrfmt().
>
> Yes, I can fix this and others while I'm at it, but a lot of things like
> that in this code are funny uses of APIs that we could improve.
>
> I think it's probably best to just leave these for now.
Agreed. We could instead have a separate series to fix API usage
before these and then build leak-plugging on top, or the other way
around, and in general "clean then plug" would make it easier to
review the plugging patches (simply because it would be working on
clean code, not code that misuses the API in strange ways), but it
is too late now. Lets make sure we do not forget to revisit the API
misuse but lets avoid mixing it into the series.
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule()
2022-07-22 18:47 ` Junio C Hamano
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
0 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
On Fri, Jul 22 2022, Junio C Hamano wrote:
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>>> This looks like a roundabout way to say xstrfmt().
>>
>> Yes, I can fix this and others while I'm at it, but a lot of things like
>> that in this code are funny uses of APIs that we could improve.
>>
>> I think it's probably best to just leave these for now.
>
> Agreed. We could instead have a separate series to fix API usage
> before these and then build leak-plugging on top, or the other way
> around, and in general "clean then plug" would make it easier to
> review the plugging patches (simply because it would be working on
> clean code, not code that misuses the API in strange ways), but it
> is too late now. Lets make sure we do not forget to revisit the API
> misuse but lets avoid mixing it into the series.
I ended up doing the opposite of what you suggested here, but not
lightly.
When re-rolling the v4 of the leak series I noticed that some of what
was suggested I'd fix (and thanks a lot to you and Glen for the reviews)
was code that was either dead, or should really belong in a "test-tool"
at this point.
So, I could have addressed those by padding the "leak" series with more
digressions, but I felt that just cleanly splitting it into a "prep"
series and "leak fixes" was better, those two are the just-submitted:
https://lore.kernel.org/cover-00.20-00000000000-20220728T161116Z-avarab@gmail.com
https://lore.kernel.org/git/cover-v4-00.17-00000000000-20220728T162442Z-avarab@gmail.com
Sorry if that causes any disruption for you. I noticed that you merged
the v3 into your "jch", but it didn't look anywhere close to "next", so
getting it more right to begin with seemed like a better trade-off.
Thanks!
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-07-21 19:12 ` [PATCH v3 01/26] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
2022-07-21 19:12 ` [PATCH v3 02/26] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:12 ` Ævar Arnfjörð Bjarmason
2022-07-21 21:26 ` Junio C Hamano
2022-07-25 17:07 ` Glen Choo
2022-07-21 19:13 ` [PATCH v3 04/26] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
` (23 subsequent siblings)
26 siblings, 2 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:12 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add "const" to the "struct module_clone_data" that we pass to
clone_submodule(), which makes the ownership clear, and stops us from
clobbering the "clone_data->path".
We still need to add to the "reference" member, which is a "struct
string_list". We could do this by having clone_submodule() create its
own, and copy the contents over, but let's instead pass it as a
separate parameter. The main point of doing this is to make it clear
that e.g. "clone_data->path" always comes from the "argv", there's no
ambiguity about whether we can eventually free() the "struct
string_list".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 38 +++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 29641690c8c..7d5ee6a6261 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1650,20 +1650,22 @@ static char *clone_submodule_sm_gitdir(const char *name)
return sm_gitdir;
}
-static int clone_submodule(struct module_clone_data *clone_data)
+static int clone_submodule(const struct module_clone_data *clone_data,
+ struct string_list *reference)
{
char *p;
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
+ const char *clone_data_path;
if (!is_absolute_path(clone_data->path)) {
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
- clone_data->path = strbuf_detach(&sb, NULL);
+ clone_data_path = strbuf_detach(&sb, NULL);
} else {
- clone_data->path = xstrdup(clone_data->path);
+ clone_data_path = xstrdup(clone_data_path);
}
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
@@ -1674,7 +1676,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
if (safe_create_leading_directories_const(sm_gitdir) < 0)
die(_("could not create directory '%s'"), sm_gitdir);
- prepare_possible_alternates(clone_data->name, &clone_data->reference);
+ prepare_possible_alternates(clone_data->name, reference);
strvec_push(&cp.args, "clone");
strvec_push(&cp.args, "--no-checkout");
@@ -1684,9 +1686,9 @@ static int clone_submodule(struct module_clone_data *clone_data)
strvec_push(&cp.args, "--progress");
if (clone_data->depth && *(clone_data->depth))
strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
- if (clone_data->reference.nr) {
+ if (reference->nr) {
struct string_list_item *item;
- for_each_string_list_item(item, &clone_data->reference)
+ for_each_string_list_item(item, reference)
strvec_pushl(&cp.args, "--reference",
item->string, NULL);
}
@@ -1705,7 +1707,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
strvec_push(&cp.args, "--");
strvec_push(&cp.args, clone_data->url);
- strvec_push(&cp.args, clone_data->path);
+ strvec_push(&cp.args, clone_data_path);
cp.git_cmd = 1;
prepare_submodule_repo_env(&cp.env);
@@ -1713,25 +1715,25 @@ static int clone_submodule(struct module_clone_data *clone_data)
if(run_command(&cp))
die(_("clone of '%s' into submodule path '%s' failed"),
- clone_data->url, clone_data->path);
+ clone_data->url, clone_data_path);
} else {
struct strbuf sb = STRBUF_INIT;
- if (clone_data->require_init && !access(clone_data->path, X_OK) &&
- !is_empty_dir(clone_data->path))
- die(_("directory not empty: '%s'"), clone_data->path);
- if (safe_create_leading_directories_const(clone_data->path) < 0)
- die(_("could not create directory '%s'"), clone_data->path);
+ if (clone_data->require_init && !access(clone_data_path, X_OK) &&
+ !is_empty_dir(clone_data_path))
+ die(_("directory not empty: '%s'"), clone_data_path);
+ if (safe_create_leading_directories_const(clone_data_path) < 0)
+ die(_("could not create directory '%s'"), clone_data_path);
strbuf_addf(&sb, "%s/index", sm_gitdir);
unlink_or_warn(sb.buf);
strbuf_release(&sb);
}
- connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
+ connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
- p = git_pathdup_submodule(clone_data->path, "config");
+ p = git_pathdup_submodule(clone_data_path, "config");
if (!p)
- die(_("could not get submodule directory for '%s'"), clone_data->path);
+ die(_("could not get submodule directory for '%s'"), clone_data_path);
/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
git_config_get_string("submodule.alternateLocation", &sm_alternate);
@@ -1810,7 +1812,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
usage_with_options(git_submodule_helper_usage,
module_clone_options);
- clone_submodule(&clone_data);
+ clone_submodule(&clone_data, &clone_data.reference);
list_objects_filter_release(&filter_options);
return 0;
}
@@ -3088,7 +3090,7 @@ static int add_submodule(const struct add_data *add_data)
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
- if (clone_submodule(&clone_data))
+ if (clone_submodule(&clone_data, &clone_data.reference))
return -1;
prepare_submodule_repo_env(&cp.env);
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
2022-07-21 19:12 ` [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-21 21:26 ` Junio C Hamano
2022-07-25 17:07 ` Glen Choo
1 sibling, 0 replies; 186+ messages in thread
From: Junio C Hamano @ 2022-07-21 21:26 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> -static int clone_submodule(struct module_clone_data *clone_data)
> +static int clone_submodule(const struct module_clone_data *clone_data,
> + struct string_list *reference)
> {
> char *p;
> char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
> char *sm_alternate = NULL, *error_strategy = NULL;
> struct child_process cp = CHILD_PROCESS_INIT;
> + const char *clone_data_path;
>
> if (!is_absolute_path(clone_data->path)) {
> struct strbuf sb = STRBUF_INIT;
>
> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
> - clone_data->path = strbuf_detach(&sb, NULL);
> + clone_data_path = strbuf_detach(&sb, NULL);
OK.
> } else {
> - clone_data->path = xstrdup(clone_data->path);
> + clone_data_path = xstrdup(clone_data_path);
Is the variable we are duplicating by passing it to xstrdup() still
uninitialized at this point? How could the compiler not catch this?
Apparently there is no test coverage on this codepath; all tests
pass when I replace this else clause with BUG().
Let's read on, pretending that you passed clone_data->path to
xstrdup(), for now.
> @@ -1674,7 +1676,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
> if (safe_create_leading_directories_const(sm_gitdir) < 0)
> die(_("could not create directory '%s'"), sm_gitdir);
>
> - prepare_possible_alternates(clone_data->name, &clone_data->reference);
> + prepare_possible_alternates(clone_data->name, reference);
>
> strvec_push(&cp.args, "clone");
> strvec_push(&cp.args, "--no-checkout");
> @@ -1684,9 +1686,9 @@ static int clone_submodule(struct module_clone_data *clone_data)
> strvec_push(&cp.args, "--progress");
> if (clone_data->depth && *(clone_data->depth))
> strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
> - if (clone_data->reference.nr) {
> + if (reference->nr) {
> struct string_list_item *item;
> - for_each_string_list_item(item, &clone_data->reference)
> + for_each_string_list_item(item, reference)
> strvec_pushl(&cp.args, "--reference",
> item->string, NULL);
> }
All the uses of reference (both above, so below) looks OK.
I wonder if we can simply have a separate string list variable in
module_clone() and add_submodule() and remove clone_data.reference
member, which may make the end-result even cleaner, now that we pass
it as a separate parameter anyway.
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
2022-07-21 19:12 ` [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
2022-07-21 21:26 ` Junio C Hamano
@ 2022-07-25 17:07 ` Glen Choo
1 sibling, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-07-25 17:07 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Add "const" to the "struct module_clone_data" that we pass to
> clone_submodule(), which makes the ownership clear, and stops us from
> clobbering the "clone_data->path".
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 38 +++++++++++++++++++------------------
> 1 file changed, 20 insertions(+), 18 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 29641690c8c..7d5ee6a6261 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1650,20 +1650,22 @@ static char *clone_submodule_sm_gitdir(const char *name)
> return sm_gitdir;
> }
>
> -static int clone_submodule(struct module_clone_data *clone_data)
> +static int clone_submodule(const struct module_clone_data *clone_data,
> + struct string_list *reference)
> {
> char *p;
> char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
> char *sm_alternate = NULL, *error_strategy = NULL;
> struct child_process cp = CHILD_PROCESS_INIT;
> + const char *clone_data_path;
>
> if (!is_absolute_path(clone_data->path)) {
> struct strbuf sb = STRBUF_INIT;
>
> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
> - clone_data->path = strbuf_detach(&sb, NULL);
> + clone_data_path = strbuf_detach(&sb, NULL);
> } else {
> - clone_data->path = xstrdup(clone_data->path);
> + clone_data_path = xstrdup(clone_data_path);
> }
>
> if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
Hm, the leak in the preimage comes from the fact that we assign back to
clone_data->path, which is a "const char *" that initially comes from
argv. So we didn't free() it even though it always pointing to
free()-able memory past this point.
So now that we're introducing and assigning to a new variable,
clone_data_path, wouldn't it be simpler to just make it "char *" and
free it (instead of adding a separate "char *to_free" in the next
patch)?
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 04/26] submodule--helper: fix a leak in "clone_submodule"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (2 preceding siblings ...)
2022-07-21 19:12 ` [PATCH v3 03/26] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 21:30 ` Junio C Hamano
2022-07-21 19:13 ` [PATCH v3 05/26] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
` (22 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak of the "clone_data_path" variable that we copy or
derive from the "struct module_clone_data" in clone_submodule(). This
code was refactored in preceding commits, but the leak has been with
us since f8eaa0ba98b (submodule--helper, module_clone: always operate
on absolute paths, 2016-03-31).
For the "else" case we don't need to xstrdup() the "clone_data->path",
and we don't need to free our own "clone_data_path".
In the case of the module_clone() caller it's from "argv", and doesn't
need to be free'd, and in the case of the add_submodule() caller we
get a pointer to "sm_path", which doesn't need to be directly free'd
either.
Fixing this leak makes several tests pass, so let's mark them as
passing with TEST_PASSES_SANITIZE_LEAK=true.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 ++++--
t/t1500-rev-parse.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 ++
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 ++
6 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7d5ee6a6261..1ddce8e19c1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1658,14 +1658,15 @@ static int clone_submodule(const struct module_clone_data *clone_data,
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
const char *clone_data_path;
+ char *to_free = NULL;
if (!is_absolute_path(clone_data->path)) {
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
- clone_data_path = strbuf_detach(&sb, NULL);
+ clone_data_path = to_free = strbuf_detach(&sb, NULL);
} else {
- clone_data_path = xstrdup(clone_data_path);
+ clone_data_path = clone_data->path;
}
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
@@ -1750,6 +1751,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
free(sm_gitdir);
free(p);
+ free(to_free);
return 0;
}
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 1c2df08333b..0e13bcb4ebb 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -4,6 +4,7 @@ test_description='test git rev-parse'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_one () {
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 3153a0d8910..12e67e187ef 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -8,6 +8,7 @@ test_description='git rev-list involving submodules that this repo has'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
index f2e7df59cf2..3269298197c 100755
--- a/t/t7414-submodule-mistakes.sh
+++ b/t/t7414-submodule-mistakes.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='handling of common mistakes people may make with submodules'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create embedded repository' '
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index 3fcb44767f5..f5426a8e589 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -2,6 +2,7 @@
test_description='git status for submodule'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_create_repo_with_commit () {
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
index ed2653d46fe..92462a22374 100755
--- a/t/t7507-commit-verbose.sh
+++ b/t/t7507-commit-verbose.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='verbose commit template'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
write_script "check-for-diff" <<\EOF &&
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 04/26] submodule--helper: fix a leak in "clone_submodule"
2022-07-21 19:13 ` [PATCH v3 04/26] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
@ 2022-07-21 21:30 ` Junio C Hamano
2022-07-22 11:30 ` Ævar Arnfjörð Bjarmason
0 siblings, 1 reply; 186+ messages in thread
From: Junio C Hamano @ 2022-07-21 21:30 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 7d5ee6a6261..1ddce8e19c1 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1658,14 +1658,15 @@ static int clone_submodule(const struct module_clone_data *clone_data,
> char *sm_alternate = NULL, *error_strategy = NULL;
> struct child_process cp = CHILD_PROCESS_INIT;
> const char *clone_data_path;
> + char *to_free = NULL;
>
> if (!is_absolute_path(clone_data->path)) {
> struct strbuf sb = STRBUF_INIT;
>
> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
> - clone_data_path = strbuf_detach(&sb, NULL);
> + clone_data_path = to_free = strbuf_detach(&sb, NULL);
> } else {
> - clone_data_path = xstrdup(clone_data_path);
> + clone_data_path = clone_data->path;
> }
Heh, the bug I noticed in the previous step is silently fixed here.
This is why I do not trust a series that is artificially split into
steps and sent out without self reviewing or even compiling them.
Forces reviewers to do more work wasting their time reviewing and
finding bugs that ends up not mattering because that weren't even
something the author intended to write in the end.
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v3 04/26] submodule--helper: fix a leak in "clone_submodule"
2022-07-21 21:30 ` Junio C Hamano
@ 2022-07-22 11:30 ` Ævar Arnfjörð Bjarmason
0 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-22 11:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
On Thu, Jul 21 2022, Junio C Hamano wrote:
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index 7d5ee6a6261..1ddce8e19c1 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -1658,14 +1658,15 @@ static int clone_submodule(const struct module_clone_data *clone_data,
>> char *sm_alternate = NULL, *error_strategy = NULL;
>> struct child_process cp = CHILD_PROCESS_INIT;
>> const char *clone_data_path;
>> + char *to_free = NULL;
>>
>> if (!is_absolute_path(clone_data->path)) {
>> struct strbuf sb = STRBUF_INIT;
>>
>> strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
>> - clone_data_path = strbuf_detach(&sb, NULL);
>> + clone_data_path = to_free = strbuf_detach(&sb, NULL);
>> } else {
>> - clone_data_path = xstrdup(clone_data_path);
>> + clone_data_path = clone_data->path;
>> }
>
> Heh, the bug I noticed in the previous step is silently fixed here.
>
> This is why I do not trust a series that is artificially split into
> steps and sent out without self reviewing or even compiling them.
Sorry for that mistake, will fix it in a re-roll. It was a result of
dumb search-replacing.
But FWIW I did (and do generally) test my changes with "git rebase -i -x
make..." before sending them out.
But as you note this doesn't seem to have test coverage, and which gcc
yells at me about this, clang (13.0.1-3+b2) does not.
I generally test my changes with both gcc & clang before sending them
out, but usually only use clang for the incremental compiling, I'll
switch back to gcc...
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 05/26] submodule--helper: fix trivial get_default_remote_submodule() leak
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (3 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 04/26] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 06/26] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
` (21 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in 1012a5cbc3f (submodule--helper
run-update-procedure: learn --remote, 2022-03-04), we need to free()
the xstrdup()'d string. This gets e.g. t/t7419-submodule-set-branch.sh
closer to passing under SANITIZE=leak.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 1ddce8e19c1..73ac1fcbb9c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2486,6 +2486,8 @@ static int update_submodule(struct update_data *update_data)
const char *branch = remote_submodule_branch(update_data->sm_path);
char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ free(remote_name);
+
if (!update_data->nofetch) {
if (fetch_in_submodule(update_data->sm_path, update_data->depth,
0, NULL))
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 06/26] submodule--helper: fix most "struct pathspec" memory leaks
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (4 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 05/26] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 21:37 ` Junio C Hamano
2022-07-21 19:13 ` [PATCH v3 07/26] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
` (20 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call clear_pathspec() at the end of various functions that work with
and allocate a "struct pathspec".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 84 +++++++++++++++++++++++++------------
1 file changed, 58 insertions(+), 26 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 73ac1fcbb9c..a60dc6af178 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -269,7 +269,7 @@ static char *get_up_path(const char *path)
static int module_list(int argc, const char **argv, const char *prefix)
{
int i;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_list_options[] = {
@@ -278,6 +278,7 @@ static int module_list(int argc, const char **argv, const char *prefix)
N_("alternative anchor for relative paths")),
OPT_END()
};
+ int ret = 1;
const char *const git_submodule_helper_usage[] = {
N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
@@ -288,7 +289,7 @@ static int module_list(int argc, const char **argv, const char *prefix)
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
for (i = 0; i < list.nr; i++) {
const struct cache_entry *ce = list.entries[i];
@@ -302,7 +303,10 @@ static int module_list(int argc, const char **argv, const char *prefix)
fprintf(stdout, "%s\n", ce->name);
}
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static void for_each_listed_submodule(const struct module_list *list,
@@ -427,7 +431,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
static int module_foreach(int argc, const char **argv, const char *prefix)
{
struct foreach_cb info = FOREACH_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_foreach_options[] = {
@@ -441,12 +445,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_foreach_options,
git_submodule_helper_usage, 0);
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.argc = argc;
info.argv = argv;
@@ -454,7 +459,10 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int starts_with_dot_slash(const char *const path)
@@ -562,7 +570,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_init(int argc, const char **argv, const char *prefix)
{
struct init_cb info = INIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
@@ -575,12 +583,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
N_("git submodule init [<options>] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_init_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
/*
* If there are no path args and submodule.active is set then,
@@ -595,7 +604,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, init_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct status_cb {
@@ -740,7 +752,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
static int module_status(int argc, const char **argv, const char *prefix)
{
struct status_cb info = STATUS_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
@@ -755,12 +767,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_status_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -768,7 +781,10 @@ static int module_status(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, status_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int module_name(int argc, const char **argv, const char *prefix)
@@ -1326,10 +1342,11 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_sync(int argc, const char **argv, const char *prefix)
{
struct sync_cb info = SYNC_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int recursive = 0;
+ int ret = 1;
struct option module_sync_options[] = {
OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
@@ -1347,7 +1364,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1357,7 +1374,10 @@ static int module_sync(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, sync_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct deinit_cb {
@@ -1464,7 +1484,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
static int module_deinit(int argc, const char **argv, const char *prefix)
{
struct deinit_cb info = DEINIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int force = 0;
@@ -1481,6 +1501,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_deinit_options,
git_submodule_helper_usage, 0);
@@ -1495,7 +1516,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
die(_("Use '--all' if you really want to deinitialize all submodules"));
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1505,7 +1526,10 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, deinit_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_clone_data {
@@ -2577,7 +2601,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2656,8 +2680,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
opt.update_strategy.type = opt.update_default;
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
- list_objects_filter_release(&filter_options);
- return 1;
+ ret = 1;
+ goto cleanup;
}
if (pathspec.nr)
@@ -2668,8 +2692,10 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0)
- return 1;
+ &pathspec, &list) < 0) {
+ ret = 1;
+ goto cleanup;
+ }
/*
* If there are no path args and submodule.active is set then,
@@ -2686,7 +2712,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
}
ret = update_submodules(&opt);
+cleanup:
list_objects_filter_release(&filter_options);
+ clear_pathspec(&pathspec);
return ret;
}
@@ -2770,9 +2798,10 @@ static int push_check(int argc, const char **argv, const char *prefix)
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
{
int i;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
+ int ret = 1;
struct option embed_gitdir_options[] = {
OPT_STRING(0, "prefix", &prefix,
@@ -2792,12 +2821,15 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
for (i = 0; i < list.nr; i++)
absorb_git_dir_into_superproject(list.entries[i]->name, flags);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int is_active(int argc, const char **argv, const char *prefix)
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 06/26] submodule--helper: fix most "struct pathspec" memory leaks
2022-07-21 19:13 ` [PATCH v3 06/26] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-07-21 21:37 ` Junio C Hamano
0 siblings, 0 replies; 186+ messages in thread
From: Junio C Hamano @ 2022-07-21 21:37 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Call clear_pathspec() at the end of various functions that work with
> and allocate a "struct pathspec".
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 84 +++++++++++++++++++++++++------------
> 1 file changed, 58 insertions(+), 26 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 73ac1fcbb9c..a60dc6af178 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -269,7 +269,7 @@ static char *get_up_path(const char *path)
> static int module_list(int argc, const char **argv, const char *prefix)
> {
> int i;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct module_list list = MODULE_LIST_INIT;
>
> struct option module_list_options[] = {
> @@ -278,6 +278,7 @@ static int module_list(int argc, const char **argv, const char *prefix)
> N_("alternative anchor for relative paths")),
> OPT_END()
> };
> + int ret = 1;
Move this way above, perhaps next to where "int i;" is declared, or
replace the blank before where module_list_options[] is declared
with this line.
The same comment applies to changes to module_foreach() and
status_submodule_cb() in this patch. The change to
absorb_git_dirs() gets it right.
Thanks.
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 07/26] submodule--helper: "struct pathspec" memory leak in module_update()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (5 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 06/26] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 08/26] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
` (19 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
The module_update() function calls module_list_compute() twice, which
in turn will reset the "struct pathspec" passed to it. Let's instead
track two of them, and clear them both.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a60dc6af178..f317236f016 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2602,6 +2602,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec = { 0 };
+ struct pathspec pathspec2 = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2692,7 +2693,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0) {
+ &pathspec2, &list) < 0) {
ret = 1;
goto cleanup;
}
@@ -2715,6 +2716,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
cleanup:
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
+ clear_pathspec(&pathspec2);
return ret;
}
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 08/26] submodule--helper: don't leak {run,capture}_command() cp.dir argument
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (6 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 07/26] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 09/26] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
` (18 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24) and 3c3558f0953 (submodule--helper: run
update using child process struct, 2022-03-15) by not allocating
memory in the first place.
The "dir" member of "struct child_process" will not be modified by
that API, and it's declared to be "const char *". So let's not
needlessly duplicate these strings.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f317236f016..fb3102f024f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2194,7 +2194,7 @@ static int is_tip_reachable(const char *path, struct object_id *oid)
char *hex = oid_to_hex(oid);
cp.git_cmd = 1;
- cp.dir = xstrdup(path);
+ cp.dir = path;
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
@@ -2212,7 +2212,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
- cp.dir = xstrdup(module_path);
+ cp.dir = module_path;
strvec_push(&cp.args, "fetch");
if (quiet)
@@ -2267,7 +2267,7 @@ static int run_update_command(struct update_data *ud, int subforce)
}
strvec_push(&cp.args, oid);
- cp.dir = xstrdup(ud->sm_path);
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
if (run_command(&cp)) {
switch (ud->update_strategy.type) {
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 09/26] submodule--helper: add "const" to copy of "update_data"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (7 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 08/26] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 10/26] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
` (17 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
From: Glen Choo <chooglen@google.com>
Add a "const" to the copy of "struct update_data" that's tracked by
the "struct submodule_update_clone", as it neither owns nor modifies
it.
Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fb3102f024f..3223c93f91a 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1889,7 +1889,7 @@ struct submodule_update_clone {
int current;
/* configuration parameters which are passed on to the children */
- struct update_data *update_data;
+ const struct update_data *update_data;
/* to be consumed by update_submodule() */
struct update_clone_data *update_clone;
@@ -1974,7 +1974,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
const char *update_string;
enum submodule_update_type update_type;
char *key;
- struct update_data *ud = suc->update_data;
+ const struct update_data *ud = suc->update_data;
char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
struct strbuf sb = STRBUF_INIT;
int needs_cloning = 0;
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 10/26] submodule--helper: add and use *_release() functions
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (8 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 09/26] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 11/26] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
` (16 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add release functions for "struct module_list", "struct
submodule_update_clone" and "struct update_data".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 29 ++++++++++++++++++++++++++++-
t/t6134-pathspec-in-submodule.sh | 1 +
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3223c93f91a..21b3abb7b40 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -182,6 +182,11 @@ struct module_list {
};
#define MODULE_LIST_INIT { 0 }
+static void module_list_release(struct module_list *ml)
+{
+ free(ml->entries);
+}
+
static int module_list_compute(int argc, const char **argv,
const char *prefix,
struct pathspec *pathspec,
@@ -243,7 +248,7 @@ static void module_list_active(struct module_list *list)
active_modules.entries[active_modules.nr++] = ce;
}
- free(list->entries);
+ module_list_release(list);
*list = active_modules;
}
@@ -305,6 +310,7 @@ static int module_list(int argc, const char **argv, const char *prefix)
}
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -461,6 +467,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -606,6 +613,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -783,6 +791,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1376,6 +1385,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1528,6 +1538,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1904,6 +1915,12 @@ struct submodule_update_clone {
};
#define SUBMODULE_UPDATE_CLONE_INIT { 0 }
+static void submodule_update_clone_release(struct submodule_update_clone *suc)
+{
+ free(suc->update_clone);
+ free(suc->failed_clones);
+}
+
struct update_data {
const char *prefix;
const char *displaypath;
@@ -1942,6 +1959,11 @@ struct update_data {
.max_jobs = 1, \
}
+static void update_data_release(struct update_data *ud)
+{
+ module_list_release(&ud->list);
+}
+
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
struct strbuf *out, const char *displaypath)
{
@@ -2595,6 +2617,7 @@ static int update_submodules(struct update_data *update_data)
}
cleanup:
+ submodule_update_clone_release(&suc);
string_list_clear(&update_data->references, 0);
return res;
}
@@ -2694,6 +2717,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
if (module_list_compute(argc, argv, opt.prefix,
&pathspec2, &list) < 0) {
+ module_list_release(&list);
ret = 1;
goto cleanup;
}
@@ -2710,10 +2734,12 @@ static int module_update(int argc, const char **argv, const char *prefix)
info.flags |= OPT_QUIET;
for_each_listed_submodule(&list, init_submodule_cb, &info);
+ module_list_release(&list);
}
ret = update_submodules(&opt);
cleanup:
+ update_data_release(&opt);
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
clear_pathspec(&pathspec2);
@@ -2831,6 +2857,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
clear_pathspec(&pathspec);
+ module_list_release(&list);
return ret;
}
diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh
index 0f1cb49cedc..3a241f259de 100755
--- a/t/t6134-pathspec-in-submodule.sh
+++ b/t/t6134-pathspec-in-submodule.sh
@@ -2,6 +2,7 @@
test_description='test case exclude pathspec'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a submodule' '
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 11/26] submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (9 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 10/26] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-25 23:15 ` Glen Choo
2022-07-21 19:13 ` [PATCH v3 12/26] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
` (15 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
From: Glen Choo <chooglen@google.com>
Refactor code added in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13) so that "errmsg" and
"errmsg_str" are folded into one. The distinction between the empty
string and NULL is something that's tested for by
e.g. "t/t7401-submodule-summary.sh".
This is in preparation for fixing a memory leak the "struct strbuf" in
the pre-image.
Let's also pass a "const char *" to print_submodule_summary(), as it
should not be modifying the "errmsg".
Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 21b3abb7b40..f794d2b588b 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -866,7 +866,7 @@ static char *verify_submodule_committish(const char *sm_path,
return strbuf_detach(&result, NULL);
}
-static void print_submodule_summary(struct summary_cb *info, char *errmsg,
+static void print_submodule_summary(struct summary_cb *info, const char *errmsg,
int total_commits, const char *displaypath,
const char *src_abbrev, const char *dst_abbrev,
struct module_cb *p)
@@ -924,7 +924,7 @@ static void generate_submodule_summary(struct summary_cb *info,
{
char *displaypath, *src_abbrev = NULL, *dst_abbrev;
int missing_src = 0, missing_dst = 0;
- char *errmsg = NULL;
+ struct strbuf errmsg = STRBUF_INIT;
int total_commits = -1;
if (!info->cached && oideq(&p->oid_dst, null_oid())) {
@@ -1024,23 +1024,21 @@ static void generate_submodule_summary(struct summary_cb *info,
* submodule, i.e., deleted or changed to blob
*/
if (S_ISGITLINK(p->mod_dst)) {
- struct strbuf errmsg_str = STRBUF_INIT;
if (missing_src && missing_dst) {
- strbuf_addf(&errmsg_str, " Warn: %s doesn't contain commits %s and %s\n",
+ strbuf_addf(&errmsg, " Warn: %s doesn't contain commits %s and %s\n",
displaypath, oid_to_hex(&p->oid_src),
oid_to_hex(&p->oid_dst));
} else {
- strbuf_addf(&errmsg_str, " Warn: %s doesn't contain commit %s\n",
+ strbuf_addf(&errmsg, " Warn: %s doesn't contain commit %s\n",
displaypath, missing_src ?
oid_to_hex(&p->oid_src) :
oid_to_hex(&p->oid_dst));
}
- errmsg = strbuf_detach(&errmsg_str, NULL);
}
}
- print_submodule_summary(info, errmsg, total_commits,
- displaypath, src_abbrev,
+ print_submodule_summary(info, errmsg.len ? errmsg.buf : NULL,
+ total_commits, displaypath, src_abbrev,
dst_abbrev, p);
free(displaypath);
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 11/26] submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
2022-07-21 19:13 ` [PATCH v3 11/26] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
@ 2022-07-25 23:15 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-07-25 23:15 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> From: Glen Choo <chooglen@google.com>
>
> Refactor code added in e83e3333b57 (submodule: port submodule
> subcommand 'summary' from shell to C, 2020-08-13) so that "errmsg" and
> "errmsg_str" are folded into one. The distinction between the empty
> string and NULL is something that's tested for by
> e.g. "t/t7401-submodule-summary.sh".
>
> This is in preparation for fixing a memory leak the "struct strbuf" in
> the pre-image.
>
> Let's also pass a "const char *" to print_submodule_summary(), as it
> should not be modifying the "errmsg".
>
> Signed-off-by: Glen Choo <chooglen@google.com>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 14 ++++++--------
> 1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 21b3abb7b40..f794d2b588b 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -866,7 +866,7 @@ static char *verify_submodule_committish(const char *sm_path,
> return strbuf_detach(&result, NULL);
> }
>
> -static void print_submodule_summary(struct summary_cb *info, char *errmsg,
> +static void print_submodule_summary(struct summary_cb *info, const char *errmsg,
> int total_commits, const char *displaypath,
> const char *src_abbrev, const char *dst_abbrev,
> struct module_cb *p)
> @@ -924,7 +924,7 @@ static void generate_submodule_summary(struct summary_cb *info,
> {
> char *displaypath, *src_abbrev = NULL, *dst_abbrev;
> int missing_src = 0, missing_dst = 0;
> - char *errmsg = NULL;
> + struct strbuf errmsg = STRBUF_INIT;
> int total_commits = -1;
>
> if (!info->cached && oideq(&p->oid_dst, null_oid())) {
> @@ -1024,23 +1024,21 @@ static void generate_submodule_summary(struct summary_cb *info,
> * submodule, i.e., deleted or changed to blob
> */
> if (S_ISGITLINK(p->mod_dst)) {
> - struct strbuf errmsg_str = STRBUF_INIT;
> if (missing_src && missing_dst) {
> - strbuf_addf(&errmsg_str, " Warn: %s doesn't contain commits %s and %s\n",
> + strbuf_addf(&errmsg, " Warn: %s doesn't contain commits %s and %s\n",
> displaypath, oid_to_hex(&p->oid_src),
> oid_to_hex(&p->oid_dst));
> } else {
> - strbuf_addf(&errmsg_str, " Warn: %s doesn't contain commit %s\n",
> + strbuf_addf(&errmsg, " Warn: %s doesn't contain commit %s\n",
> displaypath, missing_src ?
> oid_to_hex(&p->oid_src) :
> oid_to_hex(&p->oid_dst));
> }
> - errmsg = strbuf_detach(&errmsg_str, NULL);
> }
> }
>
> - print_submodule_summary(info, errmsg, total_commits,
> - displaypath, src_abbrev,
> + print_submodule_summary(info, errmsg.len ? errmsg.buf : NULL,
> + total_commits, displaypath, src_abbrev,
> dst_abbrev, p);
>
> free(displaypath);
Ah, this is mostly the same as what I sent out, but with the length
check in the same function (instead of in print_submodule_summary()).
This makes it easier to tell that the caller is still doing the same
thing.
Looks good.
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 12/26] submodule--helper: fix "errmsg_str" memory leak
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (10 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 11/26] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 13/26] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
` (14 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak introduced in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13), we sometimes append
to the "errmsg", and need to free the "struct strbuf".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f794d2b588b..ad11ff20022 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1044,6 +1044,7 @@ static void generate_submodule_summary(struct summary_cb *info,
free(displaypath);
free(src_abbrev);
free(dst_abbrev);
+ strbuf_release(&errmsg);
}
static void prepare_submodule_summary(struct summary_cb *info,
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 13/26] submodule--helper: fix "sm_path" and other "module_cb_list" leaks
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (11 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 12/26] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 14/26] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
` (13 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix leaks in "struct module_cb_list" and the "struct module_cb" which
it contains, these fixes leaks in e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).
The "sm_path" should always have been a "char *", not a "const
char *", we always create it with xstrdup().
We can't mark any tests passing passing with SANITIZE=leak using
"TEST_PASSES_SANITIZE_LEAK=true" as a result of this change, but
"t7401-submodule-summary.sh" gets closer to passing as a result of
this change.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ad11ff20022..a5492c6d89a 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -820,16 +820,34 @@ struct module_cb {
struct object_id oid_src;
struct object_id oid_dst;
char status;
- const char *sm_path;
+ char *sm_path;
};
#define MODULE_CB_INIT { 0 }
+static void module_cb_release(struct module_cb *mcb)
+{
+ free(mcb->sm_path);
+}
+
struct module_cb_list {
struct module_cb **entries;
int alloc, nr;
};
#define MODULE_CB_LIST_INIT { 0 }
+static void module_cb_list_release(struct module_cb_list *mcbl)
+{
+ int i;
+
+ for (i = 0; i < mcbl->nr; i++) {
+ struct module_cb *mcb = mcbl->entries[i];
+
+ module_cb_release(mcb);
+ free(mcb);
+ }
+ free(mcbl->entries);
+}
+
struct summary_cb {
int argc;
const char **argv;
@@ -1172,6 +1190,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
cleanup:
strvec_clear(&diff_args);
release_revisions(&rev);
+ module_cb_list_release(&list);
return ret;
}
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 14/26] submodule--helper: fix a leak with repo_clear()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (12 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 13/26] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 15/26] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
` (12 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call repo_clear() in ensure_core_worktree() to free the "struct
repository". Fixes a leak that's been here since
74d4731da1f (submodule--helper: replace connect-gitdir-workingtree by
ensure-core-worktree, 2018-08-13).
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a5492c6d89a..a3de17754fd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2458,6 +2458,7 @@ static void ensure_core_worktree(const char *path)
free(abs_path);
strbuf_release(&sb);
}
+ repo_clear(&subrepo);
}
static const char *submodule_update_type_to_label(enum submodule_update_type type)
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 15/26] submodule--helper: fix a memory leak in get_default_remote_submodule()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (13 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 14/26] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 16/26] submodule--helper: fix "reference" leak is "module_clone_data" Ævar Arnfjörð Bjarmason
` (11 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in the get_default_remote_submodule() function added
in a77c3fcb5ec (submodule--helper: get remote names from any
repository, 2022-03-04), we need to repo_clear() the submodule we
initialize.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a3de17754fd..fe490c8d44d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -62,9 +62,13 @@ static char *repo_get_default_remote(struct repository *repo)
static char *get_default_remote_submodule(const char *module_path)
{
struct repository subrepo;
+ char *ret;
repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
- return repo_get_default_remote(&subrepo);
+ ret = repo_get_default_remote(&subrepo);
+ repo_clear(&subrepo);
+
+ return ret;
}
static char *get_default_remote(void)
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 16/26] submodule--helper: fix "reference" leak is "module_clone_data"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (14 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 15/26] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 17/26] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
` (10 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix leaks in the "reference" member of "struct module_clone_data" that
have been with us since 31224cbdc72 (clone: recursive and reference
option triggers submodule alternates, 2016-08-17) and
8c8195e9c3e (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).
To fix this create a a module_clone_data_release() function to go with
the MODULE_CLONE_DATA_INIT added in a98b02c1128 (submodule--helper:
refactor module_clone(), 2021-07-10). We only need to add it to
add_submodule() to fix the leak, but let's add it to module_clone() as
well for consistency.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fe490c8d44d..80c1c1d4918 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1584,6 +1584,11 @@ struct module_clone_data {
.single_branch = -1, \
}
+static void module_clone_data_release(struct module_clone_data *cd)
+{
+ string_list_clear(&cd->reference, 1);
+}
+
struct submodule_alternate_setup {
const char *submodule_name;
enum SUBMODULE_ALTERNATE_ERROR_MODE {
@@ -1636,7 +1641,9 @@ static int add_possible_reference_from_superproject(
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
- string_list_append(sas->reference, xstrdup(sb.buf));
+ char *p = strbuf_detach(&sb, NULL);
+
+ string_list_append(sas->reference, p)->util = p;
free(sm_alternate);
} else {
switch (sas->error_mode) {
@@ -1873,6 +1880,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
clone_submodule(&clone_data, &clone_data.reference);
list_objects_filter_release(&filter_options);
+ module_clone_data_release(&clone_data);
return 0;
}
@@ -3117,6 +3125,7 @@ static int add_submodule(const struct add_data *add_data)
{
char *submod_gitdir_path;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
+ int ret = -1;
/* perhaps the path already exists and is already a git repo, else clone it */
if (is_directory(add_data->sm_path)) {
@@ -3171,15 +3180,17 @@ static int add_submodule(const struct add_data *add_data)
clone_data.url = add_data->realrepo;
clone_data.quiet = add_data->quiet;
clone_data.progress = add_data->progress;
- if (add_data->reference_path)
- string_list_append(&clone_data.reference,
- xstrdup(add_data->reference_path));
+ if (add_data->reference_path) {
+ char *p = xstrdup(add_data->reference_path);
+
+ string_list_append(&clone_data.reference, p)->util = p;
+ }
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
if (clone_submodule(&clone_data, &clone_data.reference))
- return -1;
+ goto cleanup;
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -3198,7 +3209,10 @@ static int add_submodule(const struct add_data *add_data)
if (run_command(&cp))
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
}
- return 0;
+ ret = 0;
+cleanup:
+ module_clone_data_release(&clone_data);
+ return ret;
}
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 17/26] submodule--helper: fix obscure leak in module_add()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (15 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 16/26] submodule--helper: fix "reference" leak is "module_clone_data" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 21:45 ` Junio C Hamano
2022-07-21 19:13 ` [PATCH v3 18/26] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
` (9 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix an obscure leak in module_add()< if the "git add" command we were
piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
introduced in a6226fd772b (submodule--helper: convert the bulk of
cmd_add() to C, 2021-08-10).
In fixing it move to a "goto cleanup" pattern, and since we need to
introduce a "ret" variable to do that let's also get rid of the
intermediate "exit_code" variable. The initialization to "-1" in
a6226fd772b has always been redundant, we'd only use the "exit_code"
value after assigning the return value of pipe_command() to it.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 80c1c1d4918..04b5141c0f9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3352,6 +3352,8 @@ static int module_add(int argc, const char **argv, const char *prefix)
int force = 0, quiet = 0, progress = 0, dissociate = 0;
struct add_data add_data = ADD_DATA_INIT;
char *to_free = NULL;
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 1;
struct option options[] = {
OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
@@ -3423,20 +3425,16 @@ static int module_add(int argc, const char **argv, const char *prefix)
die_on_repo_without_commits(add_data.sm_path);
if (!force) {
- int exit_code = -1;
- struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdout = 1;
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
"--no-warn-embedded-repo", add_data.sm_path, NULL);
- if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+ if ((ret = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
strbuf_complete_line(&sb);
fputs(sb.buf, stderr);
- free(add_data.sm_path);
- return exit_code;
+ goto cleanup;
}
- strbuf_release(&sb);
}
if(!add_data.sm_name)
@@ -3451,15 +3449,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
add_data.progress = !!progress;
add_data.dissociate = !!dissociate;
- if (add_submodule(&add_data)) {
- free(add_data.sm_path);
- return 1;
- }
+ if (add_submodule(&add_data))
+ goto cleanup;
configure_added_submodule(&add_data);
+
+ ret = 0;
+cleanup:
free(add_data.sm_path);
free(to_free);
+ strbuf_release(&sb);
- return 0;
+ return ret;
}
#define SUPPORT_SUPER_PREFIX (1<<0)
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 17/26] submodule--helper: fix obscure leak in module_add()
2022-07-21 19:13 ` [PATCH v3 17/26] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
@ 2022-07-21 21:45 ` Junio C Hamano
0 siblings, 0 replies; 186+ messages in thread
From: Junio C Hamano @ 2022-07-21 21:45 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Fix an obscure leak in module_add()< if the "git add" command we were
"<" -> "," perhaps? I dunno.
> piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
> introduced in a6226fd772b (submodule--helper: convert the bulk of
> cmd_add() to C, 2021-08-10).
>
> In fixing it move to a "goto cleanup" pattern, and since we need to
> introduce a "ret" variable to do that let's also get rid of the
> intermediate "exit_code" variable. The initialization to "-1" in
> a6226fd772b has always been redundant, we'd only use the "exit_code"
> value after assigning the return value of pipe_command() to it.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 22 +++++++++++-----------
> 1 file changed, 11 insertions(+), 11 deletions(-)
The patch looks good, especially with removal of "exit_code" it is
very clear what is going on and how errors are handled.
Nicely done.
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 18/26] submodule--helper: fix a leak in module_add()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (16 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 17/26] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 19/26] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
` (8 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in module_path(), since a6226fd772b (submodule--helper:
convert the bulk of cmd_add() to C, 2021-08-10), we've been freeing
add_data.sm_path, but in this case we clobbered it, and didn't free
the value we clobbered.
This makes test 28 of "t/t7400-submodule-basic.sh" ("submodule add in
subdirectory") pass when we're compiled with SANITIZE=leak..
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 04b5141c0f9..0fb720d3a16 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3395,8 +3395,11 @@ static int module_add(int argc, const char **argv, const char *prefix)
else
add_data.sm_path = xstrdup(argv[1]);
- if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
- add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
+ char *sm_path = add_data.sm_path;
+ add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
+ free(sm_path);
+ }
if (starts_with_dot_dot_slash(add_data.repo) ||
starts_with_dot_slash(add_data.repo)) {
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 19/26] submodule--helper: fix a memory leak in print_status()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (17 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 18/26] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 20/26] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
` (7 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in print_status(), the compute_rev_name() function
implemented in this file will return a strbuf_detach()'d value, or
NULL.
This leak has existed since this code was added in
a9f8a37584a (submodule: port submodule subcommand 'status' from shell
to C, 2017-10-06), but in 0b5e2ea7cf3 (submodule--helper: don't print
null in 'submodule status', 2018-04-18) we added a "const"
intermediate variable for the return value, that "const" should be
removed.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 0fb720d3a16..4decbdcdc5c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -637,10 +637,11 @@ static void print_status(unsigned int flags, char state, const char *path,
printf("%c%s %s", state, oid_to_hex(oid), displaypath);
if (state == ' ' || state == '+') {
- const char *name = compute_rev_name(path, oid_to_hex(oid));
+ char *name = compute_rev_name(path, oid_to_hex(oid));
if (name)
printf(" (%s)", name);
+ free(name);
}
printf("\n");
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 20/26] submodule--helper: free some "displaypath" in "struct update_data"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (18 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 19/26] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 21/26] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
` (6 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Make the update_data_release() function free "displaypath" member when
appropriate. The "displaypath" member is always ours, the "const" on
the "char *" was wrong to begin with.
This leaves a leak of "displaypath" in update_submodule(), which as
we'll see in subsequent commits is harder to deal with than this
trivial fix.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
t/t2403-worktree-move.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4decbdcdc5c..378f85e37fa 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1954,7 +1954,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
struct update_data {
const char *prefix;
- const char *displaypath;
+ char *displaypath;
enum submodule_update_type update_default;
struct object_id suboid;
struct string_list references;
@@ -1992,6 +1992,7 @@ struct update_data {
static void update_data_release(struct update_data *ud)
{
+ free(ud->displaypath);
module_list_release(&ud->list);
}
diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh
index a4e1a178e0a..1168e9f9982 100755
--- a/t/t2403-worktree-move.sh
+++ b/t/t2403-worktree-move.sh
@@ -2,6 +2,7 @@
test_description='test git worktree move, remove, lock and unlock'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 1cfa150768d..2859695c6d2 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -6,6 +6,7 @@ This test verifies that `git submodue absorbgitdirs` moves a submodules git
directory into the superproject.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 21/26] submodule--helper: rename "int res" to "int ret"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (19 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 20/26] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 22/26] submodule--helper: add skeleton "goto cleanup" to update_submodule() Ævar Arnfjörð Bjarmason
` (5 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Rename the "res" variable added in b3c5f5cb048 (submodule: move core
cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
in the rest of this file. Subsequent commits will change this code to
a "goto cleanup" pattern, let's have the post image look consistent
with the rest.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 378f85e37fa..94eec34c595 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2588,7 +2588,7 @@ static int update_submodule(struct update_data *update_data)
if (update_data->recursive) {
struct child_process cp = CHILD_PROCESS_INIT;
struct update_data next = *update_data;
- int res;
+ int ret;
next.prefix = NULL;
oidcpy(&next.oid, null_oid());
@@ -2600,14 +2600,14 @@ static int update_submodule(struct update_data *update_data)
update_data_to_args(&next, &cp.args);
/* die() if child process die()'d */
- res = run_command(&cp);
- if (!res)
+ ret = run_command(&cp);
+ if (!ret)
return 0;
die_message(_("Failed to recurse into submodule path '%s'"),
update_data->displaypath);
- if (res == 128)
- exit(res);
- else if (res)
+ if (ret == 128)
+ exit(ret);
+ else if (ret)
return 1;
}
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 22/26] submodule--helper: add skeleton "goto cleanup" to update_submodule()
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (20 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 21/26] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 23/26] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
` (4 subsequent siblings)
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add a skeleton "goto cleanup" pattern to update_submodule(), rather
than having branches in it "return". This is in preparation for doing
something useful with the "cleanup" label, but for now we're using it
as the equivalent of a "done" label.
The "exit()" branch is not handled yet, and neither is the exit() that
run_update_procedure() might invoke. That'll be handled in a
subsequent commit.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 94eec34c595..790f0ccb82e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2545,6 +2545,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
static int update_submodule(struct update_data *update_data)
{
+ int ret = 1;
+
ensure_core_worktree(update_data->sm_path);
update_data->displaypath = get_submodule_displaypath(
@@ -2581,14 +2583,14 @@ static int update_submodule(struct update_data *update_data)
free(remote_ref);
}
- if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
+ if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
if (run_update_procedure(update_data))
- return 1;
+ goto cleanup;
+ }
if (update_data->recursive) {
struct child_process cp = CHILD_PROCESS_INIT;
struct update_data next = *update_data;
- int ret;
next.prefix = NULL;
oidcpy(&next.oid, null_oid());
@@ -2602,16 +2604,20 @@ static int update_submodule(struct update_data *update_data)
/* die() if child process die()'d */
ret = run_command(&cp);
if (!ret)
- return 0;
+ goto cleanup;
die_message(_("Failed to recurse into submodule path '%s'"),
update_data->displaypath);
- if (ret == 128)
+ if (ret == 128) {
exit(ret);
- else if (ret)
- return 1;
+ } else if (ret) {
+ ret = 1;
+ goto cleanup;
+ }
}
- return 0;
+ ret = 0;
+cleanup:
+ return ret;
}
static int update_submodules(struct update_data *update_data)
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 23/26] submodule--helper: don't exit() on failure, return
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (21 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 22/26] submodule--helper: add skeleton "goto cleanup" to update_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-25 23:57 ` Glen Choo
2022-07-21 19:13 ` [PATCH v3 24/26] submodule--helper: free rest of "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
` (3 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Change code downstream of module_update() to short-circuit and return
to the top-level on failure, rather than calling exit().
To do so we need to diligently check whether we "must_die_on_failure",
which is a pattern started in c51f8f94e5b (submodule--helper: run
update procedures from C, 2021-08-24), but which hadn't been completed
to the point where we could avoid calling exit() here.
This introduces no functional changes, but makes it easier to both
call these routines as a library in the future, and to avoid leaking
memory.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 790f0ccb82e..b65665105e7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2283,7 +2283,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
return run_command(&cp);
}
-static int run_update_command(struct update_data *ud, int subforce)
+static int run_update_command(struct update_data *ud, int subforce,
+ int *must_die_on_failurep)
{
struct child_process cp = CHILD_PROCESS_INIT;
char *oid = oid_to_hex(&ud->oid);
@@ -2345,8 +2346,10 @@ static int run_update_command(struct update_data *ud, int subforce)
BUG("unexpected update strategy type: %s",
submodule_strategy_to_string(&ud->update_strategy));
}
- if (must_die_on_failure)
- exit(128);
+ if (must_die_on_failure) {
+ *must_die_on_failurep = 1;
+ return 128;
+ }
/* the command failed, but update must continue */
return 1;
@@ -2380,7 +2383,8 @@ static int run_update_command(struct update_data *ud, int subforce)
return 0;
}
-static int run_update_procedure(struct update_data *ud)
+static int run_update_procedure(struct update_data *ud,
+ int *must_die_on_failure)
{
int subforce = is_null_oid(&ud->suboid) || ud->force;
@@ -2407,7 +2411,7 @@ static int run_update_procedure(struct update_data *ud)
ud->displaypath, oid_to_hex(&ud->oid));
}
- return run_update_command(ud, subforce);
+ return run_update_command(ud, subforce, must_die_on_failure);
}
static const char *remote_submodule_branch(const char *path)
@@ -2543,7 +2547,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
"--no-single-branch");
}
-static int update_submodule(struct update_data *update_data)
+static int update_submodule(struct update_data *update_data,
+ int *must_die_on_failure)
{
int ret = 1;
@@ -2584,8 +2589,13 @@ static int update_submodule(struct update_data *update_data)
}
if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
- if (run_update_procedure(update_data))
+ ret = run_update_procedure(update_data, must_die_on_failure);
+ if (ret && *must_die_on_failure) {
+ goto cleanup;
+ } else if (ret) {
+ ret = 1;
goto cleanup;
+ }
}
if (update_data->recursive) {
@@ -2608,7 +2618,8 @@ static int update_submodule(struct update_data *update_data)
die_message(_("Failed to recurse into submodule path '%s'"),
update_data->displaypath);
if (ret == 128) {
- exit(ret);
+ *must_die_on_failure = 1;
+ goto cleanup;
} else if (ret) {
ret = 1;
goto cleanup;
@@ -2646,13 +2657,18 @@ static int update_submodules(struct update_data *update_data)
for (i = 0; i < suc.update_clone_nr; i++) {
struct update_clone_data ucd = suc.update_clone[i];
+ int code;
+ int must_die_on_failure = 0;
oidcpy(&update_data->oid, &ucd.oid);
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
- if (update_submodule(update_data))
- res = 1;
+ code = update_submodule(update_data, &must_die_on_failure);
+ if (code)
+ res = code;
+ if (must_die_on_failure)
+ goto cleanup;
}
cleanup:
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 23/26] submodule--helper: don't exit() on failure, return
2022-07-21 19:13 ` [PATCH v3 23/26] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-07-25 23:57 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-07-25 23:57 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Change code downstream of module_update() to short-circuit and return
> to the top-level on failure, rather than calling exit().
>
> To do so we need to diligently check whether we "must_die_on_failure",
> which is a pattern started in c51f8f94e5b (submodule--helper: run
> update procedures from C, 2021-08-24), but which hadn't been completed
> to the point where we could avoid calling exit() here.
>
> This introduces no functional changes, but makes it easier to both
> call these routines as a library in the future, and to avoid leaking
> memory.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 36 ++++++++++++++++++++++++++----------
> 1 file changed, 26 insertions(+), 10 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 790f0ccb82e..b65665105e7 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2283,7 +2283,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
> return run_command(&cp);
> }
>
> -static int run_update_command(struct update_data *ud, int subforce)
> +static int run_update_command(struct update_data *ud, int subforce,
> + int *must_die_on_failurep)
It's not obvious in the context lines, but there is an auto variable
named "must_die_on_failure", so we need the "p".
> {
> struct child_process cp = CHILD_PROCESS_INIT;
> char *oid = oid_to_hex(&ud->oid);
> @@ -2345,8 +2346,10 @@ static int run_update_command(struct update_data *ud, int subforce)
> BUG("unexpected update strategy type: %s",
> submodule_strategy_to_string(&ud->update_strategy));
> }
> - if (must_die_on_failure)
> - exit(128);
> + if (must_die_on_failure) {
> + *must_die_on_failurep = 1;
> + return 128;
> + }
[...]
>
> /* the command failed, but update must continue */
> return 1;
> @@ -2380,7 +2383,8 @@ static int run_update_command(struct update_data *ud, int subforce)
> return 0;
> }
>
> -static int run_update_procedure(struct update_data *ud)
> +static int run_update_procedure(struct update_data *ud,
> + int *must_die_on_failure)
> {
> int subforce = is_null_oid(&ud->suboid) || ud->force;
>
> @@ -2407,7 +2411,7 @@ static int run_update_procedure(struct update_data *ud)
> ud->displaypath, oid_to_hex(&ud->oid));
> }
>
> - return run_update_command(ud, subforce);
> + return run_update_command(ud, subforce, must_die_on_failure);
> }
>
> static const char *remote_submodule_branch(const char *path)
> @@ -2543,7 +2547,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
> "--no-single-branch");
> }
>
> -static int update_submodule(struct update_data *update_data)
> +static int update_submodule(struct update_data *update_data,
> + int *must_die_on_failure)
> {
> int ret = 1;
>
> @@ -2584,8 +2589,13 @@ static int update_submodule(struct update_data *update_data)
> }
>
> if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
> - if (run_update_procedure(update_data))
> + ret = run_update_procedure(update_data, must_die_on_failure);
> + if (ret && *must_die_on_failure) {
> + goto cleanup;
> + } else if (ret) {
> + ret = 1;
> goto cleanup;
> + }
> }
>
> if (update_data->recursive) {
> @@ -2608,7 +2618,8 @@ static int update_submodule(struct update_data *update_data)
> die_message(_("Failed to recurse into submodule path '%s'"),
> update_data->displaypath);
> if (ret == 128) {
> - exit(ret);
> + *must_die_on_failure = 1;
> + goto cleanup;
One important property in the preimage is that there's an obvious
connection between the exit(128) and this section here, i.e. the child
"git submodule update" process failed in a way that the parent needs to
stop immediately.
With this patch, this property is no longer obvious because we return
128 from the lowest level (run_update_command()). By the time we reach
the top level (module_update()), it's no longer clear that the return
value was meant to be 128.
Two ways we can fix this:
1) Just return 128 at all levels to mean "must die on failure", which
will let us get rid of "must_die_on_failure".
or...
> } else if (ret) {
> ret = 1;
> goto cleanup;
> @@ -2646,13 +2657,18 @@ static int update_submodules(struct update_data *update_data)
>
> for (i = 0; i < suc.update_clone_nr; i++) {
> struct update_clone_data ucd = suc.update_clone[i];
> + int code;
> + int must_die_on_failure = 0;
>
> oidcpy(&update_data->oid, &ucd.oid);
> update_data->just_cloned = ucd.just_cloned;
> update_data->sm_path = ucd.sub->path;
>
> - if (update_submodule(update_data))
> - res = 1;
> + code = update_submodule(update_data, &must_die_on_failure);
> + if (code)
> + res = code;
> + if (must_die_on_failure)
> + goto cleanup;
> }
2) In update_submodules() (i.e. just before module_update()), we make
update_submodules() return 128 if must_die_on_failure != 0. Then we
can drop the return value of 128 from the rest of the call chain and
just use an opaque nonzero return value instead.
>
> cleanup:
> --
> 2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 24/26] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (22 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 23/26] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-26 1:06 ` Glen Choo
2022-07-21 19:13 ` [PATCH v3 25/26] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
` (2 subsequent siblings)
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24), we clobber the "displaypath" member of
the passed-in "struct update_data" both so that die() messages in this
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b65665105e7..4e70a74357c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2551,10 +2551,11 @@ static int update_submodule(struct update_data *update_data,
int *must_die_on_failure)
{
int ret = 1;
+ char *to_free, *restore = update_data->displaypath;
ensure_core_worktree(update_data->sm_path);
- update_data->displaypath = get_submodule_displaypath(
+ update_data->displaypath = to_free = get_submodule_displaypath(
update_data->sm_path, update_data->prefix);
determine_submodule_update_strategy(the_repository, update_data->just_cloned,
@@ -2628,6 +2629,9 @@ static int update_submodule(struct update_data *update_data,
ret = 0;
cleanup:
+ free(to_free);
+ update_data->displaypath = restore;
+
return ret;
}
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 24/26] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-07-21 19:13 ` [PATCH v3 24/26] submodule--helper: free rest of "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-07-26 1:06 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-07-26 1:06 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
> procedures from C, 2021-08-24), we clobber the "displaypath" member of
> the passed-in "struct update_data" both so that die() messages in this
> update_submodule() function itself can use it, and for the
> run_update_procedure() called within this function.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index b65665105e7..4e70a74357c 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2551,10 +2551,11 @@ static int update_submodule(struct update_data *update_data,
> int *must_die_on_failure)
> {
> int ret = 1;
> + char *to_free, *restore = update_data->displaypath;
>
> ensure_core_worktree(update_data->sm_path);
>
> - update_data->displaypath = get_submodule_displaypath(
> + update_data->displaypath = to_free = get_submodule_displaypath(
> update_data->sm_path, update_data->prefix);
>
> determine_submodule_update_strategy(the_repository, update_data->just_cloned,
> @@ -2628,6 +2629,9 @@ static int update_submodule(struct update_data *update_data,
>
> ret = 0;
> cleanup:
> + free(to_free);
> + update_data->displaypath = restore;
> +
> return ret;
> }
I'm not sure why we need to have "restore". We set
"update_data->displaypath" so that we can use it inside this function
(and its call chain), but we don't care about it outside of this call
chain at all.
If the goal is to avoid exposing a free()-d pointer, could we just do
FREE_AND_NULL(update_data->displaypath);
instead?
>
> --
> 2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v3 25/26] submodule--helper: fix bad config API usage
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (23 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 24/26] submodule--helper: free rest of "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 19:13 ` [PATCH v3 26/26] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
26 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix bad config API usage added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06). After
git_config_get_string() returns successfully we know the "char **dest"
will be non-NULL.
A coccinelle patch that transforms this turns up a couple of other
such issues, one in fetch-pack.c, and another in upload-pack.c:
@@
identifier F =~ "^(repo|git)_config_get_string(_tmp)?$";
identifier V;
@@
!F(..., &V)
- && (V)
But let's focus narrowly on submodule--helper for now, we can fix
those some other time.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4e70a74357c..37c145b3ede 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3306,7 +3306,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string("submodule.active", &val) && val) {
+ if (!git_config_get_string("submodule.active", &val)) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v3 26/26] submodule--helper: fix a configure_added_submodule() leak
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (24 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 25/26] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
@ 2022-07-21 19:13 ` Ævar Arnfjörð Bjarmason
2022-07-21 21:51 ` Junio C Hamano
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
26 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-21 19:13 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix config API a memory leak added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06) by using the *_tmp()
variant of git_config_get_string().
In this case we're only checking whether
the (repo|git)_config_get_string() call is telling us that the
"submodule.active" key exists.
As with the preceding commit we'll find many other such patterns in
the codebase if we go fishing. E.g. "git gc" leaks in the code added
in 61f7a383d3b (maintenance: use 'incremental' strategy by default,
2020-10-15). Similar code in "git gc" added in
b08ff1fee00 (maintenance: add --schedule option and config,
2020-09-11) doesn't leak, but we could avoid the malloc() & free() in
that case.
A coccinelle rule to find those would find and fix some leaks, and
cases where we're doing needless malloc() + free()'s but only care
about the key existence, or are copying
the (repo|git)_config_get_string() return value right away.
But as with the preceding commit let's punt on all of that for now,
and just narrowly fix this specific case in submodule--helper.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 ++--
t/t7413-submodule-is-active.sh | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 37c145b3ede..fdf96c5d424 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3261,7 +3261,7 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
static void configure_added_submodule(struct add_data *add_data)
{
char *key;
- char *val = NULL;
+ const char *val;
struct child_process add_submod = CHILD_PROCESS_INIT;
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
@@ -3306,7 +3306,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string("submodule.active", &val)) {
+ if (!git_config_get_string_tmp("submodule.active", &val)) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index c8e7e983317..c4c1f86f3d2 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -6,6 +6,7 @@ This test verifies that `git submodue--helper is-active` correctly identifies
submodules which are "active" and interesting to the user.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
--
2.37.1.1095.g0bd6f54ba8a
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v3 26/26] submodule--helper: fix a configure_added_submodule() leak
2022-07-21 19:13 ` [PATCH v3 26/26] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-07-21 21:51 ` Junio C Hamano
0 siblings, 0 replies; 186+ messages in thread
From: Junio C Hamano @ 2022-07-21 21:51 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Glen Choo, Atharva Raykar, Prathamesh Chavan
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> static void configure_added_submodule(struct add_data *add_data)
> {
> char *key;
> - char *val = NULL;
> + const char *val;
> struct child_process add_submod = CHILD_PROCESS_INIT;
> struct child_process add_gitmodules = CHILD_PROCESS_INIT;
>
> @@ -3306,7 +3306,7 @@ static void configure_added_submodule(struct add_data *add_data)
> * is_submodule_active(), since that function needs to find
> * out the value of "submodule.active" again anyway.
> */
> - if (!git_config_get_string("submodule.active", &val)) {
> + if (!git_config_get_string_tmp("submodule.active", &val)) {
Obviously correct ;-)
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v4 00/17] submodule--helper: (only) fix memory leaks
2022-07-21 19:12 ` [PATCH v3 00/26] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (25 preceding siblings ...)
2022-07-21 19:13 ` [PATCH v3 26/26] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:29 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
` (17 more replies)
26 siblings, 18 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:29 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
This series fixes all of the memory leaks in
builtin/submodule--helper.c that our test suite spots, except for
those where the leak is downstream of cmd_submodule__helper() and
caused by code that's not in builtin/submodule--helper.c (e.g. leaks
in the object or config APIs, and in submodule.c).
For the v3 see [1]. The v3 was 26 patches, but this one's 17. The
reason for the reduction is that this is now based on a just-submitted
"prep" series[2].
The sum total is much larger now, but hopefully easier to digest, much
of the new "prep" series is either trivial patches (like whitespace
fixes), or deletion or moving (into test-tool) of code that this
"leak" series doesn't need to deal with anymore.
I think this should address all outstanding comments on the v3. In the
case of Glen's comment at [3] I dealt with my updating a commit
message in the "prep" series, see the last two paragraphs of [4] (also
shown in the range-diff of [2]).
1. https://lore.kernel.org/git/cover-v3-00.26-00000000000-20220721T191249Z-avarab@gmail.com/
2. https://lore.kernel.org/git/cover-00.20-00000000000-20220728T161116Z-avarab@gmail.com/
3. https://lore.kernel.org/git/kl6ltu74sq3b.fsf@chooglen-macbookpro.roam.corp.google.com/
4. https://lore.kernel.org/git/patch-19.20-5a26c9428be-20220728T161116Z-avarab@gmail.com/
Ævar Arnfjörð Bjarmason (17):
submodule--helper: fix a leak in "clone_submodule"
submodule--helper: fix trivial get_default_remote_submodule() leak
submodule--helper: fix most "struct pathspec" memory leaks
submodule--helper: "struct pathspec" memory leak in module_update()
submodule--helper: don't leak {run,capture}_command() cp.dir argument
submodule--helper: add and use *_release() functions
submodule--helper: fix "errmsg_str" memory leak
submodule--helper: fix "sm_path" and other "module_cb_list" leaks
submodule--helper: fix a leak with repo_clear()
submodule--helper: fix a memory leak in get_default_remote_submodule()
submodule--helper: fix "reference" leak
submodule--helper: fix obscure leak in module_add()
submodule--helper: fix a leak in module_add()
submodule--helper: fix a memory leak in print_status()
submodule--helper: free some "displaypath" in "struct update_data"
submodule--helper: free rest of "displaypath" in "struct update_data"
submodule--helper: fix a configure_added_submodule() leak
builtin/submodule--helper.c | 218 +++++++++++++++++++++--------
t/t1500-rev-parse.sh | 1 +
t/t2403-worktree-move.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t6134-pathspec-in-submodule.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
t/t7413-submodule-is-active.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 +
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 +
10 files changed, 171 insertions(+), 58 deletions(-)
Range-diff against v3:
1: 3c7ae3e0222 < -: ----------- submodule--helper: replace memset() with { 0 }-initialization
2: 32e4ae7ead5 < -: ----------- submodule--helper: stop conflating "sb" in clone_submodule()
3: eee6ca28c6f < -: ----------- submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
4: 26f0caf0386 ! 1: aac987a414a submodule--helper: fix a leak in "clone_submodule"
@@ Commit message
on absolute paths, 2016-03-31).
For the "else" case we don't need to xstrdup() the "clone_data->path",
- and we don't need to free our own "clone_data_path".
+ and we don't need to free our own "clone_data_path". We can therefore
+ assign the "clone_data->path" to our own "clone_data_path" right away,
+ and only override it (and remember to free it!) if we need to
+ xstrfmt() a replacement.
In the case of the module_clone() caller it's from "argv", and doesn't
need to be free'd, and in the case of the add_submodule() caller we
@@ Commit message
## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static int clone_submodule(const struct module_clone_data *clone_data,
+ char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *clone_data_path;
+- const char *clone_data_path;
++ const char *clone_data_path = clone_data->path;
+ char *to_free = NULL;
- if (!is_absolute_path(clone_data->path)) {
- struct strbuf sb = STRBUF_INIT;
-
- strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
-- clone_data_path = strbuf_detach(&sb, NULL);
-+ clone_data_path = to_free = strbuf_detach(&sb, NULL);
- } else {
-- clone_data_path = xstrdup(clone_data_path);
-+ clone_data_path = clone_data->path;
- }
+ if (!is_absolute_path(clone_data->path))
+- clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
+- clone_data->path);
+- else
+- clone_data_path = xstrdup(clone_data->path);
++ clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
++ clone_data->path);
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
+ die(_("refusing to create/use '%s' in another submodule's "
@@ builtin/submodule--helper.c: static int clone_submodule(const struct module_clone_data *clone_data,
free(sm_gitdir);
5: 75775bf4f6c ! 2: 390c5174e17 submodule--helper: fix trivial get_default_remote_submodule() leak
@@ Commit message
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
+@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
const char *branch = remote_submodule_branch(update_data->sm_path);
char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
6: 7672ef1305f ! 3: 529e10233d5 submodule--helper: fix most "struct pathspec" memory leaks
@@ Commit message
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static char *get_up_path(const char *path)
- static int module_list(int argc, const char **argv, const char *prefix)
- {
- int i;
-- struct pathspec pathspec;
-+ struct pathspec pathspec = { 0 };
- struct module_list list = MODULE_LIST_INIT;
-
- struct option module_list_options[] = {
-@@ builtin/submodule--helper.c: static int module_list(int argc, const char **argv, const char *prefix)
- N_("alternative anchor for relative paths")),
- OPT_END()
- };
-+ int ret = 1;
-
- const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
-@@ builtin/submodule--helper.c: static int module_list(int argc, const char **argv, const char *prefix)
- git_submodule_helper_usage, 0);
-
- if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-- return 1;
-+ goto cleanup;
-
- for (i = 0; i < list.nr; i++) {
- const struct cache_entry *ce = list.entries[i];
-@@ builtin/submodule--helper.c: static int module_list(int argc, const char **argv, const char *prefix)
-
- fprintf(stdout, "%s\n", ce->name);
- }
-- return 0;
-+ ret = 0;
-+cleanup:
-+ clear_pathspec(&pathspec);
-+ return ret;
- }
-
- static void for_each_listed_submodule(const struct module_list *list,
@@ builtin/submodule--helper.c: static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
static int module_foreach(int argc, const char **argv, const char *prefix)
{
@@ builtin/submodule--helper.c: static void runcommand_in_submodule_cb(const struct
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
-
struct option module_foreach_options[] = {
+ OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
@@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **argv, const char *prefix)
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
@@ builtin/submodule--helper.c: static void init_submodule_cb(const struct cache_en
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
-
+ struct option module_init_options[] = {
@@ builtin/submodule--helper.c: static int module_init(int argc, const char **argv, const char *prefix)
N_("git submodule init [<options>] [<path>]"),
NULL
@@ builtin/submodule--helper.c: static void status_submodule_cb(const struct cache_
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
-
+ struct option module_status_options[] = {
@@ builtin/submodule--helper.c: static int module_status(int argc, const char **argv, const char *prefix)
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
NULL
@@ builtin/submodule--helper.c: static int module_status(int argc, const char **arg
+ return ret;
}
- static int module_name(int argc, const char **argv, const char *prefix)
+ struct module_cb {
@@ builtin/submodule--helper.c: static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_sync(int argc, const char **argv, const char *prefix)
{
@@ builtin/submodule--helper.c: static void sync_submodule_cb(const struct cache_en
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int recursive = 0;
+@@ builtin/submodule--helper.c: static int module_sync(int argc, const char **argv, const char *prefix)
+ N_("git submodule sync [--quiet] [--recursive] [<path>]"),
+ NULL
+ };
+ int ret = 1;
- struct option module_sync_options[] = {
- OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
-@@ builtin/submodule--helper.c: static int module_sync(int argc, const char **argv, const char *prefix)
+ argc = parse_options(argc, argv, prefix, module_sync_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
@@ builtin/submodule--helper.c: static int push_check(int argc, const char **argv,
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
-+ int ret = 1;
-
struct option embed_gitdir_options[] = {
- OPT_STRING(0, "prefix", &prefix,
@@ builtin/submodule--helper.c: static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
+ N_("git submodule absorbgitdirs [<options>] [<path>...]"),
+ NULL
+ };
++ int ret = 1;
+
+ argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
@@ builtin/submodule--helper.c: static int absorb_git_dirs(int argc, const char **a
+ return ret;
}
- static int is_active(int argc, const char **argv, const char *prefix)
+ static int module_config(int argc, const char **argv, const char *prefix)
7: 325aa1521e2 = 4: 683d327752f submodule--helper: "struct pathspec" memory leak in module_update()
8: 424b24961b5 ! 5: 4e8e9197539 submodule--helper: don't leak {run,capture}_command() cp.dir argument
@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_pa
strvec_push(&cp.args, "fetch");
if (quiet)
-@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
+@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce,
}
strvec_push(&cp.args, oid);
9: abf5c4754a4 < -: ----------- submodule--helper: add "const" to copy of "update_data"
10: 6ab5aabae35 ! 6: 575d3e8d2e2 submodule--helper: add and use *_release() functions
@@ builtin/submodule--helper.c: static void module_list_active(struct module_list *
*list = active_modules;
}
-@@ builtin/submodule--helper.c: static int module_list(int argc, const char **argv, const char *prefix)
- }
- ret = 0;
- cleanup:
-+ module_list_release(&list);
- clear_pathspec(&pathspec);
- return ret;
- }
@@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **argv, const char *prefix)
ret = 0;
11: feec1f20bf9 < -: ----------- submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
12: d368db73de7 = 7: d4c81e04254 submodule--helper: fix "errmsg_str" memory leak
13: 5be941b3d1b = 8: ef9e29d5bfe submodule--helper: fix "sm_path" and other "module_cb_list" leaks
14: b8560e8c111 = 9: 0798a00c9ef submodule--helper: fix a leak with repo_clear()
15: abfd61f9f05 = 10: dae2a6f8e07 submodule--helper: fix a memory leak in get_default_remote_submodule()
16: b8df96a9cf0 ! 11: e7352bb8cfa submodule--helper: fix "reference" leak is "module_clone_data"
@@ Metadata
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## Commit message ##
- submodule--helper: fix "reference" leak is "module_clone_data"
+ submodule--helper: fix "reference" leak
- Fix leaks in the "reference" member of "struct module_clone_data" that
- have been with us since 31224cbdc72 (clone: recursive and reference
- option triggers submodule alternates, 2016-08-17) and
- 8c8195e9c3e (submodule--helper: introduce add-clone subcommand,
- 2021-07-10).
+ 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
+ 31224cbdc72 (clone: recursive and reference option triggers submodule
+ alternates, 2016-08-17) and 8c8195e9c3e (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()
@@ Commit message
member, if it has a pointer it's the pointer we'll need to free,
otherwise it'll be NULL (i.e. from argv).
- To fix this create a a module_clone_data_release() function to go with
- the MODULE_CLONE_DATA_INIT added in a98b02c1128 (submodule--helper:
- refactor module_clone(), 2021-07-10). We only need to add it to
- add_submodule() to fix the leak, but let's add it to module_clone() as
- well for consistency.
+ 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 <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: struct module_clone_data {
- .single_branch = -1, \
- }
-
-+static void module_clone_data_release(struct module_clone_data *cd)
-+{
-+ string_list_clear(&cd->reference, 1);
-+}
-+
- struct submodule_alternate_setup {
- const char *submodule_name;
- enum SUBMODULE_ALTERNATE_ERROR_MODE {
@@ builtin/submodule--helper.c: static int add_possible_reference_from_superproject(
sm_alternate = compute_alternate_path(sb.buf, &err);
@@ builtin/submodule--helper.c: static int add_possible_reference_from_superproject
switch (sas->error_mode) {
@@ builtin/submodule--helper.c: static int module_clone(int argc, const char **argv, const char *prefix)
- clone_submodule(&clone_data, &clone_data.reference);
+ clone_submodule(&clone_data, &reference);
list_objects_filter_release(&filter_options);
-+ module_clone_data_release(&clone_data);
++ string_list_clear(&reference, 1);
return 0;
}
@@ builtin/submodule--helper.c: static int add_submodule(const struct add_data *add_data)
- {
char *submod_gitdir_path;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
+ struct string_list reference = STRING_LIST_INIT_NODUP;
+ int ret = -1;
/* perhaps the path already exists and is already a git repo, else clone it */
@@ builtin/submodule--helper.c: static int add_submodule(const struct add_data *add
clone_data.quiet = add_data->quiet;
clone_data.progress = add_data->progress;
- if (add_data->reference_path)
-- string_list_append(&clone_data.reference,
+- string_list_append(&reference,
- xstrdup(add_data->reference_path));
+ if (add_data->reference_path) {
+ char *p = xstrdup(add_data->reference_path);
+
-+ string_list_append(&clone_data.reference, p)->util = p;
++ string_list_append(&reference, p)->util = p;
+ }
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
- if (clone_submodule(&clone_data, &clone_data.reference))
+ if (clone_submodule(&clone_data, &reference))
- return -1;
+ goto cleanup;
@@ builtin/submodule--helper.c: static int add_submodule(const struct add_data *add
- return 0;
+ ret = 0;
+cleanup:
-+ module_clone_data_release(&clone_data);
++ string_list_clear(&reference, 1);
+ return ret;
}
17: 7811bdbf149 ! 12: 1adb7b66656 submodule--helper: fix obscure leak in module_add()
@@ Metadata
## Commit message ##
submodule--helper: fix obscure leak in module_add()
- Fix an obscure leak in module_add()< if the "git add" command we were
+ Fix an obscure leak in module_add(), if the "git add" command we were
piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
introduced in a6226fd772b (submodule--helper: convert the bulk of
cmd_add() to C, 2021-08-10).
@@ Commit message
## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static int module_add(int argc, const char **argv, const char *prefix)
- int force = 0, quiet = 0, progress = 0, dissociate = 0;
- struct add_data add_data = ADD_DATA_INIT;
- char *to_free = NULL;
+ N_("git submodule add [<options>] [--] <repository> [<path>]"),
+ NULL
+ };
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 1;
- struct option options[] = {
- OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
+ argc = parse_options(argc, argv, prefix, options, usage, 0);
+
@@ builtin/submodule--helper.c: static int module_add(int argc, const char **argv, const char *prefix)
die_on_repo_without_commits(add_data.sm_path);
@@ builtin/submodule--helper.c: static int module_add(int argc, const char **argv,
- int exit_code = -1;
- struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
+
cp.git_cmd = 1;
cp.no_stdout = 1;
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
18: 01566d63926 ! 13: b27b665d287 submodule--helper: fix a leak in module_add()
@@ builtin/submodule--helper.c: static int module_add(int argc, const char **argv,
- add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
+ char *sm_path = add_data.sm_path;
++
+ add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
+ free(sm_path);
+ }
19: 7ef89abed86 = 14: 53ba1705eb6 submodule--helper: fix a memory leak in print_status()
20: b8d47fc7d70 = 15: 230e5f8ad14 submodule--helper: free some "displaypath" in "struct update_data"
21: 4fb17f0dff1 < -: ----------- submodule--helper: rename "int res" to "int ret"
22: af83925046b < -: ----------- submodule--helper: add skeleton "goto cleanup" to update_submodule()
23: 4c60784d281 < -: ----------- submodule--helper: don't exit() on failure, return
24: 7551af195ad = 16: c0fba2f1c56 submodule--helper: free rest of "displaypath" in "struct update_data"
25: f650716cd7e < -: ----------- submodule--helper: fix bad config API usage
26: 581ce0872c0 ! 17: 95f8b68bd41 submodule--helper: fix a configure_added_submodule() leak
@@ builtin/submodule--helper.c: static void configure_added_submodule(struct add_da
* current configured pathspec, set the submodule's active flag
## t/t7413-submodule-is-active.sh ##
-@@ t/t7413-submodule-is-active.sh: This test verifies that `git submodue--helper is-active` correctly identifies
+@@ t/t7413-submodule-is-active.sh: This test verifies that `test-tool submodule is-active` correctly identifies
submodules which are "active" and interesting to the user.
'
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v4 01/17] submodule--helper: fix a leak in "clone_submodule"
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:29 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
` (16 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:29 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak of the "clone_data_path" variable that we copy or
derive from the "struct module_clone_data" in clone_submodule(). This
code was refactored in preceding commits, but the leak has been with
us since f8eaa0ba98b (submodule--helper, module_clone: always operate
on absolute paths, 2016-03-31).
For the "else" case we don't need to xstrdup() the "clone_data->path",
and we don't need to free our own "clone_data_path". We can therefore
assign the "clone_data->path" to our own "clone_data_path" right away,
and only override it (and remember to free it!) if we need to
xstrfmt() a replacement.
In the case of the module_clone() caller it's from "argv", and doesn't
need to be free'd, and in the case of the add_submodule() caller we
get a pointer to "sm_path", which doesn't need to be directly free'd
either.
Fixing this leak makes several tests pass, so let's mark them as
passing with TEST_PASSES_SANITIZE_LEAK=true.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 10 +++++-----
t/t1500-rev-parse.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 ++
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 ++
6 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 22c79353bb0..d3dd47588d5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1572,13 +1572,12 @@ static int clone_submodule(const struct module_clone_data *clone_data,
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *clone_data_path;
+ const char *clone_data_path = clone_data->path;
+ char *to_free = NULL;
if (!is_absolute_path(clone_data->path))
- clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
- clone_data->path);
- else
- clone_data_path = xstrdup(clone_data->path);
+ clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
+ clone_data->path);
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
die(_("refusing to create/use '%s' in another submodule's "
@@ -1663,6 +1662,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
free(sm_gitdir);
free(p);
+ free(to_free);
return 0;
}
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 1c2df08333b..0e13bcb4ebb 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -4,6 +4,7 @@ test_description='test git rev-parse'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_one () {
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 3153a0d8910..12e67e187ef 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -8,6 +8,7 @@ test_description='git rev-list involving submodules that this repo has'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
index f2e7df59cf2..3269298197c 100755
--- a/t/t7414-submodule-mistakes.sh
+++ b/t/t7414-submodule-mistakes.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='handling of common mistakes people may make with submodules'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create embedded repository' '
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index 3fcb44767f5..f5426a8e589 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -2,6 +2,7 @@
test_description='git status for submodule'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_create_repo_with_commit () {
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
index ed2653d46fe..92462a22374 100755
--- a/t/t7507-commit-verbose.sh
+++ b/t/t7507-commit-verbose.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='verbose commit template'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
write_script "check-for-diff" <<\EOF &&
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:29 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
` (15 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:29 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in 1012a5cbc3f (submodule--helper
run-update-procedure: learn --remote, 2022-03-04), we need to free()
the xstrdup()'d string. This gets e.g. t/t7419-submodule-set-branch.sh
closer to passing under SANITIZE=leak.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d3dd47588d5..d452af40d2d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2410,6 +2410,8 @@ static int update_submodule(struct update_data *update_data,
const char *branch = remote_submodule_branch(update_data->sm_path);
char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ free(remote_name);
+
if (!update_data->nofetch) {
if (fetch_in_submodule(update_data->sm_path, update_data->depth,
0, NULL))
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 03/17] submodule--helper: fix most "struct pathspec" memory leaks
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:29 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
` (14 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:29 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call clear_pathspec() at the end of various functions that work with
and allocate a "struct pathspec".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 74 +++++++++++++++++++++++++------------
1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d452af40d2d..6c53c83a2af 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -367,7 +367,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
static int module_foreach(int argc, const char **argv, const char *prefix)
{
struct foreach_cb info = FOREACH_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_foreach_options[] = {
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
@@ -379,12 +379,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_foreach_options,
git_submodule_helper_usage, 0);
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.argc = argc;
info.argv = argv;
@@ -392,7 +393,10 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int starts_with_dot_slash(const char *const path)
@@ -502,7 +506,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_init(int argc, const char **argv, const char *prefix)
{
struct init_cb info = INIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_init_options[] = {
@@ -513,12 +517,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
N_("git submodule init [<options>] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_init_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
/*
* If there are no path args and submodule.active is set then,
@@ -533,7 +538,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, init_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct status_cb {
@@ -680,7 +688,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
static int module_status(int argc, const char **argv, const char *prefix)
{
struct status_cb info = STATUS_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_status_options[] = {
@@ -693,12 +701,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_status_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -706,7 +715,10 @@ static int module_status(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, status_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_cb {
@@ -1245,7 +1257,7 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_sync(int argc, const char **argv, const char *prefix)
{
struct sync_cb info = SYNC_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int recursive = 0;
@@ -1259,12 +1271,13 @@ static int module_sync(int argc, const char **argv, const char *prefix)
N_("git submodule sync [--quiet] [--recursive] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_sync_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1274,7 +1287,10 @@ static int module_sync(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, sync_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct deinit_cb {
@@ -1383,7 +1399,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
static int module_deinit(int argc, const char **argv, const char *prefix)
{
struct deinit_cb info = DEINIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int force = 0;
@@ -1398,6 +1414,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_deinit_options,
git_submodule_helper_usage, 0);
@@ -1412,7 +1429,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
die(_("Use '--all' if you really want to deinitialize all submodules"));
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1422,7 +1439,10 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, deinit_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_clone_data {
@@ -2516,7 +2536,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2593,8 +2613,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
opt.update_strategy.type = opt.update_default;
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
- list_objects_filter_release(&filter_options);
- return 1;
+ ret = 1;
+ goto cleanup;
}
if (pathspec.nr)
@@ -2605,8 +2625,10 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0)
- return 1;
+ &pathspec, &list) < 0) {
+ ret = 1;
+ goto cleanup;
+ }
/*
* If there are no path args and submodule.active is set then,
@@ -2623,7 +2645,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
}
ret = update_submodules(&opt);
+cleanup:
list_objects_filter_release(&filter_options);
+ clear_pathspec(&pathspec);
return ret;
}
@@ -2707,7 +2731,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
{
int i;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
struct option embed_gitdir_options[] = {
@@ -2722,17 +2746,21 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
N_("git submodule absorbgitdirs [<options>] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
for (i = 0; i < list.nr; i++)
absorb_git_dir_into_superproject(list.entries[i]->name, flags);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int module_config(int argc, const char **argv, const char *prefix)
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 04/17] submodule--helper: "struct pathspec" memory leak in module_update()
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (2 preceding siblings ...)
2022-07-28 16:29 ` [PATCH v4 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:29 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:29 ` [PATCH v4 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
` (13 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:29 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
The module_update() function calls module_list_compute() twice, which
in turn will reset the "struct pathspec" passed to it. Let's instead
track two of them, and clear them both.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6c53c83a2af..057cb6c0d42 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2537,6 +2537,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec = { 0 };
+ struct pathspec pathspec2 = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2625,7 +2626,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0) {
+ &pathspec2, &list) < 0) {
ret = 1;
goto cleanup;
}
@@ -2648,6 +2649,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
cleanup:
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
+ clear_pathspec(&pathspec2);
return ret;
}
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (3 preceding siblings ...)
2022-07-28 16:29 ` [PATCH v4 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:29 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
` (12 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:29 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24) and 3c3558f0953 (submodule--helper: run
update using child process struct, 2022-03-15) by not allocating
memory in the first place.
The "dir" member of "struct child_process" will not be modified by
that API, and it's declared to be "const char *". So let's not
needlessly duplicate these strings.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 057cb6c0d42..35a168009b7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2105,7 +2105,7 @@ static int is_tip_reachable(const char *path, struct object_id *oid)
char *hex = oid_to_hex(oid);
cp.git_cmd = 1;
- cp.dir = xstrdup(path);
+ cp.dir = path;
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
@@ -2123,7 +2123,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
- cp.dir = xstrdup(module_path);
+ cp.dir = module_path;
strvec_push(&cp.args, "fetch");
if (quiet)
@@ -2180,7 +2180,7 @@ static int run_update_command(struct update_data *ud, int subforce,
}
strvec_push(&cp.args, oid);
- cp.dir = xstrdup(ud->sm_path);
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
if (run_command(&cp)) {
switch (ud->update_strategy.type) {
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 06/17] submodule--helper: add and use *_release() functions
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (4 preceding siblings ...)
2022-07-28 16:29 ` [PATCH v4 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
` (11 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add release functions for "struct module_list", "struct
submodule_update_clone" and "struct update_data".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 28 +++++++++++++++++++++++++++-
t/t6134-pathspec-in-submodule.sh | 1 +
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 35a168009b7..48507a6e0df 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -160,6 +160,11 @@ struct module_list {
};
#define MODULE_LIST_INIT { 0 }
+static void module_list_release(struct module_list *ml)
+{
+ free(ml->entries);
+}
+
static int module_list_compute(int argc, const char **argv,
const char *prefix,
struct pathspec *pathspec,
@@ -222,7 +227,7 @@ static void module_list_active(struct module_list *list)
active_modules.entries[active_modules.nr++] = ce;
}
- free(list->entries);
+ module_list_release(list);
*list = active_modules;
}
@@ -395,6 +400,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -540,6 +546,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -717,6 +724,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1289,6 +1297,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1441,6 +1450,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1810,6 +1820,12 @@ struct submodule_update_clone {
};
#define SUBMODULE_UPDATE_CLONE_INIT { 0 }
+static void submodule_update_clone_release(struct submodule_update_clone *suc)
+{
+ free(suc->update_clone);
+ free(suc->failed_clones);
+}
+
struct update_data {
const char *prefix;
const char *displaypath;
@@ -1848,6 +1864,11 @@ struct update_data {
.max_jobs = 1, \
}
+static void update_data_release(struct update_data *ud)
+{
+ module_list_release(&ud->list);
+}
+
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
struct strbuf *out, const char *displaypath)
{
@@ -2530,6 +2551,7 @@ static int update_submodules(struct update_data *update_data)
}
cleanup:
+ submodule_update_clone_release(&suc);
string_list_clear(&update_data->references, 0);
return res;
}
@@ -2627,6 +2649,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
if (module_list_compute(argc, argv, opt.prefix,
&pathspec2, &list) < 0) {
+ module_list_release(&list);
ret = 1;
goto cleanup;
}
@@ -2643,10 +2666,12 @@ static int module_update(int argc, const char **argv, const char *prefix)
info.flags |= OPT_QUIET;
for_each_listed_submodule(&list, init_submodule_cb, &info);
+ module_list_release(&list);
}
ret = update_submodules(&opt);
cleanup:
+ update_data_release(&opt);
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
clear_pathspec(&pathspec2);
@@ -2762,6 +2787,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
clear_pathspec(&pathspec);
+ module_list_release(&list);
return ret;
}
diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh
index 0f1cb49cedc..3a241f259de 100755
--- a/t/t6134-pathspec-in-submodule.sh
+++ b/t/t6134-pathspec-in-submodule.sh
@@ -2,6 +2,7 @@
test_description='test case exclude pathspec'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a submodule' '
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 07/17] submodule--helper: fix "errmsg_str" memory leak
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (5 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
` (10 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak introduced in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13), we sometimes append
to the "errmsg", and need to free the "struct strbuf".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 48507a6e0df..5cbe6a41e5f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -960,6 +960,7 @@ static void generate_submodule_summary(struct summary_cb *info,
free(displaypath);
free(src_abbrev);
free(dst_abbrev);
+ strbuf_release(&errmsg);
}
static void prepare_submodule_summary(struct summary_cb *info,
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (6 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
` (9 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix leaks in "struct module_cb_list" and the "struct module_cb" which
it contains, these fixes leaks in e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).
The "sm_path" should always have been a "char *", not a "const
char *", we always create it with xstrdup().
We can't mark any tests passing passing with SANITIZE=leak using
"TEST_PASSES_SANITIZE_LEAK=true" as a result of this change, but
"t7401-submodule-summary.sh" gets closer to passing as a result of
this change.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5cbe6a41e5f..becf686e47a 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -735,16 +735,34 @@ struct module_cb {
struct object_id oid_src;
struct object_id oid_dst;
char status;
- const char *sm_path;
+ char *sm_path;
};
#define MODULE_CB_INIT { 0 }
+static void module_cb_release(struct module_cb *mcb)
+{
+ free(mcb->sm_path);
+}
+
struct module_cb_list {
struct module_cb **entries;
int alloc, nr;
};
#define MODULE_CB_LIST_INIT { 0 }
+static void module_cb_list_release(struct module_cb_list *mcbl)
+{
+ int i;
+
+ for (i = 0; i < mcbl->nr; i++) {
+ struct module_cb *mcb = mcbl->entries[i];
+
+ module_cb_release(mcb);
+ free(mcb);
+ }
+ free(mcbl->entries);
+}
+
struct summary_cb {
int argc;
const char **argv;
@@ -1088,6 +1106,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
cleanup:
strvec_clear(&diff_args);
release_revisions(&rev);
+ module_cb_list_release(&list);
return ret;
}
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 09/17] submodule--helper: fix a leak with repo_clear()
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (7 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
` (8 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call repo_clear() in ensure_core_worktree() to free the "struct
repository". Fixes a leak that's been here since
74d4731da1f (submodule--helper: replace connect-gitdir-workingtree by
ensure-core-worktree, 2018-08-13).
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index becf686e47a..dbeafd9787d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2375,6 +2375,7 @@ static void ensure_core_worktree(const char *path)
free(abs_path);
strbuf_release(&sb);
}
+ repo_clear(&subrepo);
}
static const char *submodule_update_type_to_label(enum submodule_update_type type)
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule()
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (8 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
` (7 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in the get_default_remote_submodule() function added
in a77c3fcb5ec (submodule--helper: get remote names from any
repository, 2022-03-04), we need to repo_clear() the submodule we
initialize.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index dbeafd9787d..f8a92ecf86d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -62,9 +62,13 @@ static char *repo_get_default_remote(struct repository *repo)
static char *get_default_remote_submodule(const char *module_path)
{
struct repository subrepo;
+ char *ret;
repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
- return repo_get_default_remote(&subrepo);
+ ret = repo_get_default_remote(&subrepo);
+ repo_clear(&subrepo);
+
+ return ret;
}
static char *get_default_remote(void)
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 11/17] submodule--helper: fix "reference" leak
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (9 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
` (6 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
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
31224cbdc72 (clone: recursive and reference option triggers submodule
alternates, 2016-08-17) and 8c8195e9c3e (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 <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f8a92ecf86d..debe3a4a2f5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1548,7 +1548,9 @@ static int add_possible_reference_from_superproject(
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
- string_list_append(sas->reference, xstrdup(sb.buf));
+ char *p = strbuf_detach(&sb, NULL);
+
+ string_list_append(sas->reference, p)->util = p;
free(sm_alternate);
} else {
switch (sas->error_mode) {
@@ -1780,6 +1782,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
clone_submodule(&clone_data, &reference);
list_objects_filter_release(&filter_options);
+ string_list_clear(&reference, 1);
return 0;
}
@@ -3018,6 +3021,7 @@ static int add_submodule(const struct add_data *add_data)
char *submod_gitdir_path;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
struct string_list reference = STRING_LIST_INIT_NODUP;
+ int ret = -1;
/* perhaps the path already exists and is already a git repo, else clone it */
if (is_directory(add_data->sm_path)) {
@@ -3073,15 +3077,17 @@ static int add_submodule(const struct add_data *add_data)
clone_data.url = add_data->realrepo;
clone_data.quiet = add_data->quiet;
clone_data.progress = add_data->progress;
- if (add_data->reference_path)
- string_list_append(&reference,
- xstrdup(add_data->reference_path));
+ if (add_data->reference_path) {
+ char *p = xstrdup(add_data->reference_path);
+
+ string_list_append(&reference, p)->util = p;
+ }
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
if (clone_submodule(&clone_data, &reference))
- return -1;
+ goto cleanup;
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -3100,7 +3106,10 @@ static int add_submodule(const struct add_data *add_data)
if (run_command(&cp))
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
}
- return 0;
+ ret = 0;
+cleanup:
+ string_list_clear(&reference, 1);
+ return ret;
}
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 12/17] submodule--helper: fix obscure leak in module_add()
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (10 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
` (5 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix an obscure leak in module_add(), if the "git add" command we were
piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
introduced in a6226fd772b (submodule--helper: convert the bulk of
cmd_add() to C, 2021-08-10).
In fixing it move to a "goto cleanup" pattern, and since we need to
introduce a "ret" variable to do that let's also get rid of the
intermediate "exit_code" variable. The initialization to "-1" in
a6226fd772b has always been redundant, we'd only use the "exit_code"
value after assigning the return value of pipe_command() to it.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index debe3a4a2f5..0f6c07e3d1e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3269,6 +3269,8 @@ static int module_add(int argc, const char **argv, const char *prefix)
N_("git submodule add [<options>] [--] <repository> [<path>]"),
NULL
};
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 1;
argc = parse_options(argc, argv, prefix, options, usage, 0);
@@ -3318,21 +3320,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
die_on_repo_without_commits(add_data.sm_path);
if (!force) {
- int exit_code = -1;
- struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdout = 1;
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
"--no-warn-embedded-repo", add_data.sm_path, NULL);
- if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+ if ((ret = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
strbuf_complete_line(&sb);
fputs(sb.buf, stderr);
- free(add_data.sm_path);
- return exit_code;
+ goto cleanup;
}
- strbuf_release(&sb);
}
if(!add_data.sm_name)
@@ -3347,15 +3345,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
add_data.progress = !!progress;
add_data.dissociate = !!dissociate;
- if (add_submodule(&add_data)) {
- free(add_data.sm_path);
- return 1;
- }
+ if (add_submodule(&add_data))
+ goto cleanup;
configure_added_submodule(&add_data);
+
+ ret = 0;
+cleanup:
free(add_data.sm_path);
free(to_free);
+ strbuf_release(&sb);
- return 0;
+ return ret;
}
#define SUPPORT_SUPER_PREFIX (1<<0)
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 13/17] submodule--helper: fix a leak in module_add()
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (11 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
` (4 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in module_path(), since a6226fd772b (submodule--helper:
convert the bulk of cmd_add() to C, 2021-08-10), we've been freeing
add_data.sm_path, but in this case we clobbered it, and didn't free
the value we clobbered.
This makes test 28 of "t/t7400-submodule-basic.sh" ("submodule add in
subdirectory") pass when we're compiled with SANITIZE=leak..
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 0f6c07e3d1e..6077aecd202 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3290,8 +3290,12 @@ static int module_add(int argc, const char **argv, const char *prefix)
else
add_data.sm_path = xstrdup(argv[1]);
- if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
- add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
+ char *sm_path = add_data.sm_path;
+
+ add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
+ free(sm_path);
+ }
if (starts_with_dot_dot_slash(add_data.repo) ||
starts_with_dot_slash(add_data.repo)) {
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 14/17] submodule--helper: fix a memory leak in print_status()
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (12 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
` (3 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in print_status(), the compute_rev_name() function
implemented in this file will return a strbuf_detach()'d value, or
NULL.
This leak has existed since this code was added in
a9f8a37584a (submodule: port submodule subcommand 'status' from shell
to C, 2017-10-06), but in 0b5e2ea7cf3 (submodule--helper: don't print
null in 'submodule status', 2018-04-18) we added a "const"
intermediate variable for the return value, that "const" should be
removed.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6077aecd202..b51b60d5c77 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -570,10 +570,11 @@ static void print_status(unsigned int flags, char state, const char *path,
printf("%c%s %s", state, oid_to_hex(oid), displaypath);
if (state == ' ' || state == '+') {
- const char *name = compute_rev_name(path, oid_to_hex(oid));
+ char *name = compute_rev_name(path, oid_to_hex(oid));
if (name)
printf(" (%s)", name);
+ free(name);
}
printf("\n");
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 15/17] submodule--helper: free some "displaypath" in "struct update_data"
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (13 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
` (2 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Make the update_data_release() function free "displaypath" member when
appropriate. The "displaypath" member is always ours, the "const" on
the "char *" was wrong to begin with.
This leaves a leak of "displaypath" in update_submodule(), which as
we'll see in subsequent commits is harder to deal with than this
trivial fix.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
t/t2403-worktree-move.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b51b60d5c77..2e39750fb06 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1856,7 +1856,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
struct update_data {
const char *prefix;
- const char *displaypath;
+ char *displaypath;
enum submodule_update_type update_default;
struct object_id suboid;
struct string_list references;
@@ -1894,6 +1894,7 @@ struct update_data {
static void update_data_release(struct update_data *ud)
{
+ free(ud->displaypath);
module_list_release(&ud->list);
}
diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh
index a4e1a178e0a..1168e9f9982 100755
--- a/t/t2403-worktree-move.sh
+++ b/t/t2403-worktree-move.sh
@@ -2,6 +2,7 @@
test_description='test git worktree move, remove, lock and unlock'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 1cfa150768d..2859695c6d2 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -6,6 +6,7 @@ This test verifies that `git submodue absorbgitdirs` moves a submodules git
directory into the superproject.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (14 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-07-28 16:30 ` [PATCH v4 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24), we clobber the "displaypath" member of
the passed-in "struct update_data" both so that die() messages in this
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2e39750fb06..2a171d25992 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2460,10 +2460,11 @@ static int update_submodule(struct update_data *update_data,
int *must_die_on_failure)
{
int ret = 1;
+ char *to_free, *restore = update_data->displaypath;
ensure_core_worktree(update_data->sm_path);
- update_data->displaypath = get_submodule_displaypath(
+ update_data->displaypath = to_free = get_submodule_displaypath(
update_data->sm_path, update_data->prefix);
determine_submodule_update_strategy(the_repository, update_data->just_cloned,
@@ -2537,6 +2538,9 @@ static int update_submodule(struct update_data *update_data,
ret = 0;
cleanup:
+ free(to_free);
+ update_data->displaypath = restore;
+
return ret;
}
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v4 17/17] submodule--helper: fix a configure_added_submodule() leak
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (15 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:30 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:30 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix config API a memory leak added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06) by using the *_tmp()
variant of git_config_get_string().
In this case we're only checking whether
the (repo|git)_config_get_string() call is telling us that the
"submodule.active" key exists.
As with the preceding commit we'll find many other such patterns in
the codebase if we go fishing. E.g. "git gc" leaks in the code added
in 61f7a383d3b (maintenance: use 'incremental' strategy by default,
2020-10-15). Similar code in "git gc" added in
b08ff1fee00 (maintenance: add --schedule option and config,
2020-09-11) doesn't leak, but we could avoid the malloc() & free() in
that case.
A coccinelle rule to find those would find and fix some leaks, and
cases where we're doing needless malloc() + free()'s but only care
about the key existence, or are copying
the (repo|git)_config_get_string() return value right away.
But as with the preceding commit let's punt on all of that for now,
and just narrowly fix this specific case in submodule--helper.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 ++--
t/t7413-submodule-is-active.sh | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2a171d25992..a3e00c9929d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3136,7 +3136,7 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
static void configure_added_submodule(struct add_data *add_data)
{
char *key;
- char *val = NULL;
+ const char *val;
struct child_process add_submod = CHILD_PROCESS_INIT;
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
@@ -3181,7 +3181,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string("submodule.active", &val)) {
+ if (!git_config_get_string_tmp("submodule.active", &val)) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index 9ead083371a..a3c824c3e4b 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -6,6 +6,7 @@ This test verifies that `test-tool submodule is-active` correctly identifies
submodules which are "active" and interesting to the user.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
--
2.37.1.1197.g7ed548b7807
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 00/17] submodule--helper: fix memory leaks
2022-07-28 16:29 ` [PATCH v4 00/17] submodule--helper: (only) fix memory leaks Ævar Arnfjörð Bjarmason
` (16 preceding siblings ...)
2022-07-28 16:30 ` [PATCH v4 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
` (17 more replies)
17 siblings, 18 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
This series fixes all of the memory leaks in
builtin/submodule--helper.c that our test suite spots, except for
those where the leak is downstream of cmd_submodule__helper() and
caused by code that's not in builtin/submodule--helper.c (e.g. leaks
in the object or config APIs, and in submodule.c).
This re-roll is on top of the just-now re-rolled v2 of the base
topic[1]. The only changes are to rebase the changes here on top of
those changes.
Changes:
* The base topic renamed another "res" variable (one was left behind
before).
* The "goto cleanup" pattern in update_submodule() is gone now, which
makes 16/17 much easier.
For the CI run & pushed branch see [2].
1. https://lore.kernel.org/git/cover-v2-00.28-00000000000-20220802T154036Z-avarab@gmail.com/
2. https://github.com/avar/git/tree/avar/submodule--helper-memory-leaks-5
Ævar Arnfjörð Bjarmason (17):
submodule--helper: fix a leak in "clone_submodule"
submodule--helper: fix trivial get_default_remote_submodule() leak
submodule--helper: fix most "struct pathspec" memory leaks
submodule--helper: "struct pathspec" memory leak in module_update()
submodule--helper: don't leak {run,capture}_command() cp.dir argument
submodule--helper: add and use *_release() functions
submodule--helper: fix "errmsg_str" memory leak
submodule--helper: fix "sm_path" and other "module_cb_list" leaks
submodule--helper: fix a leak with repo_clear()
submodule--helper: fix a memory leak in get_default_remote_submodule()
submodule--helper: fix "reference" leak
submodule--helper: fix obscure leak in module_add()
submodule--helper: fix a leak in module_add()
submodule--helper: fix a memory leak in print_status()
submodule--helper: free some "displaypath" in "struct update_data"
submodule--helper: free rest of "displaypath" in "struct update_data"
submodule--helper: fix a configure_added_submodule() leak
builtin/submodule--helper.c | 239 +++++++++++++++++++++--------
t/t1500-rev-parse.sh | 1 +
t/t2403-worktree-move.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t6134-pathspec-in-submodule.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
t/t7413-submodule-is-active.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 +
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 +
10 files changed, 185 insertions(+), 65 deletions(-)
Range-diff against v4:
1: aac987a414a = 1: 118e965d401 submodule--helper: fix a leak in "clone_submodule"
2: 390c5174e17 ! 2: d885e1dd59a submodule--helper: fix trivial get_default_remote_submodule() leak
@@ Commit message
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
+@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
const char *branch = remote_submodule_branch(update_data->sm_path);
char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
3: 529e10233d5 = 3: 1f90348d61f submodule--helper: fix most "struct pathspec" memory leaks
4: 683d327752f = 4: f768ff2e34d submodule--helper: "struct pathspec" memory leak in module_update()
5: 4e8e9197539 ! 5: 509133c37fa submodule--helper: don't leak {run,capture}_command() cp.dir argument
@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_pa
strvec_push(&cp.args, "fetch");
if (quiet)
-@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce,
+@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
}
strvec_push(&cp.args, oid);
@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
if (run_command(&cp)) {
- switch (ud->update_strategy.type) {
+ int ret;
6: 575d3e8d2e2 ! 6: 25377f1d06c submodule--helper: add and use *_release() functions
@@ builtin/submodule--helper.c: static int update_submodules(struct update_data *up
cleanup:
+ submodule_update_clone_release(&suc);
string_list_clear(&update_data->references, 0);
- return res;
+ return ret;
}
@@ builtin/submodule--helper.c: static int module_update(int argc, const char **argv, const char *prefix)
7: d4c81e04254 = 7: 1a85057cd0c submodule--helper: fix "errmsg_str" memory leak
8: ef9e29d5bfe = 8: 3c4f734e958 submodule--helper: fix "sm_path" and other "module_cb_list" leaks
9: 0798a00c9ef ! 9: 3aebff9f8e3 submodule--helper: fix a leak with repo_clear()
@@ Commit message
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static void ensure_core_worktree(const char *path)
- free(abs_path);
+@@ builtin/submodule--helper.c: static int ensure_core_worktree(const char *path)
strbuf_release(&sb);
}
+
+ repo_clear(&subrepo);
+ return 0;
}
- static const char *submodule_update_type_to_label(enum submodule_update_type type)
10: dae2a6f8e07 = 10: 38345ec76bc submodule--helper: fix a memory leak in get_default_remote_submodule()
11: e7352bb8cfa = 11: 4b1e5ced969 submodule--helper: fix "reference" leak
12: 1adb7b66656 = 12: e74c396073b submodule--helper: fix obscure leak in module_add()
13: b27b665d287 = 13: 71a56c59864 submodule--helper: fix a leak in module_add()
14: 53ba1705eb6 = 14: 2429db2f1c7 submodule--helper: fix a memory leak in print_status()
15: 230e5f8ad14 = 15: 613d077c4ec submodule--helper: free some "displaypath" in "struct update_data"
16: c0fba2f1c56 ! 16: 8f150a81507 submodule--helper: free rest of "displaypath" in "struct update_data"
@@ Commit message
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
+ To make managing that clobbering easier let's wrap the
+ update_submodule() in a new update_submodule_outer() function, which
+ will do the clobbering and free(to_free) dance for us.
+
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
- int *must_die_on_failure)
+@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
{
- int ret = 1;
-+ char *to_free, *restore = update_data->displaypath;
-
- ensure_core_worktree(update_data->sm_path);
+ int ret;
+- ret = ensure_core_worktree(update_data->sm_path);
+- if (ret)
+- return ret;
+-
- update_data->displaypath = get_submodule_displaypath(
-+ update_data->displaypath = to_free = get_submodule_displaypath(
- update_data->sm_path, update_data->prefix);
-
- determine_submodule_update_strategy(the_repository, update_data->just_cloned,
-@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
+- update_data->sm_path, update_data->prefix);
+-
+ ret = determine_submodule_update_strategy(the_repository,
+ update_data->just_cloned,
+ update_data->sm_path,
+@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
+ return 0;
+ }
- ret = 0;
- cleanup:
++static int update_submodule_outer(struct update_data *update_data)
++{
++ char *to_free, *restore = update_data->displaypath;
++ int ret;
++
++ ensure_core_worktree(update_data->sm_path);
++
++ update_data->displaypath = to_free = get_submodule_displaypath(
++ update_data->sm_path, update_data->prefix);
++
++ ret = update_submodule(update_data);
++
+ free(to_free);
+ update_data->displaypath = restore;
+
- return ret;
- }
++ return ret;
++}
++
+ static int update_submodules(struct update_data *update_data)
+ {
+ int i, ret = 0;
+@@ builtin/submodule--helper.c: static int update_submodules(struct update_data *update_data)
+ update_data->just_cloned = ucd.just_cloned;
+ update_data->sm_path = ucd.sub->path;
+- code = update_submodule(update_data);
++ code = update_submodule_outer(update_data);
+ if (code)
+ ret = code;
+ if (code == 128)
17: 95f8b68bd41 ! 17: 17c77ceba01 submodule--helper: fix a configure_added_submodule() leak
@@ builtin/submodule--helper.c: static void configure_added_submodule(struct add_da
* current configured pathspec, set the submodule's active flag
## t/t7413-submodule-is-active.sh ##
-@@ t/t7413-submodule-is-active.sh: This test verifies that `test-tool submodule is-active` correctly identifies
- submodules which are "active" and interesting to the user.
+@@ t/t7413-submodule-is-active.sh: This is a unit test of the submodule.c is_submodule_active() function,
+ which is also indirectly tested elsewhere.
'
+TEST_PASSES_SANITIZE_LEAK=true
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v5 01/17] submodule--helper: fix a leak in "clone_submodule"
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
` (16 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak of the "clone_data_path" variable that we copy or
derive from the "struct module_clone_data" in clone_submodule(). This
code was refactored in preceding commits, but the leak has been with
us since f8eaa0ba98b (submodule--helper, module_clone: always operate
on absolute paths, 2016-03-31).
For the "else" case we don't need to xstrdup() the "clone_data->path",
and we don't need to free our own "clone_data_path". We can therefore
assign the "clone_data->path" to our own "clone_data_path" right away,
and only override it (and remember to free it!) if we need to
xstrfmt() a replacement.
In the case of the module_clone() caller it's from "argv", and doesn't
need to be free'd, and in the case of the add_submodule() caller we
get a pointer to "sm_path", which doesn't need to be directly free'd
either.
Fixing this leak makes several tests pass, so let's mark them as
passing with TEST_PASSES_SANITIZE_LEAK=true.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 10 +++++-----
t/t1500-rev-parse.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 ++
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 ++
6 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5bc9cc41369..d7eaedee491 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1592,13 +1592,12 @@ static int clone_submodule(const struct module_clone_data *clone_data,
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *clone_data_path;
+ const char *clone_data_path = clone_data->path;
+ char *to_free = NULL;
if (!is_absolute_path(clone_data->path))
- clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
- clone_data->path);
- else
- clone_data_path = xstrdup(clone_data->path);
+ clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
+ clone_data->path);
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
die(_("refusing to create/use '%s' in another submodule's "
@@ -1683,6 +1682,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
free(sm_gitdir);
free(p);
+ free(to_free);
return 0;
}
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 1c2df08333b..0e13bcb4ebb 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -4,6 +4,7 @@ test_description='test git rev-parse'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_one () {
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 3153a0d8910..12e67e187ef 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -8,6 +8,7 @@ test_description='git rev-list involving submodules that this repo has'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
index f2e7df59cf2..3269298197c 100755
--- a/t/t7414-submodule-mistakes.sh
+++ b/t/t7414-submodule-mistakes.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='handling of common mistakes people may make with submodules'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create embedded repository' '
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index 3fcb44767f5..f5426a8e589 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -2,6 +2,7 @@
test_description='git status for submodule'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_create_repo_with_commit () {
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
index ed2653d46fe..92462a22374 100755
--- a/t/t7507-commit-verbose.sh
+++ b/t/t7507-commit-verbose.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='verbose commit template'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
write_script "check-for-diff" <<\EOF &&
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
` (15 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in 1012a5cbc3f (submodule--helper
run-update-procedure: learn --remote, 2022-03-04), we need to free()
the xstrdup()'d string. This gets e.g. t/t7419-submodule-set-branch.sh
closer to passing under SANITIZE=leak.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d7eaedee491..d958da7dddc 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2437,6 +2437,8 @@ static int update_submodule(struct update_data *update_data)
const char *branch = remote_submodule_branch(update_data->sm_path);
char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ free(remote_name);
+
if (!update_data->nofetch) {
if (fetch_in_submodule(update_data->sm_path, update_data->depth,
0, NULL))
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 03/17] submodule--helper: fix most "struct pathspec" memory leaks
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-03 22:59 ` Glen Choo
2022-08-02 15:54 ` [PATCH v5 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
` (14 subsequent siblings)
17 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call clear_pathspec() at the end of various functions that work with
and allocate a "struct pathspec".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 74 +++++++++++++++++++++++++------------
1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d958da7dddc..92d32f2877f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -367,7 +367,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
static int module_foreach(int argc, const char **argv, const char *prefix)
{
struct foreach_cb info = FOREACH_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_foreach_options[] = {
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
@@ -379,12 +379,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_foreach_options,
git_submodule_helper_usage, 0);
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.argc = argc;
info.argv = argv;
@@ -392,7 +393,10 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int starts_with_dot_slash(const char *const path)
@@ -522,7 +526,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_init(int argc, const char **argv, const char *prefix)
{
struct init_cb info = INIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_init_options[] = {
@@ -533,12 +537,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
N_("git submodule init [<options>] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_init_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
/*
* If there are no path args and submodule.active is set then,
@@ -553,7 +558,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, init_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct status_cb {
@@ -700,7 +708,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
static int module_status(int argc, const char **argv, const char *prefix)
{
struct status_cb info = STATUS_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_status_options[] = {
@@ -713,12 +721,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_status_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -726,7 +735,10 @@ static int module_status(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, status_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_cb {
@@ -1265,7 +1277,7 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_sync(int argc, const char **argv, const char *prefix)
{
struct sync_cb info = SYNC_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int recursive = 0;
@@ -1279,12 +1291,13 @@ static int module_sync(int argc, const char **argv, const char *prefix)
N_("git submodule sync [--quiet] [--recursive] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_sync_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1294,7 +1307,10 @@ static int module_sync(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, sync_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct deinit_cb {
@@ -1403,7 +1419,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
static int module_deinit(int argc, const char **argv, const char *prefix)
{
struct deinit_cb info = DEINIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int force = 0;
@@ -1418,6 +1434,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_deinit_options,
git_submodule_helper_usage, 0);
@@ -1432,7 +1449,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
die(_("Use '--all' if you really want to deinitialize all submodules"));
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1442,7 +1459,10 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, deinit_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_clone_data {
@@ -2531,7 +2551,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2608,8 +2628,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
opt.update_strategy.type = opt.update_default;
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
- list_objects_filter_release(&filter_options);
- return 1;
+ ret = 1;
+ goto cleanup;
}
if (pathspec.nr)
@@ -2620,8 +2640,10 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0)
- return 1;
+ &pathspec, &list) < 0) {
+ ret = 1;
+ goto cleanup;
+ }
/*
* If there are no path args and submodule.active is set then,
@@ -2638,7 +2660,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
}
ret = update_submodules(&opt);
+cleanup:
list_objects_filter_release(&filter_options);
+ clear_pathspec(&pathspec);
return ret;
}
@@ -2722,7 +2746,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
{
int i;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
struct option embed_gitdir_options[] = {
@@ -2737,17 +2761,21 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
N_("git submodule absorbgitdirs [<options>] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
for (i = 0; i < list.nr; i++)
absorb_git_dir_into_superproject(list.entries[i]->name, flags);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int module_config(int argc, const char **argv, const char *prefix)
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v5 03/17] submodule--helper: fix most "struct pathspec" memory leaks
2022-08-02 15:54 ` [PATCH v5 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-03 22:59 ` Glen Choo
2022-08-04 7:04 ` Ævar Arnfjörð Bjarmason
0 siblings, 1 reply; 186+ messages in thread
From: Glen Choo @ 2022-08-03 22:59 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Call clear_pathspec() at the end of various functions that work with
> and allocate a "struct pathspec".
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 74 +++++++++++++++++++++++++------------
> 1 file changed, 51 insertions(+), 23 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index d958da7dddc..92d32f2877f 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -367,7 +367,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
> static int module_foreach(int argc, const char **argv, const char *prefix)
> {
> struct foreach_cb info = FOREACH_CB_INIT;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
Out of curiousity, does this zero-initialization do anything for us
leaks-wise?
> struct module_list list = MODULE_LIST_INIT;
> struct option module_foreach_options[] = {
> OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
> @@ -379,12 +379,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
> N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
> NULL
> };
> + int ret = 1;
>
> argc = parse_options(argc, argv, prefix, module_foreach_options,
> git_submodule_helper_usage, 0);
>
> if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
> - return 1;
> + goto cleanup;
>
> info.argc = argc;
> info.argv = argv;
> @@ -392,7 +393,10 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
>
> for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
>
> - return 0;
> + ret = 0;
> +cleanup:
> + clear_pathspec(&pathspec);
> + return ret;
> }
>
> static int starts_with_dot_slash(const char *const path)
> @@ -522,7 +526,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
> static int module_init(int argc, const char **argv, const char *prefix)
> {
> struct init_cb info = INIT_CB_INIT;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct module_list list = MODULE_LIST_INIT;
> int quiet = 0;
> struct option module_init_options[] = {
> @@ -533,12 +537,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
> N_("git submodule init [<options>] [<path>]"),
> NULL
> };
> + int ret = 1;
>
> argc = parse_options(argc, argv, prefix, module_init_options,
> git_submodule_helper_usage, 0);
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> - return 1;
> + goto cleanup;
>
> /*
> * If there are no path args and submodule.active is set then,
> @@ -553,7 +558,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
>
> for_each_listed_submodule(&list, init_submodule_cb, &info);
>
> - return 0;
> + ret = 0;
> +cleanup:
> + clear_pathspec(&pathspec);
> + return ret;
> }
>
> struct status_cb {
> @@ -700,7 +708,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
> static int module_status(int argc, const char **argv, const char *prefix)
> {
> struct status_cb info = STATUS_CB_INIT;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct module_list list = MODULE_LIST_INIT;
> int quiet = 0;
> struct option module_status_options[] = {
> @@ -713,12 +721,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
> N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
> NULL
> };
> + int ret = 1;
>
> argc = parse_options(argc, argv, prefix, module_status_options,
> git_submodule_helper_usage, 0);
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> - return 1;
> + goto cleanup;
>
> info.prefix = prefix;
> if (quiet)
> @@ -726,7 +735,10 @@ static int module_status(int argc, const char **argv, const char *prefix)
>
> for_each_listed_submodule(&list, status_submodule_cb, &info);
>
> - return 0;
> + ret = 0;
> +cleanup:
> + clear_pathspec(&pathspec);
> + return ret;
> }
>
> struct module_cb {
> @@ -1265,7 +1277,7 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
> static int module_sync(int argc, const char **argv, const char *prefix)
> {
> struct sync_cb info = SYNC_CB_INIT;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct module_list list = MODULE_LIST_INIT;
> int quiet = 0;
> int recursive = 0;
> @@ -1279,12 +1291,13 @@ static int module_sync(int argc, const char **argv, const char *prefix)
> N_("git submodule sync [--quiet] [--recursive] [<path>]"),
> NULL
> };
> + int ret = 1;
>
> argc = parse_options(argc, argv, prefix, module_sync_options,
> git_submodule_helper_usage, 0);
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> - return 1;
> + goto cleanup;
>
> info.prefix = prefix;
> if (quiet)
> @@ -1294,7 +1307,10 @@ static int module_sync(int argc, const char **argv, const char *prefix)
>
> for_each_listed_submodule(&list, sync_submodule_cb, &info);
>
> - return 0;
> + ret = 0;
> +cleanup:
> + clear_pathspec(&pathspec);
> + return ret;
> }
>
> struct deinit_cb {
> @@ -1403,7 +1419,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
> static int module_deinit(int argc, const char **argv, const char *prefix)
> {
> struct deinit_cb info = DEINIT_CB_INIT;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct module_list list = MODULE_LIST_INIT;
> int quiet = 0;
> int force = 0;
> @@ -1418,6 +1434,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
> N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
> NULL
> };
> + int ret = 1;
>
> argc = parse_options(argc, argv, prefix, module_deinit_options,
> git_submodule_helper_usage, 0);
> @@ -1432,7 +1449,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
> die(_("Use '--all' if you really want to deinitialize all submodules"));
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> - return 1;
> + goto cleanup;
>
> info.prefix = prefix;
> if (quiet)
> @@ -1442,7 +1459,10 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
>
> for_each_listed_submodule(&list, deinit_submodule_cb, &info);
>
> - return 0;
> + ret = 0;
> +cleanup:
> + clear_pathspec(&pathspec);
> + return ret;
> }
>
> struct module_clone_data {
> @@ -2531,7 +2551,7 @@ static int update_submodules(struct update_data *update_data)
>
> static int module_update(int argc, const char **argv, const char *prefix)
> {
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct update_data opt = UPDATE_DATA_INIT;
> struct list_objects_filter_options filter_options = { 0 };
> int ret;
> @@ -2608,8 +2628,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
> opt.update_strategy.type = opt.update_default;
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
> - list_objects_filter_release(&filter_options);
> - return 1;
> + ret = 1;
> + goto cleanup;
> }
>
> if (pathspec.nr)
> @@ -2620,8 +2640,10 @@ static int module_update(int argc, const char **argv, const char *prefix)
> struct init_cb info = INIT_CB_INIT;
>
> if (module_list_compute(argc, argv, opt.prefix,
> - &pathspec, &list) < 0)
> - return 1;
> + &pathspec, &list) < 0) {
> + ret = 1;
> + goto cleanup;
> + }
>
> /*
> * If there are no path args and submodule.active is set then,
> @@ -2638,7 +2660,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
> }
>
> ret = update_submodules(&opt);
> +cleanup:
> list_objects_filter_release(&filter_options);
> + clear_pathspec(&pathspec);
> return ret;
> }
>
> @@ -2722,7 +2746,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
> static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
> {
> int i;
> - struct pathspec pathspec;
> + struct pathspec pathspec = { 0 };
> struct module_list list = MODULE_LIST_INIT;
> unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
> struct option embed_gitdir_options[] = {
> @@ -2737,17 +2761,21 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
> N_("git submodule absorbgitdirs [<options>] [<path>...]"),
> NULL
> };
> + int ret = 1;
>
> argc = parse_options(argc, argv, prefix, embed_gitdir_options,
> git_submodule_helper_usage, 0);
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> - return 1;
> + goto cleanup;
>
> for (i = 0; i < list.nr; i++)
> absorb_git_dir_into_superproject(list.entries[i]->name, flags);
>
> - return 0;
> + ret = 0;
> +cleanup:
> + clear_pathspec(&pathspec);
> + return ret;
> }
>
> static int module_config(int argc, const char **argv, const char *prefix)
> --
> 2.37.1.1233.ge8b09efaedc
^ permalink raw reply [flat|nested] 186+ messages in thread
* Re: [PATCH v5 03/17] submodule--helper: fix most "struct pathspec" memory leaks
2022-08-03 22:59 ` Glen Choo
@ 2022-08-04 7:04 ` Ævar Arnfjörð Bjarmason
0 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-04 7:04 UTC (permalink / raw)
To: Glen Choo; +Cc: git, Junio C Hamano, Atharva Raykar, Prathamesh Chavan
On Wed, Aug 03 2022, Glen Choo wrote:
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> Call clear_pathspec() at the end of various functions that work with
>> and allocate a "struct pathspec".
>>
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> ---
>> builtin/submodule--helper.c | 74 +++++++++++++++++++++++++------------
>> 1 file changed, 51 insertions(+), 23 deletions(-)
>>
>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index d958da7dddc..92d32f2877f 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -367,7 +367,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
>> static int module_foreach(int argc, const char **argv, const char *prefix)
>> {
>> struct foreach_cb info = FOREACH_CB_INIT;
>> - struct pathspec pathspec;
>> + struct pathspec pathspec = { 0 };
>
> Out of curiousity, does this zero-initialization do anything for us
> leaks-wise?
No, because if we leak module_list_compute() must have filled the
pathspec with something it allocated, but...
>> struct module_list list = MODULE_LIST_INIT;
>> struct option module_foreach_options[] = {
>> OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
>> @@ -379,12 +379,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
>> N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
>> NULL
>> };
>> + int ret = 1;
>>
>> argc = parse_options(argc, argv, prefix, module_foreach_options,
>> git_submodule_helper_usage, 0);
>>
>> if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
>> - return 1;
>> + goto cleanup;
...if we don't initialize it then we can't "goto cleanup".
Now, right now this is redundant, we could just "return 1", as we don't
have a pathspec yet.
But it's generally worth just using the same "cleanup" pattern
everywhere, and not worrying about in your cleanunp code that you only
init'd N/TOTAL variables already.
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v5 04/17] submodule--helper: "struct pathspec" memory leak in module_update()
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (2 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
` (13 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
The module_update() function calls module_list_compute() twice, which
in turn will reset the "struct pathspec" passed to it. Let's instead
track two of them, and clear them both.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 92d32f2877f..dd9a62d139d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2552,6 +2552,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec = { 0 };
+ struct pathspec pathspec2 = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2640,7 +2641,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0) {
+ &pathspec2, &list) < 0) {
ret = 1;
goto cleanup;
}
@@ -2663,6 +2664,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
cleanup:
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
+ clear_pathspec(&pathspec2);
return ret;
}
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (3 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
` (12 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24) and 3c3558f0953 (submodule--helper: run
update using child process struct, 2022-03-15) by not allocating
memory in the first place.
The "dir" member of "struct child_process" will not be modified by
that API, and it's declared to be "const char *". So let's not
needlessly duplicate these strings.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index dd9a62d139d..3f79908b203 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2131,7 +2131,7 @@ static int is_tip_reachable(const char *path, struct object_id *oid)
char *hex = oid_to_hex(oid);
cp.git_cmd = 1;
- cp.dir = xstrdup(path);
+ cp.dir = path;
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
@@ -2149,7 +2149,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
- cp.dir = xstrdup(module_path);
+ cp.dir = module_path;
strvec_push(&cp.args, "fetch");
if (quiet)
@@ -2201,7 +2201,7 @@ static int run_update_command(struct update_data *ud, int subforce)
}
strvec_push(&cp.args, oid);
- cp.dir = xstrdup(ud->sm_path);
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
if (run_command(&cp)) {
int ret;
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 06/17] submodule--helper: add and use *_release() functions
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (4 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
` (11 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add release functions for "struct module_list", "struct
submodule_update_clone" and "struct update_data".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 28 +++++++++++++++++++++++++++-
t/t6134-pathspec-in-submodule.sh | 1 +
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3f79908b203..8e9ef58f8be 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -160,6 +160,11 @@ struct module_list {
};
#define MODULE_LIST_INIT { 0 }
+static void module_list_release(struct module_list *ml)
+{
+ free(ml->entries);
+}
+
static int module_list_compute(int argc, const char **argv,
const char *prefix,
struct pathspec *pathspec,
@@ -222,7 +227,7 @@ static void module_list_active(struct module_list *list)
active_modules.entries[active_modules.nr++] = ce;
}
- free(list->entries);
+ module_list_release(list);
*list = active_modules;
}
@@ -395,6 +400,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -560,6 +566,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -737,6 +744,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1309,6 +1317,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1461,6 +1470,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1836,6 +1846,12 @@ struct submodule_update_clone {
};
#define SUBMODULE_UPDATE_CLONE_INIT { 0 }
+static void submodule_update_clone_release(struct submodule_update_clone *suc)
+{
+ free(suc->update_clone);
+ free(suc->failed_clones);
+}
+
struct update_data {
const char *prefix;
const char *displaypath;
@@ -1874,6 +1890,11 @@ struct update_data {
.max_jobs = 1, \
}
+static void update_data_release(struct update_data *ud)
+{
+ module_list_release(&ud->list);
+}
+
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
struct strbuf *out, const char *displaypath)
{
@@ -2545,6 +2566,7 @@ static int update_submodules(struct update_data *update_data)
}
cleanup:
+ submodule_update_clone_release(&suc);
string_list_clear(&update_data->references, 0);
return ret;
}
@@ -2642,6 +2664,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
if (module_list_compute(argc, argv, opt.prefix,
&pathspec2, &list) < 0) {
+ module_list_release(&list);
ret = 1;
goto cleanup;
}
@@ -2658,10 +2681,12 @@ static int module_update(int argc, const char **argv, const char *prefix)
info.flags |= OPT_QUIET;
for_each_listed_submodule(&list, init_submodule_cb, &info);
+ module_list_release(&list);
}
ret = update_submodules(&opt);
cleanup:
+ update_data_release(&opt);
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
clear_pathspec(&pathspec2);
@@ -2777,6 +2802,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
clear_pathspec(&pathspec);
+ module_list_release(&list);
return ret;
}
diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh
index 0f1cb49cedc..3a241f259de 100755
--- a/t/t6134-pathspec-in-submodule.sh
+++ b/t/t6134-pathspec-in-submodule.sh
@@ -2,6 +2,7 @@
test_description='test case exclude pathspec'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a submodule' '
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 07/17] submodule--helper: fix "errmsg_str" memory leak
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (5 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
` (10 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak introduced in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13), we sometimes append
to the "errmsg", and need to free the "struct strbuf".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 8e9ef58f8be..68bf0f9178f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -980,6 +980,7 @@ static void generate_submodule_summary(struct summary_cb *info,
free(displaypath);
free(src_abbrev);
free(dst_abbrev);
+ strbuf_release(&errmsg);
}
static void prepare_submodule_summary(struct summary_cb *info,
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (6 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-03 23:10 ` Glen Choo
2022-08-02 15:54 ` [PATCH v5 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
` (9 subsequent siblings)
17 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix leaks in "struct module_cb_list" and the "struct module_cb" which
it contains, these fixes leaks in e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).
The "sm_path" should always have been a "char *", not a "const
char *", we always create it with xstrdup().
We can't mark any tests passing passing with SANITIZE=leak using
"TEST_PASSES_SANITIZE_LEAK=true" as a result of this change, but
"t7401-submodule-summary.sh" gets closer to passing as a result of
this change.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 68bf0f9178f..f332627d19e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -755,16 +755,34 @@ struct module_cb {
struct object_id oid_src;
struct object_id oid_dst;
char status;
- const char *sm_path;
+ char *sm_path;
};
#define MODULE_CB_INIT { 0 }
+static void module_cb_release(struct module_cb *mcb)
+{
+ free(mcb->sm_path);
+}
+
struct module_cb_list {
struct module_cb **entries;
int alloc, nr;
};
#define MODULE_CB_LIST_INIT { 0 }
+static void module_cb_list_release(struct module_cb_list *mcbl)
+{
+ int i;
+
+ for (i = 0; i < mcbl->nr; i++) {
+ struct module_cb *mcb = mcbl->entries[i];
+
+ module_cb_release(mcb);
+ free(mcb);
+ }
+ free(mcbl->entries);
+}
+
struct summary_cb {
int argc;
const char **argv;
@@ -1108,6 +1126,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
cleanup:
strvec_clear(&diff_args);
release_revisions(&rev);
+ module_cb_list_release(&list);
return ret;
}
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v5 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks
2022-08-02 15:54 ` [PATCH v5 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
@ 2022-08-03 23:10 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-08-03 23:10 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Fix leaks in "struct module_cb_list" and the "struct module_cb" which
> it contains, these fixes leaks in e83e3333b57 (submodule: port
s/fixes/fix
The diff itself LGTM.
> submodule subcommand 'summary' from shell to C, 2020-08-13).
>
> The "sm_path" should always have been a "char *", not a "const
> char *", we always create it with xstrdup().
>
> We can't mark any tests passing passing with SANITIZE=leak using
> "TEST_PASSES_SANITIZE_LEAK=true" as a result of this change, but
> "t7401-submodule-summary.sh" gets closer to passing as a result of
> this change.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 21 ++++++++++++++++++++-
> 1 file changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 68bf0f9178f..f332627d19e 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -755,16 +755,34 @@ struct module_cb {
> struct object_id oid_src;
> struct object_id oid_dst;
> char status;
> - const char *sm_path;
> + char *sm_path;
> };
> #define MODULE_CB_INIT { 0 }
>
> +static void module_cb_release(struct module_cb *mcb)
> +{
> + free(mcb->sm_path);
> +}
> +
> struct module_cb_list {
> struct module_cb **entries;
> int alloc, nr;
> };
> #define MODULE_CB_LIST_INIT { 0 }
>
> +static void module_cb_list_release(struct module_cb_list *mcbl)
> +{
> + int i;
> +
> + for (i = 0; i < mcbl->nr; i++) {
> + struct module_cb *mcb = mcbl->entries[i];
> +
> + module_cb_release(mcb);
> + free(mcb);
> + }
> + free(mcbl->entries);
> +}
> +
> struct summary_cb {
> int argc;
> const char **argv;
> @@ -1108,6 +1126,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
> cleanup:
> strvec_clear(&diff_args);
> release_revisions(&rev);
> + module_cb_list_release(&list);
> return ret;
> }
>
> --
> 2.37.1.1233.ge8b09efaedc
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v5 09/17] submodule--helper: fix a leak with repo_clear()
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (7 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
` (8 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call repo_clear() in ensure_core_worktree() to free the "struct
repository". Fixes a leak that's been here since
74d4731da1f (submodule--helper: replace connect-gitdir-workingtree by
ensure-core-worktree, 2018-08-13).
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f332627d19e..4e964a2c29c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2396,6 +2396,7 @@ static int ensure_core_worktree(const char *path)
strbuf_release(&sb);
}
+ repo_clear(&subrepo);
return 0;
}
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule()
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (8 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
` (7 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in the get_default_remote_submodule() function added
in a77c3fcb5ec (submodule--helper: get remote names from any
repository, 2022-03-04), we need to repo_clear() the submodule we
initialize.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4e964a2c29c..902349976da 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -62,9 +62,13 @@ static char *repo_get_default_remote(struct repository *repo)
static char *get_default_remote_submodule(const char *module_path)
{
struct repository subrepo;
+ char *ret;
repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
- return repo_get_default_remote(&subrepo);
+ ret = repo_get_default_remote(&subrepo);
+ repo_clear(&subrepo);
+
+ return ret;
}
static char *get_default_remote(void)
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 11/17] submodule--helper: fix "reference" leak
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (9 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
` (6 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
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
31224cbdc72 (clone: recursive and reference option triggers submodule
alternates, 2016-08-17) and 8c8195e9c3e (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 <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 902349976da..a5b0b3859c5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1568,7 +1568,9 @@ static int add_possible_reference_from_superproject(
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
- string_list_append(sas->reference, xstrdup(sb.buf));
+ char *p = strbuf_detach(&sb, NULL);
+
+ string_list_append(sas->reference, p)->util = p;
free(sm_alternate);
} else {
switch (sas->error_mode) {
@@ -1800,6 +1802,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
clone_submodule(&clone_data, &reference);
list_objects_filter_release(&filter_options);
+ string_list_clear(&reference, 1);
return 0;
}
@@ -3033,6 +3036,7 @@ static int add_submodule(const struct add_data *add_data)
char *submod_gitdir_path;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
struct string_list reference = STRING_LIST_INIT_NODUP;
+ int ret = -1;
/* perhaps the path already exists and is already a git repo, else clone it */
if (is_directory(add_data->sm_path)) {
@@ -3088,15 +3092,17 @@ static int add_submodule(const struct add_data *add_data)
clone_data.url = add_data->realrepo;
clone_data.quiet = add_data->quiet;
clone_data.progress = add_data->progress;
- if (add_data->reference_path)
- string_list_append(&reference,
- xstrdup(add_data->reference_path));
+ if (add_data->reference_path) {
+ char *p = xstrdup(add_data->reference_path);
+
+ string_list_append(&reference, p)->util = p;
+ }
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
if (clone_submodule(&clone_data, &reference))
- return -1;
+ goto cleanup;
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -3115,7 +3121,10 @@ static int add_submodule(const struct add_data *add_data)
if (run_command(&cp))
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
}
- return 0;
+ ret = 0;
+cleanup:
+ string_list_clear(&reference, 1);
+ return ret;
}
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 12/17] submodule--helper: fix obscure leak in module_add()
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (10 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
` (5 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix an obscure leak in module_add(), if the "git add" command we were
piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
introduced in a6226fd772b (submodule--helper: convert the bulk of
cmd_add() to C, 2021-08-10).
In fixing it move to a "goto cleanup" pattern, and since we need to
introduce a "ret" variable to do that let's also get rid of the
intermediate "exit_code" variable. The initialization to "-1" in
a6226fd772b has always been redundant, we'd only use the "exit_code"
value after assigning the return value of pipe_command() to it.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a5b0b3859c5..9cc92b4da9e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3284,6 +3284,8 @@ static int module_add(int argc, const char **argv, const char *prefix)
N_("git submodule add [<options>] [--] <repository> [<path>]"),
NULL
};
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 1;
argc = parse_options(argc, argv, prefix, options, usage, 0);
@@ -3333,21 +3335,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
die_on_repo_without_commits(add_data.sm_path);
if (!force) {
- int exit_code = -1;
- struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdout = 1;
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
"--no-warn-embedded-repo", add_data.sm_path, NULL);
- if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+ if ((ret = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
strbuf_complete_line(&sb);
fputs(sb.buf, stderr);
- free(add_data.sm_path);
- return exit_code;
+ goto cleanup;
}
- strbuf_release(&sb);
}
if(!add_data.sm_name)
@@ -3362,15 +3360,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
add_data.progress = !!progress;
add_data.dissociate = !!dissociate;
- if (add_submodule(&add_data)) {
- free(add_data.sm_path);
- return 1;
- }
+ if (add_submodule(&add_data))
+ goto cleanup;
configure_added_submodule(&add_data);
+
+ ret = 0;
+cleanup:
free(add_data.sm_path);
free(to_free);
+ strbuf_release(&sb);
- return 0;
+ return ret;
}
#define SUPPORT_SUPER_PREFIX (1<<0)
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 13/17] submodule--helper: fix a leak in module_add()
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (11 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
` (4 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in module_path(), since a6226fd772b (submodule--helper:
convert the bulk of cmd_add() to C, 2021-08-10), we've been freeing
add_data.sm_path, but in this case we clobbered it, and didn't free
the value we clobbered.
This makes test 28 of "t/t7400-submodule-basic.sh" ("submodule add in
subdirectory") pass when we're compiled with SANITIZE=leak..
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9cc92b4da9e..2fca6d66bb5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3305,8 +3305,12 @@ static int module_add(int argc, const char **argv, const char *prefix)
else
add_data.sm_path = xstrdup(argv[1]);
- if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
- add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
+ char *sm_path = add_data.sm_path;
+
+ add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
+ free(sm_path);
+ }
if (starts_with_dot_dot_slash(add_data.repo) ||
starts_with_dot_slash(add_data.repo)) {
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 14/17] submodule--helper: fix a memory leak in print_status()
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (12 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
` (3 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in print_status(), the compute_rev_name() function
implemented in this file will return a strbuf_detach()'d value, or
NULL.
This leak has existed since this code was added in
a9f8a37584a (submodule: port submodule subcommand 'status' from shell
to C, 2017-10-06), but in 0b5e2ea7cf3 (submodule--helper: don't print
null in 'submodule status', 2018-04-18) we added a "const"
intermediate variable for the return value, that "const" should be
removed.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2fca6d66bb5..0f1846021e6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -590,10 +590,11 @@ static void print_status(unsigned int flags, char state, const char *path,
printf("%c%s %s", state, oid_to_hex(oid), displaypath);
if (state == ' ' || state == '+') {
- const char *name = compute_rev_name(path, oid_to_hex(oid));
+ char *name = compute_rev_name(path, oid_to_hex(oid));
if (name)
printf(" (%s)", name);
+ free(name);
}
printf("\n");
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 15/17] submodule--helper: free some "displaypath" in "struct update_data"
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (13 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-02 15:54 ` [PATCH v5 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
` (2 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Make the update_data_release() function free "displaypath" member when
appropriate. The "displaypath" member is always ours, the "const" on
the "char *" was wrong to begin with.
This leaves a leak of "displaypath" in update_submodule(), which as
we'll see in subsequent commits is harder to deal with than this
trivial fix.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
t/t2403-worktree-move.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 0f1846021e6..79eca6c439b 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1882,7 +1882,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
struct update_data {
const char *prefix;
- const char *displaypath;
+ char *displaypath;
enum submodule_update_type update_default;
struct object_id suboid;
struct string_list references;
@@ -1920,6 +1920,7 @@ struct update_data {
static void update_data_release(struct update_data *ud)
{
+ free(ud->displaypath);
module_list_release(&ud->list);
}
diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh
index a4e1a178e0a..1168e9f9982 100755
--- a/t/t2403-worktree-move.sh
+++ b/t/t2403-worktree-move.sh
@@ -2,6 +2,7 @@
test_description='test git worktree move, remove, lock and unlock'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 1cfa150768d..2859695c6d2 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -6,6 +6,7 @@ This test verifies that `git submodue absorbgitdirs` moves a submodules git
directory into the superproject.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v5 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (14 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-04 18:04 ` Glen Choo
2022-08-02 15:54 ` [PATCH v5 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
17 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24), we clobber the "displaypath" member of
the passed-in "struct update_data" both so that die() messages in this
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
To make managing that clobbering easier let's wrap the
update_submodule() in a new update_submodule_outer() function, which
will do the clobbering and free(to_free) dance for us.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 79eca6c439b..cc8f42ae6df 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2482,13 +2482,6 @@ static int update_submodule(struct update_data *update_data)
{
int ret;
- ret = ensure_core_worktree(update_data->sm_path);
- if (ret)
- return ret;
-
- update_data->displaypath = get_submodule_displaypath(
- update_data->sm_path, update_data->prefix);
-
ret = determine_submodule_update_strategy(the_repository,
update_data->just_cloned,
update_data->sm_path,
@@ -2554,6 +2547,24 @@ static int update_submodule(struct update_data *update_data)
return 0;
}
+static int update_submodule_outer(struct update_data *update_data)
+{
+ char *to_free, *restore = update_data->displaypath;
+ int ret;
+
+ ensure_core_worktree(update_data->sm_path);
+
+ update_data->displaypath = to_free = get_submodule_displaypath(
+ update_data->sm_path, update_data->prefix);
+
+ ret = update_submodule(update_data);
+
+ free(to_free);
+ update_data->displaypath = restore;
+
+ return ret;
+}
+
static int update_submodules(struct update_data *update_data)
{
int i, ret = 0;
@@ -2586,7 +2597,7 @@ static int update_submodules(struct update_data *update_data)
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
- code = update_submodule(update_data);
+ code = update_submodule_outer(update_data);
if (code)
ret = code;
if (code == 128)
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v5 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-08-02 15:54 ` [PATCH v5 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-08-04 18:04 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-08-04 18:04 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
> procedures from C, 2021-08-24), we clobber the "displaypath" member of
> the passed-in "struct update_data" both so that die() messages in this
> update_submodule() function itself can use it, and for the
> run_update_procedure() called within this function.
>
> To make managing that clobbering easier let's wrap the
> update_submodule() in a new update_submodule_outer() function, which
> will do the clobbering and free(to_free) dance for us.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 27 +++++++++++++++++++--------
> 1 file changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 79eca6c439b..cc8f42ae6df 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2482,13 +2482,6 @@ static int update_submodule(struct update_data *update_data)
> {
> int ret;
>
> - ret = ensure_core_worktree(update_data->sm_path);
> - if (ret)
> - return ret;
> -
> - update_data->displaypath = get_submodule_displaypath(
> - update_data->sm_path, update_data->prefix);
> -
> ret = determine_submodule_update_strategy(the_repository,
> update_data->just_cloned,
> update_data->sm_path,
> @@ -2554,6 +2547,24 @@ static int update_submodule(struct update_data *update_data)
> return 0;
> }
>
> +static int update_submodule_outer(struct update_data *update_data)
> +{
> + char *to_free, *restore = update_data->displaypath;
> + int ret;
> +
> + ensure_core_worktree(update_data->sm_path);
> +
> + update_data->displaypath = to_free = get_submodule_displaypath(
> + update_data->sm_path, update_data->prefix);
> +
> + ret = update_submodule(update_data);
> +
> + free(to_free);
> + update_data->displaypath = restore;
> +
> + return ret;
> +}
> +
I haven't tested the alternatives yet, but on first glance using this
*_outer() pattern here seems like overkill. At least two things I can
think of are:
a) Free .displaypath using the "goto cleanup" pattern like we did
elsewhere
...
> static int update_submodules(struct update_data *update_data)
> {
> int i, ret = 0;
> @@ -2586,7 +2597,7 @@ static int update_submodules(struct update_data *update_data)
> update_data->just_cloned = ucd.just_cloned;
> update_data->sm_path = ucd.sub->path;
>
> - code = update_submodule(update_data);
> + code = update_submodule_outer(update_data);
> if (code)
> ret = code;
> if (code == 128)
b) Assign and FREE_AND_NULL() update_data->displaypath here since this
is the only caller and it already does some prep work in this hunk.
I started testing, but then realized that we don't have a
TEST_PASSES_SANITIZE_LEAK=true for this patch, so I'll spend some more
time testing whether these alternatives even work and I'll get back to
you later.
> --
> 2.37.1.1233.ge8b09efaedc
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v5 17/17] submodule--helper: fix a configure_added_submodule() leak
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (15 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:54 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:54 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix config API a memory leak added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06) by using the *_tmp()
variant of git_config_get_string().
In this case we're only checking whether
the (repo|git)_config_get_string() call is telling us that the
"submodule.active" key exists.
As with the preceding commit we'll find many other such patterns in
the codebase if we go fishing. E.g. "git gc" leaks in the code added
in 61f7a383d3b (maintenance: use 'incremental' strategy by default,
2020-10-15). Similar code in "git gc" added in
b08ff1fee00 (maintenance: add --schedule option and config,
2020-09-11) doesn't leak, but we could avoid the malloc() & free() in
that case.
A coccinelle rule to find those would find and fix some leaks, and
cases where we're doing needless malloc() + free()'s but only care
about the key existence, or are copying
the (repo|git)_config_get_string() return value right away.
But as with the preceding commit let's punt on all of that for now,
and just narrowly fix this specific case in submodule--helper.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 ++--
t/t7413-submodule-is-active.sh | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index cc8f42ae6df..60757e871e6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3158,7 +3158,7 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
static void configure_added_submodule(struct add_data *add_data)
{
char *key;
- char *val = NULL;
+ const char *val;
struct child_process add_submod = CHILD_PROCESS_INIT;
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
@@ -3203,7 +3203,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string("submodule.active", &val)) {
+ if (!git_config_get_string_tmp("submodule.active", &val)) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index ede6f02dbd5..4dc7d089423 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -9,6 +9,7 @@ This is a unit test of the submodule.c is_submodule_active() function,
which is also indirectly tested elsewhere.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
--
2.37.1.1233.ge8b09efaedc
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 00/17] submodule--helper: fix memory leaks
2022-08-02 15:54 ` [PATCH v5 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (16 preceding siblings ...)
2022-08-02 15:54 ` [PATCH v5 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
` (17 more replies)
17 siblings, 18 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
This series fixes all of the memory leaks in
builtin/submodule--helper.c that our test suite spots, except for
those where the leak is downstream of cmd_submodule__helper() and
caused by code that's not in builtin/submodule--helper.c (e.g. leaks
in the object or config APIs, and in submodule.c).
This re-roll is on top of the just-now re-rolled v3 of the base
topic[1].
Changes in v6:
* Rebase on top of the base topic.
* Mark new tests as leak-free within this series (due to changes on
"master")
* Various minor changes, see range-diff below.
1. https://lore.kernel.org/git/cover-v3-00.32-00000000000-20220821T130231Z-avarab@gmail.com/
Ævar Arnfjörð Bjarmason (17):
submodule--helper: fix a leak in "clone_submodule"
submodule--helper: fix trivial get_default_remote_submodule() leak
submodule--helper: fix most "struct pathspec" memory leaks
submodule--helper: "struct pathspec" memory leak in module_update()
submodule--helper: don't leak {run,capture}_command() cp.dir argument
submodule--helper: add and use *_release() functions
submodule--helper: fix "errmsg_str" memory leak
submodule--helper: fix "sm_path" and other "module_cb_list" leaks
submodule--helper: fix a leak with repo_clear()
submodule--helper: fix a memory leak in get_default_remote_submodule()
submodule--helper: fix "reference" leak
submodule--helper: fix obscure leak in module_add()
submodule--helper: fix a leak in module_add()
submodule--helper: fix a memory leak in print_status()
submodule--helper: free some "displaypath" in "struct update_data"
submodule--helper: free rest of "displaypath" in "struct update_data"
submodule--helper: fix a configure_added_submodule() leak
builtin/submodule--helper.c | 239 +++++++++++++++++++++--------
t/t1500-rev-parse.sh | 1 +
t/t2403-worktree-move.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t6134-pathspec-in-submodule.sh | 1 +
t/t7401-submodule-summary.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
t/t7413-submodule-is-active.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 +
t/t7419-submodule-set-branch.sh | 1 +
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 +
12 files changed, 187 insertions(+), 65 deletions(-)
Range-diff against v5:
1: 118e965d401 = 1: 0f60ea6f7c6 submodule--helper: fix a leak in "clone_submodule"
2: d885e1dd59a ! 2: c14e00f39cb submodule--helper: fix trivial get_default_remote_submodule() leak
@@ Commit message
## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
- const char *branch = remote_submodule_branch(update_data->sm_path);
- char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ return code;
+ remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ free(remote_name);
+
3: 1f90348d61f ! 3: a2ecdb301d3 submodule--helper: fix most "struct pathspec" memory leaks
@@ Commit message
Call clear_pathspec() at the end of various functions that work with
and allocate a "struct pathspec".
+ In some cases the zero-initialization here isn't strictly needed, but
+ as we're moving to a "goto cleanup" pattern let's make sure that it's
+ safe to call clear_pathspec(), we don't want the data to be
+ uninitialized.
+
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
4: f768ff2e34d = 4: 8fc3dad316e submodule--helper: "struct pathspec" memory leak in module_update()
5: 509133c37fa ! 5: a3886d36366 submodule--helper: don't leak {run,capture}_command() cp.dir argument
@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
- cp.dir = xstrdup(ud->sm_path);
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
- if (run_command(&cp)) {
- int ret;
+ if ((ret = run_command(&cp))) {
+ switch (ud->update_strategy.type) {
6: 25377f1d06c = 6: 173dbb7d8fc submodule--helper: add and use *_release() functions
7: 1a85057cd0c = 7: cd394814370 submodule--helper: fix "errmsg_str" memory leak
8: 3c4f734e958 ! 8: 2110b991913 submodule--helper: fix "sm_path" and other "module_cb_list" leaks
@@ Commit message
submodule--helper: fix "sm_path" and other "module_cb_list" leaks
Fix leaks in "struct module_cb_list" and the "struct module_cb" which
- it contains, these fixes leaks in e83e3333b57 (submodule: port
- submodule subcommand 'summary' from shell to C, 2020-08-13).
+ it contains, these fix leaks in e83e3333b57 (submodule: port submodule
+ subcommand 'summary' from shell to C, 2020-08-13).
The "sm_path" should always have been a "char *", not a "const
char *", we always create it with xstrdup().
@@ builtin/submodule--helper.c: static int compute_summary_module_list(struct objec
return ret;
}
+
+ ## t/t7401-submodule-summary.sh ##
+@@ t/t7401-submodule-summary.sh: This test script tries to verify the sanity of summary subcommand of git submodu
+ # various reasons, one of them being that there are lots of commands taking place
+ # outside of 'test_expect_success' block, which is no longer in good-style.
+
++TEST_PASSES_SANITIZE_LEAK=true
+ . ./test-lib.sh
+
+ add_file () {
9: 3aebff9f8e3 = 9: a0d1a03166f submodule--helper: fix a leak with repo_clear()
10: 38345ec76bc ! 10: 84f162f320b submodule--helper: fix a memory leak in get_default_remote_submodule()
@@ Commit message
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static char *repo_get_default_remote(struct repository *repo)
- static char *get_default_remote_submodule(const char *module_path)
+@@ builtin/submodule--helper.c: static int repo_get_default_remote(struct repository *repo, char **default_remot
+ static int get_default_remote_submodule(const char *module_path, char **default_remote)
{
struct repository subrepo;
-+ char *ret;
++ int ret;
- repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
-- return repo_get_default_remote(&subrepo);
-+ ret = repo_get_default_remote(&subrepo);
+ if (repo_submodule_init(&subrepo, the_repository, module_path,
+ null_oid()) < 0)
+ return die_message(_("could not get a repository handle for submodule '%s'"),
+ module_path);
+- return repo_get_default_remote(&subrepo, default_remote);
++ ret = repo_get_default_remote(&subrepo, default_remote);
+ repo_clear(&subrepo);
+
+ return ret;
11: 4b1e5ced969 = 11: dc5e8504354 submodule--helper: fix "reference" leak
12: e74c396073b = 12: 50d58bfb19b submodule--helper: fix obscure leak in module_add()
13: 71a56c59864 = 13: 56590508180 submodule--helper: fix a leak in module_add()
14: 2429db2f1c7 = 14: 38ceb0a36ab submodule--helper: fix a memory leak in print_status()
15: 613d077c4ec ! 15: f3cf49dd029 submodule--helper: free some "displaypath" in "struct update_data"
@@ t/t7412-submodule-absorbgitdirs.sh: This test verifies that `git submodue absorb
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
+
+ ## t/t7419-submodule-set-branch.sh ##
+@@ t/t7419-submodule-set-branch.sh: This test verifies that the set-branch subcommand of git-submodule is working
+ as expected.
+ '
+
++TEST_PASSES_SANITIZE_LEAK=true
+ TEST_NO_CREATE_REPO=1
+ . ./test-lib.sh
+
16: 8f150a81507 ! 16: a99a7736fab submodule--helper: free rest of "displaypath" in "struct update_data"
@@ builtin/submodule--helper.c: static int update_submodules(struct update_data *up
- code = update_submodule(update_data);
+ code = update_submodule_outer(update_data);
- if (code)
- ret = code;
- if (code == 128)
+ if (!code)
+ continue;
+ ret = code;
17: 17c77ceba01 = 17: ec0b02d8ee2 submodule--helper: fix a configure_added_submodule() leak
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v6 01/17] submodule--helper: fix a leak in "clone_submodule"
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
` (16 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak of the "clone_data_path" variable that we copy or
derive from the "struct module_clone_data" in clone_submodule(). This
code was refactored in preceding commits, but the leak has been with
us since f8eaa0ba98b (submodule--helper, module_clone: always operate
on absolute paths, 2016-03-31).
For the "else" case we don't need to xstrdup() the "clone_data->path",
and we don't need to free our own "clone_data_path". We can therefore
assign the "clone_data->path" to our own "clone_data_path" right away,
and only override it (and remember to free it!) if we need to
xstrfmt() a replacement.
In the case of the module_clone() caller it's from "argv", and doesn't
need to be free'd, and in the case of the add_submodule() caller we
get a pointer to "sm_path", which doesn't need to be directly free'd
either.
Fixing this leak makes several tests pass, so let's mark them as
passing with TEST_PASSES_SANITIZE_LEAK=true.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 10 +++++-----
t/t1500-rev-parse.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 ++
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 ++
6 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e489a0f6b10..2774f1884b0 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1590,13 +1590,12 @@ static int clone_submodule(const struct module_clone_data *clone_data,
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *clone_data_path;
+ const char *clone_data_path = clone_data->path;
+ char *to_free = NULL;
if (!is_absolute_path(clone_data->path))
- clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
- clone_data->path);
- else
- clone_data_path = xstrdup(clone_data->path);
+ clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
+ clone_data->path);
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
die(_("refusing to create/use '%s' in another submodule's "
@@ -1681,6 +1680,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
free(sm_gitdir);
free(p);
+ free(to_free);
return 0;
}
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 1c2df08333b..0e13bcb4ebb 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -4,6 +4,7 @@ test_description='test git rev-parse'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_one () {
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 3153a0d8910..12e67e187ef 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -8,6 +8,7 @@ test_description='git rev-list involving submodules that this repo has'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
index f2e7df59cf2..3269298197c 100755
--- a/t/t7414-submodule-mistakes.sh
+++ b/t/t7414-submodule-mistakes.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='handling of common mistakes people may make with submodules'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create embedded repository' '
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index 3fcb44767f5..f5426a8e589 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -2,6 +2,7 @@
test_description='git status for submodule'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_create_repo_with_commit () {
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
index ed2653d46fe..92462a22374 100755
--- a/t/t7507-commit-verbose.sh
+++ b/t/t7507-commit-verbose.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='verbose commit template'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
write_script "check-for-diff" <<\EOF &&
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
` (15 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in 1012a5cbc3f (submodule--helper
run-update-procedure: learn --remote, 2022-03-04), we need to free()
the xstrdup()'d string. This gets e.g. t/t7419-submodule-set-branch.sh
closer to passing under SANITIZE=leak.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2774f1884b0..da9e0016509 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2449,6 +2449,8 @@ static int update_submodule(struct update_data *update_data)
return code;
remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ free(remote_name);
+
if (!update_data->nofetch) {
if (fetch_in_submodule(update_data->sm_path, update_data->depth,
0, NULL))
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 03/17] submodule--helper: fix most "struct pathspec" memory leaks
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
` (14 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call clear_pathspec() at the end of various functions that work with
and allocate a "struct pathspec".
In some cases the zero-initialization here isn't strictly needed, but
as we're moving to a "goto cleanup" pattern let's make sure that it's
safe to call clear_pathspec(), we don't want the data to be
uninitialized.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 74 +++++++++++++++++++++++++------------
1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index da9e0016509..a118f615783 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -379,7 +379,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
static int module_foreach(int argc, const char **argv, const char *prefix)
{
struct foreach_cb info = FOREACH_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_foreach_options[] = {
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
@@ -391,12 +391,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_foreach_options,
git_submodule_helper_usage, 0);
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.argc = argc;
info.argv = argv;
@@ -404,7 +405,10 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int starts_with_dot_slash(const char *const path)
@@ -515,7 +519,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_init(int argc, const char **argv, const char *prefix)
{
struct init_cb info = INIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_init_options[] = {
@@ -526,12 +530,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
N_("git submodule init [<options>] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_init_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
/*
* If there are no path args and submodule.active is set then,
@@ -546,7 +551,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, init_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct status_cb {
@@ -693,7 +701,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
static int module_status(int argc, const char **argv, const char *prefix)
{
struct status_cb info = STATUS_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_status_options[] = {
@@ -706,12 +714,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_status_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -719,7 +728,10 @@ static int module_status(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, status_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_cb {
@@ -1261,7 +1273,7 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_sync(int argc, const char **argv, const char *prefix)
{
struct sync_cb info = SYNC_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int recursive = 0;
@@ -1275,12 +1287,13 @@ static int module_sync(int argc, const char **argv, const char *prefix)
N_("git submodule sync [--quiet] [--recursive] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_sync_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1290,7 +1303,10 @@ static int module_sync(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, sync_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct deinit_cb {
@@ -1399,7 +1415,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
static int module_deinit(int argc, const char **argv, const char *prefix)
{
struct deinit_cb info = DEINIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int force = 0;
@@ -1414,6 +1430,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_deinit_options,
git_submodule_helper_usage, 0);
@@ -1428,7 +1445,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
die(_("Use '--all' if you really want to deinitialize all submodules"));
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1438,7 +1455,10 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, deinit_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_clone_data {
@@ -2541,7 +2561,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2618,8 +2638,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
opt.update_strategy.type = opt.update_default;
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
- list_objects_filter_release(&filter_options);
- return 1;
+ ret = 1;
+ goto cleanup;
}
if (pathspec.nr)
@@ -2630,8 +2650,10 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0)
- return 1;
+ &pathspec, &list) < 0) {
+ ret = 1;
+ goto cleanup;
+ }
/*
* If there are no path args and submodule.active is set then,
@@ -2648,7 +2670,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
}
ret = update_submodules(&opt);
+cleanup:
list_objects_filter_release(&filter_options);
+ clear_pathspec(&pathspec);
return ret;
}
@@ -2732,7 +2756,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
{
int i;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
struct option embed_gitdir_options[] = {
@@ -2747,17 +2771,21 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
N_("git submodule absorbgitdirs [<options>] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
for (i = 0; i < list.nr; i++)
absorb_git_dir_into_superproject(list.entries[i]->name, flags);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int module_config(int argc, const char **argv, const char *prefix)
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 04/17] submodule--helper: "struct pathspec" memory leak in module_update()
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (2 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
` (13 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
The module_update() function calls module_list_compute() twice, which
in turn will reset the "struct pathspec" passed to it. Let's instead
track two of them, and clear them both.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a118f615783..64dc906b5e6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2562,6 +2562,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec = { 0 };
+ struct pathspec pathspec2 = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2650,7 +2651,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0) {
+ &pathspec2, &list) < 0) {
ret = 1;
goto cleanup;
}
@@ -2673,6 +2674,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
cleanup:
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
+ clear_pathspec(&pathspec2);
return ret;
}
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (3 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
` (12 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24) and 3c3558f0953 (submodule--helper: run
update using child process struct, 2022-03-15) by not allocating
memory in the first place.
The "dir" member of "struct child_process" will not be modified by
that API, and it's declared to be "const char *". So let's not
needlessly duplicate these strings.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 64dc906b5e6..5eb6bec4c63 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2129,7 +2129,7 @@ static int is_tip_reachable(const char *path, struct object_id *oid)
char *hex = oid_to_hex(oid);
cp.git_cmd = 1;
- cp.dir = xstrdup(path);
+ cp.dir = path;
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
@@ -2147,7 +2147,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
- cp.dir = xstrdup(module_path);
+ cp.dir = module_path;
strvec_push(&cp.args, "fetch");
if (quiet)
@@ -2200,7 +2200,7 @@ static int run_update_command(struct update_data *ud, int subforce)
}
strvec_push(&cp.args, oid);
- cp.dir = xstrdup(ud->sm_path);
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
if ((ret = run_command(&cp))) {
switch (ud->update_strategy.type) {
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 06/17] submodule--helper: add and use *_release() functions
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (4 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
` (11 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add release functions for "struct module_list", "struct
submodule_update_clone" and "struct update_data".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 28 +++++++++++++++++++++++++++-
t/t6134-pathspec-in-submodule.sh | 1 +
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5eb6bec4c63..fa320eb2edf 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -172,6 +172,11 @@ struct module_list {
};
#define MODULE_LIST_INIT { 0 }
+static void module_list_release(struct module_list *ml)
+{
+ free(ml->entries);
+}
+
static int module_list_compute(int argc, const char **argv,
const char *prefix,
struct pathspec *pathspec,
@@ -234,7 +239,7 @@ static void module_list_active(struct module_list *list)
active_modules.entries[active_modules.nr++] = ce;
}
- free(list->entries);
+ module_list_release(list);
*list = active_modules;
}
@@ -407,6 +412,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -553,6 +559,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -730,6 +737,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1305,6 +1313,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1457,6 +1466,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1834,6 +1844,12 @@ struct submodule_update_clone {
};
#define SUBMODULE_UPDATE_CLONE_INIT { 0 }
+static void submodule_update_clone_release(struct submodule_update_clone *suc)
+{
+ free(suc->update_clone);
+ free(suc->failed_clones);
+}
+
struct update_data {
const char *prefix;
const char *displaypath;
@@ -1872,6 +1888,11 @@ struct update_data {
.max_jobs = 1, \
}
+static void update_data_release(struct update_data *ud)
+{
+ module_list_release(&ud->list);
+}
+
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
struct strbuf *out, const char *displaypath)
{
@@ -2555,6 +2576,7 @@ static int update_submodules(struct update_data *update_data)
}
cleanup:
+ submodule_update_clone_release(&suc);
string_list_clear(&update_data->references, 0);
return ret;
}
@@ -2652,6 +2674,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
if (module_list_compute(argc, argv, opt.prefix,
&pathspec2, &list) < 0) {
+ module_list_release(&list);
ret = 1;
goto cleanup;
}
@@ -2668,10 +2691,12 @@ static int module_update(int argc, const char **argv, const char *prefix)
info.flags |= OPT_QUIET;
for_each_listed_submodule(&list, init_submodule_cb, &info);
+ module_list_release(&list);
}
ret = update_submodules(&opt);
cleanup:
+ update_data_release(&opt);
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
clear_pathspec(&pathspec2);
@@ -2787,6 +2812,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
clear_pathspec(&pathspec);
+ module_list_release(&list);
return ret;
}
diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh
index 0f1cb49cedc..3a241f259de 100755
--- a/t/t6134-pathspec-in-submodule.sh
+++ b/t/t6134-pathspec-in-submodule.sh
@@ -2,6 +2,7 @@
test_description='test case exclude pathspec'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a submodule' '
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 07/17] submodule--helper: fix "errmsg_str" memory leak
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (5 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
` (10 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak introduced in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13), we sometimes append
to the "errmsg", and need to free the "struct strbuf".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fa320eb2edf..42ec6127024 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -973,6 +973,7 @@ static void generate_submodule_summary(struct summary_cb *info,
free(displaypath);
free(src_abbrev);
free(dst_abbrev);
+ strbuf_release(&errmsg);
}
static void prepare_submodule_summary(struct summary_cb *info,
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (6 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
` (9 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix leaks in "struct module_cb_list" and the "struct module_cb" which
it contains, these fix leaks in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13).
The "sm_path" should always have been a "char *", not a "const
char *", we always create it with xstrdup().
We can't mark any tests passing passing with SANITIZE=leak using
"TEST_PASSES_SANITIZE_LEAK=true" as a result of this change, but
"t7401-submodule-summary.sh" gets closer to passing as a result of
this change.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 ++++++++++++++++++++-
t/t7401-submodule-summary.sh | 1 +
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 42ec6127024..ea925178946 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -748,16 +748,34 @@ struct module_cb {
struct object_id oid_src;
struct object_id oid_dst;
char status;
- const char *sm_path;
+ char *sm_path;
};
#define MODULE_CB_INIT { 0 }
+static void module_cb_release(struct module_cb *mcb)
+{
+ free(mcb->sm_path);
+}
+
struct module_cb_list {
struct module_cb **entries;
int alloc, nr;
};
#define MODULE_CB_LIST_INIT { 0 }
+static void module_cb_list_release(struct module_cb_list *mcbl)
+{
+ int i;
+
+ for (i = 0; i < mcbl->nr; i++) {
+ struct module_cb *mcb = mcbl->entries[i];
+
+ module_cb_release(mcb);
+ free(mcb);
+ }
+ free(mcbl->entries);
+}
+
struct summary_cb {
int argc;
const char **argv;
@@ -1104,6 +1122,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
cleanup:
strvec_clear(&diff_args);
release_revisions(&rev);
+ module_cb_list_release(&list);
return ret;
}
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 9c3cc4cf404..542b3331a78 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -17,6 +17,7 @@ This test script tries to verify the sanity of summary subcommand of git submodu
# various reasons, one of them being that there are lots of commands taking place
# outside of 'test_expect_success' block, which is no longer in good-style.
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
add_file () {
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 09/17] submodule--helper: fix a leak with repo_clear()
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (7 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
` (8 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call repo_clear() in ensure_core_worktree() to free the "struct
repository". Fixes a leak that's been here since
74d4731da1f (submodule--helper: replace connect-gitdir-workingtree by
ensure-core-worktree, 2018-08-13).
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ea925178946..b029e109b47 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2399,6 +2399,7 @@ static int ensure_core_worktree(const char *path)
strbuf_release(&sb);
}
+ repo_clear(&subrepo);
return 0;
}
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule()
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (8 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
` (7 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in the get_default_remote_submodule() function added
in a77c3fcb5ec (submodule--helper: get remote names from any
repository, 2022-03-04), we need to repo_clear() the submodule we
initialize.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b029e109b47..3f123f014f9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -65,12 +65,16 @@ static int repo_get_default_remote(struct repository *repo, char **default_remot
static int get_default_remote_submodule(const char *module_path, char **default_remote)
{
struct repository subrepo;
+ int ret;
if (repo_submodule_init(&subrepo, the_repository, module_path,
null_oid()) < 0)
return die_message(_("could not get a repository handle for submodule '%s'"),
module_path);
- return repo_get_default_remote(&subrepo, default_remote);
+ ret = repo_get_default_remote(&subrepo, default_remote);
+ repo_clear(&subrepo);
+
+ return ret;
}
static char *get_default_remote(void)
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 11/17] submodule--helper: fix "reference" leak
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (9 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
` (6 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
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
31224cbdc72 (clone: recursive and reference option triggers submodule
alternates, 2016-08-17) and 8c8195e9c3e (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 <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3f123f014f9..d469c571d52 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1566,7 +1566,9 @@ static int add_possible_reference_from_superproject(
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
- string_list_append(sas->reference, xstrdup(sb.buf));
+ char *p = strbuf_detach(&sb, NULL);
+
+ string_list_append(sas->reference, p)->util = p;
free(sm_alternate);
} else {
switch (sas->error_mode) {
@@ -1798,6 +1800,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
clone_submodule(&clone_data, &reference);
list_objects_filter_release(&filter_options);
+ string_list_clear(&reference, 1);
return 0;
}
@@ -3043,6 +3046,7 @@ static int add_submodule(const struct add_data *add_data)
char *submod_gitdir_path;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
struct string_list reference = STRING_LIST_INIT_NODUP;
+ int ret = -1;
/* perhaps the path already exists and is already a git repo, else clone it */
if (is_directory(add_data->sm_path)) {
@@ -3098,15 +3102,17 @@ static int add_submodule(const struct add_data *add_data)
clone_data.url = add_data->realrepo;
clone_data.quiet = add_data->quiet;
clone_data.progress = add_data->progress;
- if (add_data->reference_path)
- string_list_append(&reference,
- xstrdup(add_data->reference_path));
+ if (add_data->reference_path) {
+ char *p = xstrdup(add_data->reference_path);
+
+ string_list_append(&reference, p)->util = p;
+ }
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
if (clone_submodule(&clone_data, &reference))
- return -1;
+ goto cleanup;
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -3125,7 +3131,10 @@ static int add_submodule(const struct add_data *add_data)
if (run_command(&cp))
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
}
- return 0;
+ ret = 0;
+cleanup:
+ string_list_clear(&reference, 1);
+ return ret;
}
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 12/17] submodule--helper: fix obscure leak in module_add()
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (10 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
` (5 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix an obscure leak in module_add(), if the "git add" command we were
piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
introduced in a6226fd772b (submodule--helper: convert the bulk of
cmd_add() to C, 2021-08-10).
In fixing it move to a "goto cleanup" pattern, and since we need to
introduce a "ret" variable to do that let's also get rid of the
intermediate "exit_code" variable. The initialization to "-1" in
a6226fd772b has always been redundant, we'd only use the "exit_code"
value after assigning the return value of pipe_command() to it.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d469c571d52..d952b9c8616 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3294,6 +3294,8 @@ static int module_add(int argc, const char **argv, const char *prefix)
N_("git submodule add [<options>] [--] <repository> [<path>]"),
NULL
};
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 1;
argc = parse_options(argc, argv, prefix, options, usage, 0);
@@ -3343,21 +3345,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
die_on_repo_without_commits(add_data.sm_path);
if (!force) {
- int exit_code = -1;
- struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdout = 1;
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
"--no-warn-embedded-repo", add_data.sm_path, NULL);
- if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+ if ((ret = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
strbuf_complete_line(&sb);
fputs(sb.buf, stderr);
- free(add_data.sm_path);
- return exit_code;
+ goto cleanup;
}
- strbuf_release(&sb);
}
if(!add_data.sm_name)
@@ -3372,15 +3370,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
add_data.progress = !!progress;
add_data.dissociate = !!dissociate;
- if (add_submodule(&add_data)) {
- free(add_data.sm_path);
- return 1;
- }
+ if (add_submodule(&add_data))
+ goto cleanup;
configure_added_submodule(&add_data);
+
+ ret = 0;
+cleanup:
free(add_data.sm_path);
free(to_free);
+ strbuf_release(&sb);
- return 0;
+ return ret;
}
#define SUPPORT_SUPER_PREFIX (1<<0)
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 13/17] submodule--helper: fix a leak in module_add()
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (11 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
` (4 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in module_path(), since a6226fd772b (submodule--helper:
convert the bulk of cmd_add() to C, 2021-08-10), we've been freeing
add_data.sm_path, but in this case we clobbered it, and didn't free
the value we clobbered.
This makes test 28 of "t/t7400-submodule-basic.sh" ("submodule add in
subdirectory") pass when we're compiled with SANITIZE=leak..
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d952b9c8616..8d55090ee2e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3315,8 +3315,12 @@ static int module_add(int argc, const char **argv, const char *prefix)
else
add_data.sm_path = xstrdup(argv[1]);
- if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
- add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
+ char *sm_path = add_data.sm_path;
+
+ add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
+ free(sm_path);
+ }
if (starts_with_dot_dot_slash(add_data.repo) ||
starts_with_dot_slash(add_data.repo)) {
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 14/17] submodule--helper: fix a memory leak in print_status()
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (12 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
` (3 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in print_status(), the compute_rev_name() function
implemented in this file will return a strbuf_detach()'d value, or
NULL.
This leak has existed since this code was added in
a9f8a37584a (submodule: port submodule subcommand 'status' from shell
to C, 2017-10-06), but in 0b5e2ea7cf3 (submodule--helper: don't print
null in 'submodule status', 2018-04-18) we added a "const"
intermediate variable for the return value, that "const" should be
removed.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 8d55090ee2e..e75d7fa2e10 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -583,10 +583,11 @@ static void print_status(unsigned int flags, char state, const char *path,
printf("%c%s %s", state, oid_to_hex(oid), displaypath);
if (state == ' ' || state == '+') {
- const char *name = compute_rev_name(path, oid_to_hex(oid));
+ char *name = compute_rev_name(path, oid_to_hex(oid));
if (name)
printf(" (%s)", name);
+ free(name);
}
printf("\n");
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 15/17] submodule--helper: free some "displaypath" in "struct update_data"
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (13 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-21 13:59 ` [PATCH v6 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
` (2 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Make the update_data_release() function free "displaypath" member when
appropriate. The "displaypath" member is always ours, the "const" on
the "char *" was wrong to begin with.
This leaves a leak of "displaypath" in update_submodule(), which as
we'll see in subsequent commits is harder to deal with than this
trivial fix.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
t/t2403-worktree-move.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
t/t7419-submodule-set-branch.sh | 1 +
4 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e75d7fa2e10..dbbe412b24e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1880,7 +1880,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
struct update_data {
const char *prefix;
- const char *displaypath;
+ char *displaypath;
enum submodule_update_type update_default;
struct object_id suboid;
struct string_list references;
@@ -1918,6 +1918,7 @@ struct update_data {
static void update_data_release(struct update_data *ud)
{
+ free(ud->displaypath);
module_list_release(&ud->list);
}
diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh
index a4e1a178e0a..1168e9f9982 100755
--- a/t/t2403-worktree-move.sh
+++ b/t/t2403-worktree-move.sh
@@ -2,6 +2,7 @@
test_description='test git worktree move, remove, lock and unlock'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 1cfa150768d..2859695c6d2 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -6,6 +6,7 @@ This test verifies that `git submodue absorbgitdirs` moves a submodules git
directory into the superproject.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh
index 3b925c302fc..96e98423214 100755
--- a/t/t7419-submodule-set-branch.sh
+++ b/t/t7419-submodule-set-branch.sh
@@ -9,6 +9,7 @@ This test verifies that the set-branch subcommand of git-submodule is working
as expected.
'
+TEST_PASSES_SANITIZE_LEAK=true
TEST_NO_CREATE_REPO=1
. ./test-lib.sh
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (14 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-24 23:03 ` Glen Choo
2022-08-21 13:59 ` [PATCH v6 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
17 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24), we clobber the "displaypath" member of
the passed-in "struct update_data" both so that die() messages in this
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
To make managing that clobbering easier let's wrap the
update_submodule() in a new update_submodule_outer() function, which
will do the clobbering and free(to_free) dance for us.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index dbbe412b24e..070e435b13e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2485,13 +2485,6 @@ static int update_submodule(struct update_data *update_data)
{
int ret;
- ret = ensure_core_worktree(update_data->sm_path);
- if (ret)
- return ret;
-
- update_data->displaypath = get_submodule_displaypath(
- update_data->sm_path, update_data->prefix);
-
ret = determine_submodule_update_strategy(the_repository,
update_data->just_cloned,
update_data->sm_path,
@@ -2565,6 +2558,24 @@ static int update_submodule(struct update_data *update_data)
return 0;
}
+static int update_submodule_outer(struct update_data *update_data)
+{
+ char *to_free, *restore = update_data->displaypath;
+ int ret;
+
+ ensure_core_worktree(update_data->sm_path);
+
+ update_data->displaypath = to_free = get_submodule_displaypath(
+ update_data->sm_path, update_data->prefix);
+
+ ret = update_submodule(update_data);
+
+ free(to_free);
+ update_data->displaypath = restore;
+
+ return ret;
+}
+
static int update_submodules(struct update_data *update_data)
{
int i, ret = 0;
@@ -2597,7 +2608,7 @@ static int update_submodules(struct update_data *update_data)
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
- code = update_submodule(update_data);
+ code = update_submodule_outer(update_data);
if (!code)
continue;
ret = code;
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v6 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-08-21 13:59 ` [PATCH v6 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-08-24 23:03 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-08-24 23:03 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
> procedures from C, 2021-08-24), we clobber the "displaypath" member of
> the passed-in "struct update_data" both so that die() messages in this
> update_submodule() function itself can use it, and for the
> run_update_procedure() called within this function.
>
> To make managing that clobbering easier let's wrap the
> update_submodule() in a new update_submodule_outer() function, which
> will do the clobbering and free(to_free) dance for us.
The only feedback I had on v5 was on this patch
(https://lore.kernel.org/git/kl6l5yj7ubpt.fsf@chooglen-macbookpro.roam.corp.google.com)
where I said that update_submodule_outer() seemed like overkill and that
I'd test an alternative.
I tested this approach
Assign and FREE_AND_NULL() update_data->displaypath [in
update_submodules(), but outside of update_submodule()] since this
is the only caller and it already does some prep work in this hunk.
by reverting this patch and applying this one
----- >8 --------- >8 --------- >8 --------- >8 --------- >8 ----
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3557665261..c932c857dd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2486,9 +2486,6 @@ static int update_submodule(struct update_data *update_data)
if (ret)
return ret;
- update_data->displaypath = get_submodule_displaypath(
- update_data->sm_path, update_data->prefix);
-
ret = determine_submodule_update_strategy(the_repository,
update_data->just_cloned,
update_data->sm_path,
@@ -2593,8 +2590,11 @@ static int update_submodules(struct update_data *update_data)
oidcpy(&update_data->oid, &ucd.oid);
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
+ update_data->displaypath = get_submodule_displaypath(
+ update_data->sm_path, update_data->prefix);
code = update_submodule(update_data);
+ FREE_AND_NULL(update_data->displaypath);
if (!code)
continue;
ret = code;
----- >8 --------- >8 --------- >8 --------- >8 --------- >8 ----
Then I tested the update_submodule_outer() version and the
FREE_AND_NULL() version by marking t7406-submodule-update.sh as
TEST_PASSES_SANITIZE_LEAK=true and diffing the test output. I didn't see
any meaningful difference in the test output, which should mean that
both versions fix all of the leaks in "git submodule update" that our
test suite can catch.
For good measure, I also tested a version of my code without the
FREE_AND_NULL() call (albeit on v5, not v6), and I spotted the expected
memory leak:
Direct leak of 10 byte(s) in 1 object(s) allocated from:
#0 0x000000000000 in __interceptor_malloc ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:54
#1 0x000000000000 in strdup (/lib/x86_64-linux-gnu/libc.so.6+0x000000000000)
#2 0x000000000000 in xstrdup wrapper.c:39
#3 0x000000000000 in get_submodule_displaypath builtin/submodule--helper.c:119
#4 0x000000000000 in update_submodules builtin/submodule--helper.c:2585
#5 0x000000000000 in module_update builtin/submodule--helper.c:2716
#6 0x000000000000 in run_builtin git.c:466
#7 0x000000000000 in handle_builtin git.c:720
#8 0x000000000000 in run_argv git.c:787
#9 0x000000000000 in cmd_main git.c:920
#10 0x000000000000 in main common-main.c:56
#11 0x000000000000 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x000000000000)
#12 0x000000000000 in _start (git+0x000000000000)
The CI runs are at:
- FREE_AND_NULL(): https://github.com/chooglen/git/actions/runs/2920894120
- update_submodule_outer(): https://github.com/chooglen/git/actions/runs/2915661611
- control study: https://github.com/chooglen/git/actions/runs/2915671776
If FREE_AND_NULL() really plugs all of the leaks, I would strongly
prefer using that (possibly in a "goto cleanup"), over introducing
update_submodule_outer().
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v6 17/17] submodule--helper: fix a configure_added_submodule() leak
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (15 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:59 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:59 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix config API a memory leak added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06) by using the *_tmp()
variant of git_config_get_string().
In this case we're only checking whether
the (repo|git)_config_get_string() call is telling us that the
"submodule.active" key exists.
As with the preceding commit we'll find many other such patterns in
the codebase if we go fishing. E.g. "git gc" leaks in the code added
in 61f7a383d3b (maintenance: use 'incremental' strategy by default,
2020-10-15). Similar code in "git gc" added in
b08ff1fee00 (maintenance: add --schedule option and config,
2020-09-11) doesn't leak, but we could avoid the malloc() & free() in
that case.
A coccinelle rule to find those would find and fix some leaks, and
cases where we're doing needless malloc() + free()'s but only care
about the key existence, or are copying
the (repo|git)_config_get_string() return value right away.
But as with the preceding commit let's punt on all of that for now,
and just narrowly fix this specific case in submodule--helper.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 ++--
t/t7413-submodule-is-active.sh | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 070e435b13e..3061943e70d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3168,7 +3168,7 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
static void configure_added_submodule(struct add_data *add_data)
{
char *key;
- char *val = NULL;
+ const char *val;
struct child_process add_submod = CHILD_PROCESS_INIT;
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
@@ -3213,7 +3213,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string("submodule.active", &val)) {
+ if (!git_config_get_string_tmp("submodule.active", &val)) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index ede6f02dbd5..4dc7d089423 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -9,6 +9,7 @@ This is a unit test of the submodule.c is_submodule_active() function,
which is also indirectly tested elsewhere.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
--
2.37.2.1279.g64dec4e13cf
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 00/17] submodule--helper: fix memory leaks
2022-08-21 13:59 ` [PATCH v6 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (16 preceding siblings ...)
2022-08-21 13:59 ` [PATCH v6 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
` (17 more replies)
17 siblings, 18 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
This series fixes all of the memory leaks in
builtin/submodule--helper.c that our test suite spots, except for
those where the leak is downstream of cmd_submodule__helper() and
caused by code that's not in builtin/submodule--helper.c (e.g. leaks
in the object or config APIs, and in submodule.c).
This re-roll is on top of the just-now re-rolled v4 of the base
topic[1].
Changes in v7:
* Rebase on top of the base topic.
* Clarify some questions on v6 in updated commit messages.
* Go with Glen's suggested "displaypath" fix. I also tried another
way which the commit discusses. The end result was better, but it
requires further submodule--helper cleanups, and this is already
quite an Odyssey. So FREE_AND_NULL() will do.
1. https://lore.kernel.org/git/cover-v4-00.33-00000000000-20220831T230519Z-avarab@gmail.com
This series & passing CI can be seen at:
https://github.com/avar/git/tree/avar/submodule--helper-memory-leaks-7
Ævar Arnfjörð Bjarmason (17):
submodule--helper: fix a leak in "clone_submodule"
submodule--helper: fix trivial get_default_remote_submodule() leak
submodule--helper: fix most "struct pathspec" memory leaks
submodule--helper: "struct pathspec" memory leak in module_update()
submodule--helper: don't leak {run,capture}_command() cp.dir argument
submodule--helper: add and use *_release() functions
submodule--helper: fix "errmsg_str" memory leak
submodule--helper: fix "sm_path" and other "module_cb_list" leaks
submodule--helper: fix a leak with repo_clear()
submodule--helper: fix a memory leak in get_default_remote_submodule()
submodule--helper: fix "reference" leak
submodule--helper: fix obscure leak in module_add()
submodule--helper: fix a leak in module_add()
submodule--helper: fix a memory leak in print_status()
submodule--helper: free some "displaypath" in "struct update_data"
submodule--helper: free rest of "displaypath" in "struct update_data"
submodule--helper: fix a configure_added_submodule() leak
builtin/submodule--helper.c | 227 +++++++++++++++++++++--------
t/t1500-rev-parse.sh | 1 +
t/t2403-worktree-move.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t6134-pathspec-in-submodule.sh | 1 +
t/t7401-submodule-summary.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
t/t7413-submodule-is-active.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 +
t/t7419-submodule-set-branch.sh | 1 +
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 +
12 files changed, 176 insertions(+), 64 deletions(-)
Range-diff against v6:
1: 0f60ea6f7c6 = 1: 40d4aef60fa submodule--helper: fix a leak in "clone_submodule"
2: c14e00f39cb = 2: 104f0777d50 submodule--helper: fix trivial get_default_remote_submodule() leak
3: a2ecdb301d3 ! 3: 3e1948ddc02 submodule--helper: fix most "struct pathspec" memory leaks
@@ Commit message
safe to call clear_pathspec(), we don't want the data to be
uninitialized.
+ E.g. for module_foreach() we can see from looking at
+ module_list_compute() that if it returns non-zero that the "pathspec"
+ will always have been initialized. But relying on that both assumes
+ knowledge about parse_pathspec(), and would set up a fragile pattern
+ going forward.
+
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
4: 8fc3dad316e = 4: 505d7d5077e submodule--helper: "struct pathspec" memory leak in module_update()
5: a3886d36366 ! 5: 41672ffa55c submodule--helper: don't leak {run,capture}_command() cp.dir argument
@@ Commit message
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
-@@ builtin/submodule--helper.c: static int is_tip_reachable(const char *path, struct object_id *oid)
+@@ builtin/submodule--helper.c: static int is_tip_reachable(const char *path, const struct object_id *oid)
char *hex = oid_to_hex(oid);
cp.git_cmd = 1;
@@ builtin/submodule--helper.c: static int is_tip_reachable(const char *path, struc
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
-@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
+@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_path, int depth, int quiet,
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_pa
strvec_push(&cp.args, "fetch");
if (quiet)
-@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
+@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
}
strvec_push(&cp.args, oid);
6: 173dbb7d8fc = 6: 07a4cda579f submodule--helper: add and use *_release() functions
7: cd394814370 = 7: 600526e1301 submodule--helper: fix "errmsg_str" memory leak
8: 2110b991913 = 8: 2c5db495189 submodule--helper: fix "sm_path" and other "module_cb_list" leaks
9: a0d1a03166f = 9: 71ebaac73c1 submodule--helper: fix a leak with repo_clear()
10: 84f162f320b = 10: 8a016f3d58c submodule--helper: fix a memory leak in get_default_remote_submodule()
11: dc5e8504354 = 11: 6a4c22d07b9 submodule--helper: fix "reference" leak
12: 50d58bfb19b = 12: b8654647601 submodule--helper: fix obscure leak in module_add()
13: 56590508180 = 13: c922e04f3d1 submodule--helper: fix a leak in module_add()
14: 38ceb0a36ab = 14: 33babb1a165 submodule--helper: fix a memory leak in print_status()
15: f3cf49dd029 = 15: bfafd31746e submodule--helper: free some "displaypath" in "struct update_data"
16: a99a7736fab ! 16: 63ff554e306 submodule--helper: free rest of "displaypath" in "struct update_data"
@@ Commit message
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
- To make managing that clobbering easier let's wrap the
- update_submodule() in a new update_submodule_outer() function, which
- will do the clobbering and free(to_free) dance for us.
+ Fix a leak in code added in 51f8f94e5b (submodule--helper: run update
+ procedures from C, 2021-08-24). We'd always clobber the old
+ "displaypath" member of the previously passed-in "struct update_data".
+ A better fix for this would be to remove the "displaypath" member from
+ the "struct update_data" entirely. Along with "oid", "suboid",
+ "just_cloned" and "sm_path" it's managing members that mainly need to
+ be passed between 1-3 stack frames of functions adjacent to this
+ code. But doing so would be a much larger change (I have it locally,
+ and fully untangling that in an incremental way is a 10 patch
+ journey).
+
+ So let's go for this much more isolated fix suggested by Glen. We
+ FREE_AND_NULL() the "update_data->displaypath", the "AND_NULL()" part
+ of that is needed due to the later "free(ud->displaypath)" in
+ "update_data_release()" introduced in the preceding commit
+
+ Moving ensure_core_worktree() out of update_submodule() may not be
+ strictly required, but in doing so we are left with the exact same
+ ordering as before, making this a smaller functional change.
+
+ Helped-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *upd
ret = determine_submodule_update_strategy(the_repository,
update_data->just_cloned,
update_data->sm_path,
-@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
- return 0;
- }
-
-+static int update_submodule_outer(struct update_data *update_data)
-+{
-+ char *to_free, *restore = update_data->displaypath;
-+ int ret;
-+
-+ ensure_core_worktree(update_data->sm_path);
-+
-+ update_data->displaypath = to_free = get_submodule_displaypath(
-+ update_data->sm_path, update_data->prefix);
-+
-+ ret = update_submodule(update_data);
-+
-+ free(to_free);
-+ update_data->displaypath = restore;
-+
-+ return ret;
-+}
-+
- static int update_submodules(struct update_data *update_data)
- {
- int i, ret = 0;
@@ builtin/submodule--helper.c: static int update_submodules(struct update_data *update_data)
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
-- code = update_submodule(update_data);
-+ code = update_submodule_outer(update_data);
++ code = ensure_core_worktree(update_data->sm_path);
++ if (code)
++ goto fail;
++
++ update_data->displaypath = get_submodule_displaypath(
++ update_data->sm_path, update_data->prefix);
+ code = update_submodule(update_data);
++ FREE_AND_NULL(update_data->displaypath);
++fail:
if (!code)
continue;
ret = code;
17: ec0b02d8ee2 = 17: 3056bfcf607 submodule--helper: fix a configure_added_submodule() leak
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v7 01/17] submodule--helper: fix a leak in "clone_submodule"
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
` (16 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak of the "clone_data_path" variable that we copy or
derive from the "struct module_clone_data" in clone_submodule(). This
code was refactored in preceding commits, but the leak has been with
us since f8eaa0ba98b (submodule--helper, module_clone: always operate
on absolute paths, 2016-03-31).
For the "else" case we don't need to xstrdup() the "clone_data->path",
and we don't need to free our own "clone_data_path". We can therefore
assign the "clone_data->path" to our own "clone_data_path" right away,
and only override it (and remember to free it!) if we need to
xstrfmt() a replacement.
In the case of the module_clone() caller it's from "argv", and doesn't
need to be free'd, and in the case of the add_submodule() caller we
get a pointer to "sm_path", which doesn't need to be directly free'd
either.
Fixing this leak makes several tests pass, so let's mark them as
passing with TEST_PASSES_SANITIZE_LEAK=true.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 10 +++++-----
t/t1500-rev-parse.sh | 1 +
t/t6008-rev-list-submodule.sh | 1 +
t/t7414-submodule-mistakes.sh | 2 ++
t/t7506-status-submodule.sh | 1 +
t/t7507-commit-verbose.sh | 2 ++
6 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c4149f11e7f..2e042c8a043 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1590,13 +1590,12 @@ static int clone_submodule(const struct module_clone_data *clone_data,
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *clone_data_path;
+ const char *clone_data_path = clone_data->path;
+ char *to_free = NULL;
if (!is_absolute_path(clone_data->path))
- clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
- clone_data->path);
- else
- clone_data_path = xstrdup(clone_data->path);
+ clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
+ clone_data->path);
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
die(_("refusing to create/use '%s' in another submodule's "
@@ -1681,6 +1680,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
free(sm_gitdir);
free(p);
+ free(to_free);
return 0;
}
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 1c2df08333b..0e13bcb4ebb 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -4,6 +4,7 @@ test_description='test git rev-parse'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_one () {
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 3153a0d8910..12e67e187ef 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -8,6 +8,7 @@ test_description='git rev-list involving submodules that this repo has'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
index f2e7df59cf2..3269298197c 100755
--- a/t/t7414-submodule-mistakes.sh
+++ b/t/t7414-submodule-mistakes.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='handling of common mistakes people may make with submodules'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create embedded repository' '
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index 3fcb44767f5..f5426a8e589 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -2,6 +2,7 @@
test_description='git status for submodule'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_create_repo_with_commit () {
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
index ed2653d46fe..92462a22374 100755
--- a/t/t7507-commit-verbose.sh
+++ b/t/t7507-commit-verbose.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='verbose commit template'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
write_script "check-for-diff" <<\EOF &&
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
` (15 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in 1012a5cbc3f (submodule--helper
run-update-procedure: learn --remote, 2022-03-04), we need to free()
the xstrdup()'d string. This gets e.g. t/t7419-submodule-set-branch.sh
closer to passing under SANITIZE=leak.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2e042c8a043..b51a5074b42 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2451,6 +2451,8 @@ static int update_submodule(struct update_data *update_data)
return code;
remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+ free(remote_name);
+
if (!update_data->nofetch) {
if (fetch_in_submodule(update_data->sm_path, update_data->depth,
0, NULL))
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 03/17] submodule--helper: fix most "struct pathspec" memory leaks
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 01/17] submodule--helper: fix a leak in "clone_submodule" Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 02/17] submodule--helper: fix trivial get_default_remote_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
` (14 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call clear_pathspec() at the end of various functions that work with
and allocate a "struct pathspec".
In some cases the zero-initialization here isn't strictly needed, but
as we're moving to a "goto cleanup" pattern let's make sure that it's
safe to call clear_pathspec(), we don't want the data to be
uninitialized.
E.g. for module_foreach() we can see from looking at
module_list_compute() that if it returns non-zero that the "pathspec"
will always have been initialized. But relying on that both assumes
knowledge about parse_pathspec(), and would set up a fragile pattern
going forward.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 74 +++++++++++++++++++++++++------------
1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b51a5074b42..2f8603a6bb5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -379,7 +379,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
static int module_foreach(int argc, const char **argv, const char *prefix)
{
struct foreach_cb info = FOREACH_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_foreach_options[] = {
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
@@ -391,12 +391,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_foreach_options,
git_submodule_helper_usage, 0);
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.argc = argc;
info.argv = argv;
@@ -404,7 +405,10 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int starts_with_dot_slash(const char *const path)
@@ -515,7 +519,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_init(int argc, const char **argv, const char *prefix)
{
struct init_cb info = INIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_init_options[] = {
@@ -526,12 +530,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
N_("git submodule init [<options>] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_init_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
/*
* If there are no path args and submodule.active is set then,
@@ -546,7 +551,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, init_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct status_cb {
@@ -693,7 +701,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
static int module_status(int argc, const char **argv, const char *prefix)
{
struct status_cb info = STATUS_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_status_options[] = {
@@ -706,12 +714,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_status_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -719,7 +728,10 @@ static int module_status(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, status_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_cb {
@@ -1261,7 +1273,7 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
static int module_sync(int argc, const char **argv, const char *prefix)
{
struct sync_cb info = SYNC_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int recursive = 0;
@@ -1275,12 +1287,13 @@ static int module_sync(int argc, const char **argv, const char *prefix)
N_("git submodule sync [--quiet] [--recursive] [<path>]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_sync_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1290,7 +1303,10 @@ static int module_sync(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, sync_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct deinit_cb {
@@ -1399,7 +1415,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
static int module_deinit(int argc, const char **argv, const char *prefix)
{
struct deinit_cb info = DEINIT_CB_INIT;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int force = 0;
@@ -1414,6 +1430,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, module_deinit_options,
git_submodule_helper_usage, 0);
@@ -1428,7 +1445,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
die(_("Use '--all' if you really want to deinitialize all submodules"));
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
info.prefix = prefix;
if (quiet)
@@ -1438,7 +1455,10 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
for_each_listed_submodule(&list, deinit_submodule_cb, &info);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
struct module_clone_data {
@@ -2543,7 +2563,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2620,8 +2640,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
opt.update_strategy.type = opt.update_default;
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
- list_objects_filter_release(&filter_options);
- return 1;
+ ret = 1;
+ goto cleanup;
}
if (pathspec.nr)
@@ -2632,8 +2652,10 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0)
- return 1;
+ &pathspec, &list) < 0) {
+ ret = 1;
+ goto cleanup;
+ }
/*
* If there are no path args and submodule.active is set then,
@@ -2650,7 +2672,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
}
ret = update_submodules(&opt);
+cleanup:
list_objects_filter_release(&filter_options);
+ clear_pathspec(&pathspec);
return ret;
}
@@ -2734,7 +2758,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
{
int i;
- struct pathspec pathspec;
+ struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
struct option embed_gitdir_options[] = {
@@ -2749,17 +2773,21 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
N_("git submodule absorbgitdirs [<options>] [<path>...]"),
NULL
};
+ int ret = 1;
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
- return 1;
+ goto cleanup;
for (i = 0; i < list.nr; i++)
absorb_git_dir_into_superproject(list.entries[i]->name, flags);
- return 0;
+ ret = 0;
+cleanup:
+ clear_pathspec(&pathspec);
+ return ret;
}
static int module_config(int argc, const char **argv, const char *prefix)
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 04/17] submodule--helper: "struct pathspec" memory leak in module_update()
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (2 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 03/17] submodule--helper: fix most "struct pathspec" memory leaks Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
` (13 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
The module_update() function calls module_list_compute() twice, which
in turn will reset the "struct pathspec" passed to it. Let's instead
track two of them, and clear them both.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2f8603a6bb5..e8bc6f17330 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2564,6 +2564,7 @@ static int update_submodules(struct update_data *update_data)
static int module_update(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec = { 0 };
+ struct pathspec pathspec2 = { 0 };
struct update_data opt = UPDATE_DATA_INIT;
struct list_objects_filter_options filter_options = { 0 };
int ret;
@@ -2652,7 +2653,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
struct init_cb info = INIT_CB_INIT;
if (module_list_compute(argc, argv, opt.prefix,
- &pathspec, &list) < 0) {
+ &pathspec2, &list) < 0) {
ret = 1;
goto cleanup;
}
@@ -2675,6 +2676,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
cleanup:
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
+ clear_pathspec(&pathspec2);
return ret;
}
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (3 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 04/17] submodule--helper: "struct pathspec" memory leak in module_update() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
` (12 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24) and 3c3558f0953 (submodule--helper: run
update using child process struct, 2022-03-15) by not allocating
memory in the first place.
The "dir" member of "struct child_process" will not be modified by
that API, and it's declared to be "const char *". So let's not
needlessly duplicate these strings.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e8bc6f17330..0c23dd93d96 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2129,7 +2129,7 @@ static int is_tip_reachable(const char *path, const struct object_id *oid)
char *hex = oid_to_hex(oid);
cp.git_cmd = 1;
- cp.dir = xstrdup(path);
+ cp.dir = path;
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
@@ -2148,7 +2148,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet,
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
- cp.dir = xstrdup(module_path);
+ cp.dir = module_path;
strvec_push(&cp.args, "fetch");
if (quiet)
@@ -2201,7 +2201,7 @@ static int run_update_command(const struct update_data *ud, int subforce)
}
strvec_push(&cp.args, oid);
- cp.dir = xstrdup(ud->sm_path);
+ cp.dir = ud->sm_path;
prepare_submodule_repo_env(&cp.env);
if ((ret = run_command(&cp))) {
switch (ud->update_strategy.type) {
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 06/17] submodule--helper: add and use *_release() functions
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (4 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 05/17] submodule--helper: don't leak {run,capture}_command() cp.dir argument Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
` (11 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Add release functions for "struct module_list", "struct
submodule_update_clone" and "struct update_data".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 28 +++++++++++++++++++++++++++-
t/t6134-pathspec-in-submodule.sh | 1 +
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 0c23dd93d96..ae918a662b4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -172,6 +172,11 @@ struct module_list {
};
#define MODULE_LIST_INIT { 0 }
+static void module_list_release(struct module_list *ml)
+{
+ free(ml->entries);
+}
+
static int module_list_compute(int argc, const char **argv,
const char *prefix,
struct pathspec *pathspec,
@@ -234,7 +239,7 @@ static void module_list_active(struct module_list *list)
active_modules.entries[active_modules.nr++] = ce;
}
- free(list->entries);
+ module_list_release(list);
*list = active_modules;
}
@@ -407,6 +412,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -553,6 +559,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -730,6 +737,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1305,6 +1313,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1457,6 +1466,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
+ module_list_release(&list);
clear_pathspec(&pathspec);
return ret;
}
@@ -1834,6 +1844,12 @@ struct submodule_update_clone {
};
#define SUBMODULE_UPDATE_CLONE_INIT { 0 }
+static void submodule_update_clone_release(struct submodule_update_clone *suc)
+{
+ free(suc->update_clone);
+ free(suc->failed_clones);
+}
+
struct update_data {
const char *prefix;
const char *displaypath;
@@ -1872,6 +1888,11 @@ struct update_data {
.max_jobs = 1, \
}
+static void update_data_release(struct update_data *ud)
+{
+ module_list_release(&ud->list);
+}
+
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
struct strbuf *out, const char *displaypath)
{
@@ -2557,6 +2578,7 @@ static int update_submodules(struct update_data *update_data)
}
cleanup:
+ submodule_update_clone_release(&suc);
string_list_clear(&update_data->references, 0);
return ret;
}
@@ -2654,6 +2676,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
if (module_list_compute(argc, argv, opt.prefix,
&pathspec2, &list) < 0) {
+ module_list_release(&list);
ret = 1;
goto cleanup;
}
@@ -2670,10 +2693,12 @@ static int module_update(int argc, const char **argv, const char *prefix)
info.flags |= OPT_QUIET;
for_each_listed_submodule(&list, init_submodule_cb, &info);
+ module_list_release(&list);
}
ret = update_submodules(&opt);
cleanup:
+ update_data_release(&opt);
list_objects_filter_release(&filter_options);
clear_pathspec(&pathspec);
clear_pathspec(&pathspec2);
@@ -2789,6 +2814,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
ret = 0;
cleanup:
clear_pathspec(&pathspec);
+ module_list_release(&list);
return ret;
}
diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh
index 0f1cb49cedc..3a241f259de 100755
--- a/t/t6134-pathspec-in-submodule.sh
+++ b/t/t6134-pathspec-in-submodule.sh
@@ -2,6 +2,7 @@
test_description='test case exclude pathspec'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a submodule' '
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 07/17] submodule--helper: fix "errmsg_str" memory leak
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (5 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 06/17] submodule--helper: add and use *_release() functions Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
` (10 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak introduced in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13), we sometimes append
to the "errmsg", and need to free the "struct strbuf".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ae918a662b4..75a5d9d47fd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -973,6 +973,7 @@ static void generate_submodule_summary(struct summary_cb *info,
free(displaypath);
free(src_abbrev);
free(dst_abbrev);
+ strbuf_release(&errmsg);
}
static void prepare_submodule_summary(struct summary_cb *info,
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (6 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 07/17] submodule--helper: fix "errmsg_str" memory leak Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
` (9 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix leaks in "struct module_cb_list" and the "struct module_cb" which
it contains, these fix leaks in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13).
The "sm_path" should always have been a "char *", not a "const
char *", we always create it with xstrdup().
We can't mark any tests passing passing with SANITIZE=leak using
"TEST_PASSES_SANITIZE_LEAK=true" as a result of this change, but
"t7401-submodule-summary.sh" gets closer to passing as a result of
this change.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 ++++++++++++++++++++-
t/t7401-submodule-summary.sh | 1 +
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 75a5d9d47fd..162e92c033e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -748,16 +748,34 @@ struct module_cb {
struct object_id oid_src;
struct object_id oid_dst;
char status;
- const char *sm_path;
+ char *sm_path;
};
#define MODULE_CB_INIT { 0 }
+static void module_cb_release(struct module_cb *mcb)
+{
+ free(mcb->sm_path);
+}
+
struct module_cb_list {
struct module_cb **entries;
int alloc, nr;
};
#define MODULE_CB_LIST_INIT { 0 }
+static void module_cb_list_release(struct module_cb_list *mcbl)
+{
+ int i;
+
+ for (i = 0; i < mcbl->nr; i++) {
+ struct module_cb *mcb = mcbl->entries[i];
+
+ module_cb_release(mcb);
+ free(mcb);
+ }
+ free(mcbl->entries);
+}
+
struct summary_cb {
int argc;
const char **argv;
@@ -1104,6 +1122,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
cleanup:
strvec_clear(&diff_args);
release_revisions(&rev);
+ module_cb_list_release(&list);
return ret;
}
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 9c3cc4cf404..542b3331a78 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -17,6 +17,7 @@ This test script tries to verify the sanity of summary subcommand of git submodu
# various reasons, one of them being that there are lots of commands taking place
# outside of 'test_expect_success' block, which is no longer in good-style.
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
add_file () {
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 09/17] submodule--helper: fix a leak with repo_clear()
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (7 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 08/17] submodule--helper: fix "sm_path" and other "module_cb_list" leaks Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
` (8 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Call repo_clear() in ensure_core_worktree() to free the "struct
repository". Fixes a leak that's been here since
74d4731da1f (submodule--helper: replace connect-gitdir-workingtree by
ensure-core-worktree, 2018-08-13).
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 162e92c033e..9a277057012 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2400,6 +2400,7 @@ static int ensure_core_worktree(const char *path)
strbuf_release(&sb);
}
+ repo_clear(&subrepo);
return 0;
}
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule()
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (8 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 09/17] submodule--helper: fix a leak with repo_clear() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
` (7 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a memory leak in the get_default_remote_submodule() function added
in a77c3fcb5ec (submodule--helper: get remote names from any
repository, 2022-03-04), we need to repo_clear() the submodule we
initialize.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9a277057012..9f9e5f05094 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -65,12 +65,16 @@ static int repo_get_default_remote(struct repository *repo, char **default_remot
static int get_default_remote_submodule(const char *module_path, char **default_remote)
{
struct repository subrepo;
+ int ret;
if (repo_submodule_init(&subrepo, the_repository, module_path,
null_oid()) < 0)
return die_message(_("could not get a repository handle for submodule '%s'"),
module_path);
- return repo_get_default_remote(&subrepo, default_remote);
+ ret = repo_get_default_remote(&subrepo, default_remote);
+ repo_clear(&subrepo);
+
+ return ret;
}
static char *get_default_remote(void)
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 11/17] submodule--helper: fix "reference" leak
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (9 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 10/17] submodule--helper: fix a memory leak in get_default_remote_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
` (6 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
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
31224cbdc72 (clone: recursive and reference option triggers submodule
alternates, 2016-08-17) and 8c8195e9c3e (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 <avarab@gmail.com>
---
builtin/submodule--helper.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9f9e5f05094..170eaf010ac 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1566,7 +1566,9 @@ static int add_possible_reference_from_superproject(
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
- string_list_append(sas->reference, xstrdup(sb.buf));
+ char *p = strbuf_detach(&sb, NULL);
+
+ string_list_append(sas->reference, p)->util = p;
free(sm_alternate);
} else {
switch (sas->error_mode) {
@@ -1798,6 +1800,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
clone_submodule(&clone_data, &reference);
list_objects_filter_release(&filter_options);
+ string_list_clear(&reference, 1);
return 0;
}
@@ -3045,6 +3048,7 @@ static int add_submodule(const struct add_data *add_data)
char *submod_gitdir_path;
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
struct string_list reference = STRING_LIST_INIT_NODUP;
+ int ret = -1;
/* perhaps the path already exists and is already a git repo, else clone it */
if (is_directory(add_data->sm_path)) {
@@ -3100,15 +3104,17 @@ static int add_submodule(const struct add_data *add_data)
clone_data.url = add_data->realrepo;
clone_data.quiet = add_data->quiet;
clone_data.progress = add_data->progress;
- if (add_data->reference_path)
- string_list_append(&reference,
- xstrdup(add_data->reference_path));
+ if (add_data->reference_path) {
+ char *p = xstrdup(add_data->reference_path);
+
+ string_list_append(&reference, p)->util = p;
+ }
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
if (clone_submodule(&clone_data, &reference))
- return -1;
+ goto cleanup;
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -3127,7 +3133,10 @@ static int add_submodule(const struct add_data *add_data)
if (run_command(&cp))
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
}
- return 0;
+ ret = 0;
+cleanup:
+ string_list_clear(&reference, 1);
+ return ret;
}
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 12/17] submodule--helper: fix obscure leak in module_add()
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (10 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 11/17] submodule--helper: fix "reference" leak Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
` (5 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix an obscure leak in module_add(), if the "git add" command we were
piping to failed we'd fail to strbuf_release(&sb). This fixes a leak
introduced in a6226fd772b (submodule--helper: convert the bulk of
cmd_add() to C, 2021-08-10).
In fixing it move to a "goto cleanup" pattern, and since we need to
introduce a "ret" variable to do that let's also get rid of the
intermediate "exit_code" variable. The initialization to "-1" in
a6226fd772b has always been redundant, we'd only use the "exit_code"
value after assigning the return value of pipe_command() to it.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 170eaf010ac..675dc3f16a3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3296,6 +3296,8 @@ static int module_add(int argc, const char **argv, const char *prefix)
N_("git submodule add [<options>] [--] <repository> [<path>]"),
NULL
};
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 1;
argc = parse_options(argc, argv, prefix, options, usage, 0);
@@ -3345,21 +3347,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
die_on_repo_without_commits(add_data.sm_path);
if (!force) {
- int exit_code = -1;
- struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdout = 1;
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
"--no-warn-embedded-repo", add_data.sm_path, NULL);
- if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+ if ((ret = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
strbuf_complete_line(&sb);
fputs(sb.buf, stderr);
- free(add_data.sm_path);
- return exit_code;
+ goto cleanup;
}
- strbuf_release(&sb);
}
if(!add_data.sm_name)
@@ -3374,15 +3372,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
add_data.progress = !!progress;
add_data.dissociate = !!dissociate;
- if (add_submodule(&add_data)) {
- free(add_data.sm_path);
- return 1;
- }
+ if (add_submodule(&add_data))
+ goto cleanup;
configure_added_submodule(&add_data);
+
+ ret = 0;
+cleanup:
free(add_data.sm_path);
free(to_free);
+ strbuf_release(&sb);
- return 0;
+ return ret;
}
#define SUPPORT_SUPER_PREFIX (1<<0)
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 13/17] submodule--helper: fix a leak in module_add()
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (11 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 12/17] submodule--helper: fix obscure leak in module_add() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
` (4 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in module_path(), since a6226fd772b (submodule--helper:
convert the bulk of cmd_add() to C, 2021-08-10), we've been freeing
add_data.sm_path, but in this case we clobbered it, and didn't free
the value we clobbered.
This makes test 28 of "t/t7400-submodule-basic.sh" ("submodule add in
subdirectory") pass when we're compiled with SANITIZE=leak..
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 675dc3f16a3..7c62916da3c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3317,8 +3317,12 @@ static int module_add(int argc, const char **argv, const char *prefix)
else
add_data.sm_path = xstrdup(argv[1]);
- if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
- add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
+ char *sm_path = add_data.sm_path;
+
+ add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
+ free(sm_path);
+ }
if (starts_with_dot_dot_slash(add_data.repo) ||
starts_with_dot_slash(add_data.repo)) {
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 14/17] submodule--helper: fix a memory leak in print_status()
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (12 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 13/17] submodule--helper: fix a " Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
` (3 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in print_status(), the compute_rev_name() function
implemented in this file will return a strbuf_detach()'d value, or
NULL.
This leak has existed since this code was added in
a9f8a37584a (submodule: port submodule subcommand 'status' from shell
to C, 2017-10-06), but in 0b5e2ea7cf3 (submodule--helper: don't print
null in 'submodule status', 2018-04-18) we added a "const"
intermediate variable for the return value, that "const" should be
removed.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7c62916da3c..23c9e28deaa 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -583,10 +583,11 @@ static void print_status(unsigned int flags, char state, const char *path,
printf("%c%s %s", state, oid_to_hex(oid), displaypath);
if (state == ' ' || state == '+') {
- const char *name = compute_rev_name(path, oid_to_hex(oid));
+ char *name = compute_rev_name(path, oid_to_hex(oid));
if (name)
printf(" (%s)", name);
+ free(name);
}
printf("\n");
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 15/17] submodule--helper: free some "displaypath" in "struct update_data"
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (13 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 14/17] submodule--helper: fix a memory leak in print_status() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-08-31 23:14 ` [PATCH v7 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
` (2 subsequent siblings)
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Make the update_data_release() function free "displaypath" member when
appropriate. The "displaypath" member is always ours, the "const" on
the "char *" was wrong to begin with.
This leaves a leak of "displaypath" in update_submodule(), which as
we'll see in subsequent commits is harder to deal with than this
trivial fix.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 3 ++-
t/t2403-worktree-move.sh | 1 +
t/t7412-submodule-absorbgitdirs.sh | 1 +
t/t7419-submodule-set-branch.sh | 1 +
4 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 23c9e28deaa..94ebd8ea38e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1880,7 +1880,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
struct update_data {
const char *prefix;
- const char *displaypath;
+ char *displaypath;
enum submodule_update_type update_default;
struct object_id suboid;
struct string_list references;
@@ -1918,6 +1918,7 @@ struct update_data {
static void update_data_release(struct update_data *ud)
{
+ free(ud->displaypath);
module_list_release(&ud->list);
}
diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh
index a4e1a178e0a..1168e9f9982 100755
--- a/t/t2403-worktree-move.sh
+++ b/t/t2403-worktree-move.sh
@@ -2,6 +2,7 @@
test_description='test git worktree move, remove, lock and unlock'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 1cfa150768d..2859695c6d2 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -6,6 +6,7 @@ This test verifies that `git submodue absorbgitdirs` moves a submodules git
directory into the superproject.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh
index 3b925c302fc..96e98423214 100755
--- a/t/t7419-submodule-set-branch.sh
+++ b/t/t7419-submodule-set-branch.sh
@@ -9,6 +9,7 @@ This test verifies that the set-branch subcommand of git-submodule is working
as expected.
'
+TEST_PASSES_SANITIZE_LEAK=true
TEST_NO_CREATE_REPO=1
. ./test-lib.sh
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* [PATCH v7 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (14 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 15/17] submodule--helper: free some "displaypath" in "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-09-01 21:20 ` Glen Choo
2022-08-31 23:14 ` [PATCH v7 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
2022-09-01 21:23 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Glen Choo
17 siblings, 1 reply; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix a leak in code added in c51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24), we clobber the "displaypath" member of
the passed-in "struct update_data" both so that die() messages in this
update_submodule() function itself can use it, and for the
run_update_procedure() called within this function.
Fix a leak in code added in 51f8f94e5b (submodule--helper: run update
procedures from C, 2021-08-24). We'd always clobber the old
"displaypath" member of the previously passed-in "struct update_data".
A better fix for this would be to remove the "displaypath" member from
the "struct update_data" entirely. Along with "oid", "suboid",
"just_cloned" and "sm_path" it's managing members that mainly need to
be passed between 1-3 stack frames of functions adjacent to this
code. But doing so would be a much larger change (I have it locally,
and fully untangling that in an incremental way is a 10 patch
journey).
So let's go for this much more isolated fix suggested by Glen. We
FREE_AND_NULL() the "update_data->displaypath", the "AND_NULL()" part
of that is needed due to the later "free(ud->displaypath)" in
"update_data_release()" introduced in the preceding commit
Moving ensure_core_worktree() out of update_submodule() may not be
strictly required, but in doing so we are left with the exact same
ordering as before, making this a smaller functional change.
Helped-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 94ebd8ea38e..1650bf0070b 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2487,13 +2487,6 @@ static int update_submodule(struct update_data *update_data)
{
int ret;
- ret = ensure_core_worktree(update_data->sm_path);
- if (ret)
- return ret;
-
- update_data->displaypath = get_submodule_displaypath(
- update_data->sm_path, update_data->prefix);
-
ret = determine_submodule_update_strategy(the_repository,
update_data->just_cloned,
update_data->sm_path,
@@ -2599,7 +2592,15 @@ static int update_submodules(struct update_data *update_data)
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
+ code = ensure_core_worktree(update_data->sm_path);
+ if (code)
+ goto fail;
+
+ update_data->displaypath = get_submodule_displaypath(
+ update_data->sm_path, update_data->prefix);
code = update_submodule(update_data);
+ FREE_AND_NULL(update_data->displaypath);
+fail:
if (!code)
continue;
ret = code;
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v7 16/17] submodule--helper: free rest of "displaypath" in "struct update_data"
2022-08-31 23:14 ` [PATCH v7 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-09-01 21:20 ` Glen Choo
0 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-09-01 21:20 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> A better fix for this would be to remove the "displaypath" member from
> the "struct update_data" entirely. Along with "oid", "suboid",
> "just_cloned" and "sm_path" it's managing members that mainly need to
> be passed between 1-3 stack frames of functions adjacent to this
> code. But doing so would be a much larger change (I have it locally,
> and fully untangling that in an incremental way is a 10 patch
> journey).
Yeah that does sound like a better fix _and_ too much churn right now.
> So let's go for this much more isolated fix suggested by Glen. We
> FREE_AND_NULL() the "update_data->displaypath", the "AND_NULL()" part
> of that is needed due to the later "free(ud->displaypath)" in
> "update_data_release()" introduced in the preceding commit
>
> Moving ensure_core_worktree() out of update_submodule() may not be
> strictly required, but in doing so we are left with the exact same
> ordering as before, making this a smaller functional change.
Ok, it's nice that we don't have to reason about functional changes,
though I doubt it will matter in this case.
I worry a bit about whether this is setting up an implicit contract
where we always need to call ensure_core_worktree() before
update_submodule(), but the contract has always been quite fuzzy here,
e.g. the "struct update_data" at this point contains a mix of CLI args +
clone result; we should fix that at some point, so doing this
change in the meantime seems harmless.
> Helped-by: Glen Choo <chooglen@google.com>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/submodule--helper.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 94ebd8ea38e..1650bf0070b 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2487,13 +2487,6 @@ static int update_submodule(struct update_data *update_data)
> {
> int ret;
>
> - ret = ensure_core_worktree(update_data->sm_path);
> - if (ret)
> - return ret;
> -
> - update_data->displaypath = get_submodule_displaypath(
> - update_data->sm_path, update_data->prefix);
> -
> ret = determine_submodule_update_strategy(the_repository,
> update_data->just_cloned,
> update_data->sm_path,
> @@ -2599,7 +2592,15 @@ static int update_submodules(struct update_data *update_data)
> update_data->just_cloned = ucd.just_cloned;
> update_data->sm_path = ucd.sub->path;
>
> + code = ensure_core_worktree(update_data->sm_path);
> + if (code)
> + goto fail;
> +
> + update_data->displaypath = get_submodule_displaypath(
> + update_data->sm_path, update_data->prefix);
> code = update_submodule(update_data);
> + FREE_AND_NULL(update_data->displaypath);
> +fail:
> if (!code)
> continue;
> ret = code;
Looks good.
> --
> 2.37.3.1420.g76f8a3d556c
^ permalink raw reply [flat|nested] 186+ messages in thread
* [PATCH v7 17/17] submodule--helper: fix a configure_added_submodule() leak
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (15 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 16/17] submodule--helper: free rest of " Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:14 ` Ævar Arnfjörð Bjarmason
2022-09-01 21:23 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Glen Choo
17 siblings, 0 replies; 186+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:14 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Fix config API a memory leak added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06) by using the *_tmp()
variant of git_config_get_string().
In this case we're only checking whether
the (repo|git)_config_get_string() call is telling us that the
"submodule.active" key exists.
As with the preceding commit we'll find many other such patterns in
the codebase if we go fishing. E.g. "git gc" leaks in the code added
in 61f7a383d3b (maintenance: use 'incremental' strategy by default,
2020-10-15). Similar code in "git gc" added in
b08ff1fee00 (maintenance: add --schedule option and config,
2020-09-11) doesn't leak, but we could avoid the malloc() & free() in
that case.
A coccinelle rule to find those would find and fix some leaks, and
cases where we're doing needless malloc() + free()'s but only care
about the key existence, or are copying
the (repo|git)_config_get_string() return value right away.
But as with the preceding commit let's punt on all of that for now,
and just narrowly fix this specific case in submodule--helper.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
builtin/submodule--helper.c | 4 ++--
t/t7413-submodule-is-active.sh | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 1650bf0070b..37b6db5cbb4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3160,7 +3160,7 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
static void configure_added_submodule(struct add_data *add_data)
{
char *key;
- char *val = NULL;
+ const char *val;
struct child_process add_submod = CHILD_PROCESS_INIT;
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
@@ -3205,7 +3205,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string("submodule.active", &val)) {
+ if (!git_config_get_string_tmp("submodule.active", &val)) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index ede6f02dbd5..4dc7d089423 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -9,6 +9,7 @@ This is a unit test of the submodule.c is_submodule_active() function,
which is also indirectly tested elsewhere.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
--
2.37.3.1420.g76f8a3d556c
^ permalink raw reply related [flat|nested] 186+ messages in thread
* Re: [PATCH v7 00/17] submodule--helper: fix memory leaks
2022-08-31 23:14 ` [PATCH v7 00/17] submodule--helper: fix memory leaks Ævar Arnfjörð Bjarmason
` (16 preceding siblings ...)
2022-08-31 23:14 ` [PATCH v7 17/17] submodule--helper: fix a configure_added_submodule() leak Ævar Arnfjörð Bjarmason
@ 2022-09-01 21:23 ` Glen Choo
17 siblings, 0 replies; 186+ messages in thread
From: Glen Choo @ 2022-09-01 21:23 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason, git
Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
Ævar Arnfjörð Bjarmason
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> This series fixes all of the memory leaks in
> builtin/submodule--helper.c that our test suite spots, except for
> those where the leak is downstream of cmd_submodule__helper() and
> caused by code that's not in builtin/submodule--helper.c (e.g. leaks
> in the object or config APIs, and in submodule.c).
>
> This re-roll is on top of the just-now re-rolled v4 of the base
> topic[1].
>
> Changes in v7:
>
> * Rebase on top of the base topic.
> * Clarify some questions on v6 in updated commit messages.
> * Go with Glen's suggested "displaypath" fix. I also tried another
> way which the commit discusses. The end result was better, but it
> requires further submodule--helper cleanups, and this is already
> quite an Odyssey. So FREE_AND_NULL() will do.
>
> 1. https://lore.kernel.org/git/cover-v4-00.33-00000000000-20220831T230519Z-avarab@gmail.com
>
> This series & passing CI can be seen at:
> https://github.com/avar/git/tree/avar/submodule--helper-memory-leaks-7
Thanks! And thanks especially for dealing with my stream of comments :)
This series + the prep series LGTM.
Reviewed-by: Glen Choo <chooglen@google.com>
^ permalink raw reply [flat|nested] 186+ messages in thread