From c4b5bedc972d9238db5d6422bc6f4de35b4b67ed Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 7 Oct 2010 00:07:32 +0300 Subject: [PATCH] Fix possible segfaults in src/tree.c (issue 1) git_tree_entry_byname was dereferencing a NULL pointer when the searched file couldn't be found on the tree. New test cases have been added to check for entry access methods. Signed-off-by: Vicent Marti --- src/tree.c | 21 ++++++++++++++++++++- tests/t0901-readtree.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/tree.c b/src/tree.c index 43a50423d..b809290b2 100644 --- a/src/tree.c +++ b/src/tree.c @@ -124,26 +124,36 @@ unsigned int git_tree_entry_attributes(git_tree_entry *entry) const char *git_tree_entry_name(git_tree_entry *entry) { + assert(entry); return entry->filename; } const git_oid *git_tree_entry_id(git_tree_entry *entry) { + assert(entry); return &entry->oid; } git_object *git_tree_entry_2object(git_tree_entry *entry) { + assert(entry); return git_repository_lookup(entry->owner->object.repo, &entry->oid, GIT_OBJ_ANY); } git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename) { - return *(git_tree_entry **)bsearch(filename, tree->entries, tree->entry_count, sizeof(git_tree_entry *), entry_cmp); + git_tree_entry **found; + + assert(tree && filename); + + found = bsearch(filename, tree->entries, tree->entry_count, sizeof(git_tree_entry *), entry_cmp); + return found ? *found : NULL; } git_tree_entry *git_tree_entry_byindex(git_tree *tree, int idx) { + assert(tree); + if (tree->entries == NULL) return NULL; @@ -152,6 +162,7 @@ git_tree_entry *git_tree_entry_byindex(git_tree *tree, int idx) size_t git_tree_entrycount(git_tree *tree) { + assert(tree); return tree->entry_count; } @@ -159,6 +170,8 @@ void git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, { git_tree_entry *entry; + assert(tree && id && filename); + if (tree->entry_count >= tree->array_size) resize_tree_array(tree); @@ -182,6 +195,8 @@ int git_tree_remove_entry_byindex(git_tree *tree, int idx) { git_tree_entry *remove_ptr; + assert(tree); + if (idx < 0 || idx >= (int)tree->entry_count) return GIT_ENOTFOUND; @@ -200,6 +215,8 @@ int git_tree_remove_entry_byname(git_tree *tree, const char *filename) git_tree_entry **entry_ptr; int idx; + assert(tree && filename); + entry_ptr = bsearch(filename, tree->entries, tree->entry_count, sizeof(git_tree_entry *), entry_cmp); if (entry_ptr == NULL) return GIT_ENOTFOUND; @@ -212,6 +229,8 @@ int git_tree__writeback(git_tree *tree, git_odb_source *src) { size_t i; + assert(tree && src); + if (tree->entries == NULL) return GIT_ERROR; diff --git a/tests/t0901-readtree.c b/tests/t0901-readtree.c index c28ad232e..eba6ecf46 100644 --- a/tests/t0901-readtree.c +++ b/tests/t0901-readtree.c @@ -9,6 +9,34 @@ static const char *odb_dir = "../resources/sample-odb"; static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; +BEGIN_TEST(tree_entry_access_test) + git_odb *db; + git_oid id; + git_repository *repo; + git_tree *tree; + + must_pass(git_odb_open(&db, odb_dir)); + + repo = git_repository_alloc(db); + must_be_true(repo != NULL); + + git_oid_mkstr(&id, tree_oid); + + tree = git_tree_lookup(repo, &id); + must_be_true(tree != NULL); + + must_be_true(git_tree_entry_byname(tree, "README") != NULL); + must_be_true(git_tree_entry_byname(tree, "NOTEXISTS") == NULL); + must_be_true(git_tree_entry_byname(tree, "") == NULL); + must_be_true(git_tree_entry_byindex(tree, 0) != NULL); + must_be_true(git_tree_entry_byindex(tree, 2) != NULL); + must_be_true(git_tree_entry_byindex(tree, 3) == NULL); + must_be_true(git_tree_entry_byindex(tree, -1) == NULL); + + git_repository_free(repo); + git_odb_close(db); +END_TEST + BEGIN_TEST(tree_read_test) git_odb *db; git_oid id; @@ -26,8 +54,6 @@ BEGIN_TEST(tree_read_test) tree = git_tree_lookup(repo, &id); must_be_true(tree != NULL); - must_pass(git_tree__parse(tree)); - must_be_true(git_tree_entrycount(tree) == 3); entry = git_tree_entry_byname(tree, "README");