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);
* @iparam id OID for the tree entry
* @param filename Filename for the tree 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.
......
......@@ -29,17 +29,24 @@
#include "tree.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;
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 *));
if (new_entries == NULL)
return GIT_ENOMEM;
memcpy(new_entries, tree->entries, tree->entry_count * sizeof(git_tree_entry *));
free(tree->entries);
tree->entries = new_entries;
return GIT_SUCCESS;
}
int entry_cmp(const void *key, const void *array_member)
......@@ -166,17 +173,18 @@ size_t git_tree_entrycount(git_tree *tree)
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;
assert(tree && id && filename);
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)
return;
return GIT_ENOMEM;
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,
entry_resort(tree);
tree->object.modified = 1;
return GIT_SUCCESS;
}
int git_tree_remove_entry_byindex(git_tree *tree, int idx)
......@@ -277,11 +286,15 @@ int git_tree__parse(git_tree *tree)
tree->array_size = (tree->object.source.raw.len / avg_entry_size) + 1;
tree->entries = git__malloc(tree->array_size * sizeof(git_tree_entry *));
if (tree->entries == NULL)
return GIT_ENOMEM;
while (buffer < buffer_end) {
git_tree_entry *entry;
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));
if (entry == NULL) {
......
......@@ -9,6 +9,39 @@
static const char *odb_dir = "../resources/sample-odb";
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)
git_odb *db;
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