Skip to content

Commit 04d4d67

Browse files
author
Vicent Marti
committed
Merge pull request libgit2#2212 from libgit2/rb/submodule-use-after-free
Fix use-after-free in submodule reload code and other memory leaks
2 parents 041fad4 + dae8ba6 commit 04d4d67

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

src/submodule.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -852,10 +852,13 @@ int git_submodule_reload_all(git_repository *repo, int force)
852852
git_strmap_foreach_value(repo->submodules, sm, {
853853
git_strmap *cache = repo->submodules;
854854

855-
if ((sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS) == 0) {
856-
submodule_cache_remove_item(cache, sm->name, sm, true);
855+
if (sm && (sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS) == 0) {
856+
/* we must check path != name before first remove, in case
857+
* that call frees the submodule */
858+
bool free_as_path = (sm->path != sm->name);
857859

858-
if (sm->path != sm->name)
860+
submodule_cache_remove_item(cache, sm->name, sm, true);
861+
if (free_as_path)
859862
submodule_cache_remove_item(cache, sm->path, sm, true);
860863
}
861864
});
@@ -1123,6 +1126,7 @@ static void submodule_release(git_submodule *sm)
11231126
git__free(sm->path);
11241127
git__free(sm->name);
11251128
git__free(sm->url);
1129+
git__free(sm->branch);
11261130
git__memzero(sm, sizeof(*sm));
11271131
git__free(sm);
11281132
}

tests/diff/submodules.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,6 @@ void test_diff_submodules__skips_empty_includes_used(void)
449449
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
450450
git_diff *diff = NULL;
451451
diff_expects exp;
452-
git_repository *r2;
453452

454453
/* A side effect of of Git's handling of untracked directories and
455454
* auto-ignoring of ".git" entries is that a newly initialized Git
@@ -469,7 +468,11 @@ void test_diff_submodules__skips_empty_includes_used(void)
469468
cl_assert_equal_i(0, exp.files);
470469
git_diff_free(diff);
471470

472-
cl_git_pass(git_repository_init(&r2, "empty_standard_repo/subrepo", 0));
471+
{
472+
git_repository *r2;
473+
cl_git_pass(git_repository_init(&r2, "empty_standard_repo/subrepo", 0));
474+
git_repository_free(r2);
475+
}
473476

474477
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
475478
memset(&exp, 0, sizeof(exp));

0 commit comments

Comments
 (0)