mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-21 22:21:37 +00:00
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>
This commit is contained in:
parent
0ba7a03186
commit
e4def81aab
@ -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.
|
||||||
|
25
src/tree.c
25
src/tree.c
@ -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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user