diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/index.c | 102 | ||||
| -rw-r--r-- | src/repository.c | 23 | ||||
| -rw-r--r-- | src/repository.h | 1 |
3 files changed, 72 insertions, 54 deletions
diff --git a/src/index.c b/src/index.c index 389780295..d3590da42 100644 --- a/src/index.c +++ b/src/index.c @@ -99,7 +99,7 @@ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffe static int read_header(struct index_header *dest, const void *buffer); static int read_tree(git_index *index, const char *buffer, size_t buffer_size); -static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *); +static int read_tree_internal(git_index_tree **, const char **, const char *, git_index_tree *); static int parse_index(git_index *index, const char *buffer, size_t buffer_size); static int is_index_extended(git_index *index); @@ -168,13 +168,19 @@ static int index_initialize(git_index **index_out, git_repository *owner, const return git_index_read(index); } -int git_index_open_bare(git_index **index_out, const char *index_path) +int git_index_open(git_index **index_out, const char *index_path) { + assert(index_out && index_path); return index_initialize(index_out, NULL, index_path); } -int git_index_open_inrepo(git_index **index_out, git_repository *repo) +/* + * Moved from `repository.c` + */ +int git_repository_index(git_index **index_out, git_repository *repo) { + assert(index_out && repo); + if (repo->is_bare) return git__throw(GIT_EBAREINDEX, "Failed to open index. Repository is bare"); @@ -183,7 +189,7 @@ int git_index_open_inrepo(git_index **index_out, git_repository *repo) void git_index_free(git_index *index) { - if (index == NULL || index->repository != NULL) + if (index == NULL) return; git_index_clear(index); @@ -479,52 +485,81 @@ const git_index_entry_unmerged *git_index_get_unmerged(git_index *index, const c } -static git_index_tree *read_tree_internal( +static int read_tree_internal(git_index_tree **out, const char **buffer_in, const char *buffer_end, git_index_tree *parent) { git_index_tree *tree; const char *name_start, *buffer; long count; + int error = GIT_SUCCESS; if ((tree = git__malloc(sizeof(git_index_tree))) == NULL) - return NULL; + return GIT_ENOMEM; memset(tree, 0x0, sizeof(git_index_tree)); tree->parent = parent; buffer = name_start = *buffer_in; - if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL) - goto error_cleanup; + if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } /* NUL-terminated tree name */ tree->name = git__strdup(name_start); - if (++buffer >= buffer_end) - goto error_cleanup; + if (tree->name == NULL) { + error = GIT_ENOMEM; + goto cleanup; + } + + if (++buffer >= buffer_end) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } /* Blank-terminated ASCII decimal number of entries in this tree */ - if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS || - count < 0) - goto error_cleanup; + if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS || count < -1) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } + + /* Invalidated TREE. Free the tree but report success */ + if (count == -1) { + /* FIXME: return buffer_end or the end position for + * this single tree entry */ + *buffer_in = buffer_end; + *out = NULL; + free_tree(tree); /* Needs to be done manually */ + return GIT_SUCCESS; + } tree->entries = (size_t)count; - if (*buffer != ' ' || ++buffer >= buffer_end) - goto error_cleanup; + if (*buffer != ' ' || ++buffer >= buffer_end) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } /* Number of children of the tree, newline-terminated */ if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS || - count < 0) - goto error_cleanup; + count < 0) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } tree->children_count = (size_t)count; - if (*buffer != '\n' || ++buffer >= buffer_end) - goto error_cleanup; + if (*buffer != '\n' || ++buffer >= buffer_end) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } /* 160-bit SHA-1 for this tree and it's children */ - if (buffer + GIT_OID_RAWSZ > buffer_end) - goto error_cleanup; + if (buffer + GIT_OID_RAWSZ > buffer_end) { + error = GIT_EOBJCORRUPTED; + goto cleanup; + } git_oid_mkraw(&tree->oid, (const unsigned char *)buffer); buffer += GIT_OID_RAWSZ; @@ -532,33 +567,40 @@ static git_index_tree *read_tree_internal( /* Parse children: */ if (tree->children_count > 0) { unsigned int i; + int err; tree->children = git__malloc(tree->children_count * sizeof(git_index_tree *)); if (tree->children == NULL) - goto error_cleanup; + goto cleanup; for (i = 0; i < tree->children_count; ++i) { - tree->children[i] = read_tree_internal(&buffer, buffer_end, tree); + err = read_tree_internal(&tree->children[i], &buffer, buffer_end, tree); - if (tree->children[i] == NULL) - goto error_cleanup; + if (err < GIT_SUCCESS) + goto cleanup; } } *buffer_in = buffer; - return tree; + *out = tree; + return GIT_SUCCESS; -error_cleanup: + cleanup: free_tree(tree); - return NULL; + return error; } static int read_tree(git_index *index, const char *buffer, size_t buffer_size) { const char *buffer_end = buffer + buffer_size; + int error; + + error = read_tree_internal(&index->tree, &buffer, buffer_end, NULL); - index->tree = read_tree_internal(&buffer, buffer_end, NULL); - return (index->tree != NULL && buffer == buffer_end) ? GIT_SUCCESS : GIT_EOBJCORRUPTED; + if (buffer < buffer_end) + return GIT_EOBJCORRUPTED; + + return error; } static int read_unmerged(git_index *index, const char *buffer, size_t size) diff --git a/src/repository.c b/src/repository.c index 2054999fc..32ca8dd79 100644 --- a/src/repository.c +++ b/src/repository.c @@ -315,32 +315,9 @@ void git_repository_free(git_repository *repo) if (repo->db != NULL) git_odb_close(repo->db); - if (repo->index != NULL) { - repo->index->repository = NULL; - git_index_free(repo->index); - } - free(repo); } -int git_repository_index(git_index **index_out, git_repository *repo) -{ - int error; - - assert(index_out && repo); - - if (repo->index == NULL) { - error = git_index_open_inrepo(&repo->index, repo); /* TODO: move index.c to new error handling */ - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to open repository index"); - - assert(repo->index != NULL); - } - - *index_out = repo->index; - return GIT_SUCCESS; -} - git_odb *git_repository_database(git_repository *repo) { assert(repo); diff --git a/src/repository.h b/src/repository.h index 813cac942..bcf9b2bc8 100644 --- a/src/repository.h +++ b/src/repository.h @@ -25,7 +25,6 @@ struct git_object { struct git_repository { git_odb *db; - git_index *index; git_cache objects; git_refcache references; |
