Commit e4def81a by Vicent Marti

Fix issue 3 (memory corruption resize_tree_array)

The tree array wasn't being initialized when instantiating a tree object
in memory instead of loading it from disk.

New unit tests added to check for the problem.

Signed-off-by: Vicent Marti <tanoku@gmail.com>
parent 0ba7a031
...@@ -113,8 +113,9 @@ GIT_EXTERN(git_object *) git_tree_entry_2object(git_tree_entry *entry); ...@@ -113,8 +113,9 @@ GIT_EXTERN(git_object *) git_tree_entry_2object(git_tree_entry *entry);
* @iparam id OID for the tree entry * @iparam id OID for the tree entry
* @param filename Filename for the tree entry * @param filename Filename for the tree entry
* @param attributes UNIX file attributes for the entry * @param attributes UNIX file attributes for the entry
* @return 0 on success; otherwise error code
*/ */
GIT_EXTERN(void) git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes); GIT_EXTERN(int) git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes);
/** /**
* Remove an entry by its index. * Remove an entry by its index.
......
...@@ -29,17 +29,24 @@ ...@@ -29,17 +29,24 @@
#include "tree.h" #include "tree.h"
#include "git/repository.h" #include "git/repository.h"
static void resize_tree_array(git_tree *tree) static int resize_tree_array(git_tree *tree)
{ {
git_tree_entry **new_entries; git_tree_entry **new_entries;
tree->array_size = tree->array_size * 2; tree->array_size *= 2;
if (tree->array_size == 0)
tree->array_size = 8;
new_entries = git__malloc(tree->array_size * sizeof(git_tree_entry *)); new_entries = git__malloc(tree->array_size * sizeof(git_tree_entry *));
if (new_entries == NULL)
return GIT_ENOMEM;
memcpy(new_entries, tree->entries, tree->entry_count * sizeof(git_tree_entry *)); memcpy(new_entries, tree->entries, tree->entry_count * sizeof(git_tree_entry *));
free(tree->entries); free(tree->entries);
tree->entries = new_entries; tree->entries = new_entries;
return GIT_SUCCESS;
} }
int entry_cmp(const void *key, const void *array_member) int entry_cmp(const void *key, const void *array_member)
...@@ -166,17 +173,18 @@ size_t git_tree_entrycount(git_tree *tree) ...@@ -166,17 +173,18 @@ size_t git_tree_entrycount(git_tree *tree)
return tree->entry_count; return tree->entry_count;
} }
void git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes) int git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes)
{ {
git_tree_entry *entry; git_tree_entry *entry;
assert(tree && id && filename); assert(tree && id && filename);
if (tree->entry_count >= tree->array_size) if (tree->entry_count >= tree->array_size)
resize_tree_array(tree); if (resize_tree_array(tree) < 0)
return GIT_ENOMEM;
if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL) if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL)
return; return GIT_ENOMEM;
memset(entry, 0x0, sizeof(git_tree_entry)); memset(entry, 0x0, sizeof(git_tree_entry));
...@@ -189,6 +197,7 @@ void git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, ...@@ -189,6 +197,7 @@ void git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename,
entry_resort(tree); entry_resort(tree);
tree->object.modified = 1; tree->object.modified = 1;
return GIT_SUCCESS;
} }
int git_tree_remove_entry_byindex(git_tree *tree, int idx) int git_tree_remove_entry_byindex(git_tree *tree, int idx)
...@@ -277,11 +286,15 @@ int git_tree__parse(git_tree *tree) ...@@ -277,11 +286,15 @@ int git_tree__parse(git_tree *tree)
tree->array_size = (tree->object.source.raw.len / avg_entry_size) + 1; tree->array_size = (tree->object.source.raw.len / avg_entry_size) + 1;
tree->entries = git__malloc(tree->array_size * sizeof(git_tree_entry *)); tree->entries = git__malloc(tree->array_size * sizeof(git_tree_entry *));
if (tree->entries == NULL)
return GIT_ENOMEM;
while (buffer < buffer_end) { while (buffer < buffer_end) {
git_tree_entry *entry; git_tree_entry *entry;
if (tree->entry_count >= tree->array_size) if (tree->entry_count >= tree->array_size)
resize_tree_array(tree); if (resize_tree_array(tree) < 0)
return GIT_ENOMEM;
entry = git__malloc(sizeof(git_tree_entry)); entry = git__malloc(sizeof(git_tree_entry));
if (entry == NULL) { if (entry == NULL) {
......
...@@ -9,6 +9,39 @@ ...@@ -9,6 +9,39 @@
static const char *odb_dir = "../resources/sample-odb"; static const char *odb_dir = "../resources/sample-odb";
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
BEGIN_TEST(tree_in_memory_add_test)
const unsigned int entry_count = 128;
git_odb *db;
git_repository *repo;
git_tree *tree;
unsigned int i;
git_oid entry_id;
must_pass(git_odb_open(&db, odb_dir));
repo = git_repository_alloc(db);
must_be_true(repo != NULL);
tree = git_tree_new(repo);
must_be_true(tree != NULL);
git_oid_mkstr(&entry_id, tree_oid);
for (i = 0; i < entry_count; ++i) {
char filename[32];
sprintf(filename, "file%d.txt", i);
must_pass(git_tree_add_entry(tree, &entry_id, filename, 040000));
}
must_be_true(git_tree_entrycount(tree) == entry_count);
must_pass(git_object_write((git_object *)tree));
must_pass(remove_loose_object(odb_dir, (git_object *)tree));
git_repository_free(repo);
git_odb_close(db);
END_TEST
BEGIN_TEST(tree_add_entry_test) BEGIN_TEST(tree_add_entry_test)
git_odb *db; git_odb *db;
git_oid id; git_oid id;
......
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