From 7b69289f4e9249f61fb48593ddbf66b6f9ad6494 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 12:54:57 +0100 Subject: [PATCH 1/5] tree-cache: Free the tree upon the detection of a corrupted child --- src/tree-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree-cache.c b/src/tree-cache.c index 97ffc2acf..d1762821c 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -140,7 +140,7 @@ static int read_tree_internal(git_tree_cache **out, for (i = 0; i < tree->children_count; ++i) { if (read_tree_internal(&tree->children[i], &buffer, buffer_end, tree) < 0) - return -1; + goto corrupted; } } From 82e6a42c6c387a584df1b2efb4fa3bfdb8c290a2 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:13:51 +0100 Subject: [PATCH 2/5] tree-cache: Zero out the allocated tree children array --- src/tree-cache.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tree-cache.c b/src/tree-cache.c index d1762821c..a693f4f30 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -138,6 +138,8 @@ static int read_tree_internal(git_tree_cache **out, tree->children = git__malloc(tree->children_count * sizeof(git_tree_cache *)); GITERR_CHECK_ALLOC(tree->children); + memset(tree->children, 0x0, tree->children_count * sizeof(git_tree_cache *)); + for (i = 0; i < tree->children_count; ++i) { if (read_tree_internal(&tree->children[i], &buffer, buffer_end, tree) < 0) goto corrupted; From 3d5233455b2483fe78c82cabf89b568d079d6742 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:15:47 +0100 Subject: [PATCH 3/5] tree-cache: Don't segfault upon corruption --- src/tree-cache.c | 9 ++++++--- tests/index/tests.c | 9 +++++++++ tests/resources/bad.index | Bin 0 -> 412 bytes 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 tests/resources/bad.index diff --git a/src/tree-cache.c b/src/tree-cache.c index a693f4f30..57cc2946f 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -178,9 +178,12 @@ void git_tree_cache_free(git_tree_cache *tree) if (tree == NULL) return; - for (i = 0; i < tree->children_count; ++i) - git_tree_cache_free(tree->children[i]); + if (tree->children != NULL) { + for (i = 0; i < tree->children_count; ++i) + git_tree_cache_free(tree->children[i]); + + git__free(tree->children); + } - git__free(tree->children); git__free(tree); } diff --git a/tests/index/tests.c b/tests/index/tests.c index e5202980c..217e1bb55 100644 --- a/tests/index/tests.c +++ b/tests/index/tests.c @@ -6,6 +6,7 @@ static const size_t index_entry_count_2 = 1437; #define TEST_INDEX_PATH cl_fixture("testrepo.git/index") #define TEST_INDEX2_PATH cl_fixture("gitgit.index") #define TEST_INDEXBIG_PATH cl_fixture("big.index") +#define TEST_INDEXBAD_PATH cl_fixture("bad.index") /* Suite data */ @@ -535,3 +536,11 @@ void test_index_tests__reload_from_disk(void) git_index_free(write_index); git_repository_free(repo); } + +void test_index_tests__corrupted_extension(void) +{ + /* sort the entires in an empty index */ + git_index *index; + + cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR); +} diff --git a/tests/resources/bad.index b/tests/resources/bad.index new file mode 100644 index 0000000000000000000000000000000000000000..53746549feed9f42cbc8e96ff1a7012a779f8f39 GIT binary patch literal 412 zcmZ?q402{*U|<4bmY|Nc>wq*vP{-~&AQ}N0mmt^-YVwiUkGV_Bb{KE_b8o@KP1R2| zpGGmT1-Ux9__~7B0rmGo=)Jp<^Z}VD<|v%cthDU)aZqzLimwY$>hU-g-X_Ap9^~rd z>KF_%D5zs^HPjq1jW7$v9ATGtvSOjFAx>|WM&xf#d6$}@FO$Z=nP#XDbrQ@!F!OMj zgWWxxX+|(}LV{dD&hlq4Q841=GP`ChQI@tg&2XxUt;Xitc@?}|mCk8~42B8@yj)RU z4yAc2msD5OoRU6b))oF+P%=Hu2qMS*gF~^`e5S##c1QJW8@pFU}y=;P0kbyvuh Sm+Re*JqAXh|C)WywE_U^$Z9|U literal 0 HcmV?d00001 From a5d73188023cf0ae0b6fc42dfeddce5a9ee8ad5f Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:16:09 +0100 Subject: [PATCH 4/5] tree-cache: Fix error message typo --- src/tree-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tree-cache.c b/src/tree-cache.c index 57cc2946f..1d3997154 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -152,7 +152,7 @@ static int read_tree_internal(git_tree_cache **out, corrupted: git_tree_cache_free(tree); - giterr_set(GITERR_INDEX, "Corruped TREE extension in index"); + giterr_set(GITERR_INDEX, "Corrupted TREE extension in index"); return -1; } @@ -164,7 +164,7 @@ int git_tree_cache_read(git_tree_cache **tree, const char *buffer, size_t buffer return -1; if (buffer < buffer_end) { - giterr_set(GITERR_INDEX, "Corruped TREE extension in index (unexpected trailing data)"); + giterr_set(GITERR_INDEX, "Corrupted TREE extension in index (unexpected trailing data)"); return -1; } From bd15b513058afc53543b48383ec5bc56605f6c1e Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:24:10 +0100 Subject: [PATCH 5/5] index: Free the index on git_index_open() failure --- src/index.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/index.c b/src/index.c index ecab15024..09e7b2346 100644 --- a/src/index.c +++ b/src/index.c @@ -321,6 +321,7 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case) int git_index_open(git_index **index_out, const char *index_path) { git_index *index; + int error; assert(index_out); @@ -346,10 +347,15 @@ int git_index_open(git_index **index_out, const char *index_path) index->entries_search_path = index_srch_path; index->reuc_search = reuc_srch; + if ((index_path != NULL) && ((error = git_index_read(index, true)) < 0)) { + git_index_free(index); + return error; + } + *index_out = index; GIT_REFCOUNT_INC(index); - return (index_path != NULL) ? git_index_read(index, true) : 0; + return 0; } int git_index_new(git_index **out)