summaryrefslogtreecommitdiff
path: root/src/tree.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2010-10-28 02:07:18 +0300
committerVicent Marti <tanoku@gmail.com>2010-10-28 02:07:18 +0300
commit585190183b47dc991605abcfbe3afb57220a0f29 (patch)
treef8a1f2572f667296a5b5121c64c74bb353557c93 /src/tree.c
parent2d16373cb8d8c22b3ec99a6936b82821e99e64a5 (diff)
downloadlibgit2-585190183b47dc991605abcfbe3afb57220a0f29.tar.gz
Fix internal memory management on the library
String mememory is now managed in a much more sane manner. Fixes include: - git_person email and name is no longer limited to 64 characters - git_tree_entry filename is no longer limited to 255 characters - raw objects are properly opened & closed the minimum amount of times required for parsing - unit tests no longer leak - removed 5 other misc memory leaks as reported by Valgrind - tree writeback no longer segfaults on rare ocassions The git_person struct is no longer public. It is now managed by the library, and getter methods are in place to access its internal attributes. Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src/tree.c')
-rw-r--r--src/tree.c77
1 files changed, 46 insertions, 31 deletions
diff --git a/src/tree.c b/src/tree.c
index 28bc035d2..526f9dc31 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -70,17 +70,26 @@ static void entry_resort(git_tree *tree)
qsort(tree->entries, tree->entry_count, sizeof(git_tree_entry *), entry_sort_cmp);
}
-
-
-
-void git_tree__free(git_tree *tree)
+static void free_tree_entries(git_tree *tree)
{
size_t i;
- for (i = 0; i < tree->entry_count; ++i)
+ if (tree == NULL)
+ return;
+
+ for (i = 0; i < tree->entry_count; ++i) {
+ free(tree->entries[i]->filename);
free(tree->entries[i]);
+ }
free(tree->entries);
+}
+
+
+
+void git_tree__free(git_tree *tree)
+{
+ free_tree_entries(tree);
free(tree);
}
@@ -111,7 +120,8 @@ void git_tree_entry_set_name(git_tree_entry *entry, const char *name)
{
assert(entry && entry->owner);
- strncpy(entry->filename, name, GIT_TREE_MAX_FILENAME);
+ free(entry->filename);
+ entry->filename = git__strdup(name);
entry_resort(entry->owner);
entry->owner->object.modified = 1;
}
@@ -188,7 +198,7 @@ int git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename,
memset(entry, 0x0, sizeof(git_tree_entry));
- strncpy(entry->filename, filename, GIT_TREE_MAX_FILENAME);
+ entry->filename = git__strdup(filename);
git_oid_cpy(&entry->oid, id);
entry->attr = attributes;
entry->owner = tree;
@@ -212,6 +222,7 @@ int git_tree_remove_entry_byindex(git_tree *tree, int idx)
remove_ptr = tree->entries[idx];
tree->entries[idx] = tree->entries[--tree->entry_count];
+ free(remove_ptr->filename);
free(remove_ptr);
entry_resort(tree);
@@ -237,6 +248,7 @@ int git_tree_remove_entry_byname(git_tree *tree, const char *filename)
int git_tree__writeback(git_tree *tree, git_odb_source *src)
{
size_t i;
+ char filemode[8];
assert(tree && src);
@@ -249,38 +261,23 @@ int git_tree__writeback(git_tree *tree, git_odb_source *src)
git_tree_entry *entry;
entry = tree->entries[i];
- git__source_printf(src, "%06o %s\0", entry->attr, entry->filename);
+ sprintf(filemode, "%06o ", entry->attr);
+
+ git__source_write(src, filemode, strlen(filemode));
+ git__source_write(src, entry->filename, strlen(entry->filename) + 1);
git__source_write(src, entry->oid.id, GIT_OID_RAWSZ);
- }
+ }
return GIT_SUCCESS;
}
-int git_tree__parse(git_tree *tree)
+static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
{
static const size_t avg_entry_size = 40;
-
int error = 0;
- char *buffer, *buffer_end;
-
- assert(!tree->object.in_memory);
- if (tree->entries != NULL) {
- size_t i;
-
- for (i = 0; i < tree->entry_count; ++i)
- free(tree->entries[i]);
-
- free(tree->entries);
- }
-
- error = git_object__source_open((git_object *)tree);
- if (error < 0)
- return error;
-
- buffer = tree->object.source.raw.data;
- buffer_end = buffer + tree->object.source.raw.len;
+ free_tree_entries(tree);
tree->entry_count = 0;
tree->array_size = (tree->object.source.raw.len / avg_entry_size) + 1;
@@ -312,7 +309,12 @@ int git_tree__parse(git_tree *tree)
break;
}
- strncpy(entry->filename, buffer, GIT_TREE_MAX_FILENAME);
+ if (memchr(buffer, 0, buffer_end - buffer) == NULL) {
+ error = GIT_EOBJCORRUPTED;
+ break;
+ }
+
+ entry->filename = git__strdup(buffer);
while (buffer < buffer_end && *buffer != 0)
buffer++;
@@ -323,6 +325,19 @@ int git_tree__parse(git_tree *tree)
buffer += GIT_OID_RAWSZ;
}
- git_object__source_close((git_object *)tree);
return error;
}
+
+int git_tree__parse(git_tree *tree)
+{
+ char *buffer, *buffer_end;
+
+ assert(tree && tree->object.source.open);
+ assert(!tree->object.in_memory);
+
+ buffer = tree->object.source.raw.data;
+ buffer_end = buffer + tree->object.source.raw.len;
+
+ return tree_parse_buffer(tree, buffer, buffer_end);
+}
+