Commit 04d4d674 by Vicent Marti

Merge pull request #2212 from libgit2/rb/submodule-use-after-free

Fix use-after-free in submodule reload code and other memory leaks
parents 041fad4a dae8ba6e
...@@ -852,10 +852,13 @@ int git_submodule_reload_all(git_repository *repo, int force) ...@@ -852,10 +852,13 @@ int git_submodule_reload_all(git_repository *repo, int force)
git_strmap_foreach_value(repo->submodules, sm, { git_strmap_foreach_value(repo->submodules, sm, {
git_strmap *cache = repo->submodules; git_strmap *cache = repo->submodules;
if ((sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS) == 0) { if (sm && (sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS) == 0) {
submodule_cache_remove_item(cache, sm->name, sm, true); /* we must check path != name before first remove, in case
* that call frees the submodule */
bool free_as_path = (sm->path != sm->name);
if (sm->path != sm->name) submodule_cache_remove_item(cache, sm->name, sm, true);
if (free_as_path)
submodule_cache_remove_item(cache, sm->path, sm, true); submodule_cache_remove_item(cache, sm->path, sm, true);
} }
}); });
...@@ -1123,6 +1126,7 @@ static void submodule_release(git_submodule *sm) ...@@ -1123,6 +1126,7 @@ static void submodule_release(git_submodule *sm)
git__free(sm->path); git__free(sm->path);
git__free(sm->name); git__free(sm->name);
git__free(sm->url); git__free(sm->url);
git__free(sm->branch);
git__memzero(sm, sizeof(*sm)); git__memzero(sm, sizeof(*sm));
git__free(sm); git__free(sm);
} }
......
...@@ -449,7 +449,6 @@ void test_diff_submodules__skips_empty_includes_used(void) ...@@ -449,7 +449,6 @@ void test_diff_submodules__skips_empty_includes_used(void)
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff = NULL; git_diff *diff = NULL;
diff_expects exp; diff_expects exp;
git_repository *r2;
/* A side effect of of Git's handling of untracked directories and /* A side effect of of Git's handling of untracked directories and
* auto-ignoring of ".git" entries is that a newly initialized Git * auto-ignoring of ".git" entries is that a newly initialized Git
...@@ -469,7 +468,11 @@ void test_diff_submodules__skips_empty_includes_used(void) ...@@ -469,7 +468,11 @@ void test_diff_submodules__skips_empty_includes_used(void)
cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.files);
git_diff_free(diff); git_diff_free(diff);
{
git_repository *r2;
cl_git_pass(git_repository_init(&r2, "empty_standard_repo/subrepo", 0)); cl_git_pass(git_repository_init(&r2, "empty_standard_repo/subrepo", 0));
git_repository_free(r2);
}
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp)); memset(&exp, 0, sizeof(exp));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment