Commit 1dbcc9fc by Russell Belfer

Fix several memory issues

This contains fixes for several issues discovered by MSVC and
by valgrind, including some bad data access, some memory
leakage (in where certain files were not being successfully
added to the cache), and some code simplification.
parent 0cfcff5d
...@@ -227,14 +227,16 @@ int git_attr_cache__push_file( ...@@ -227,14 +227,16 @@ int git_attr_cache__push_file(
git_attr_file *file; git_attr_file *file;
int add_to_cache = 0; int add_to_cache = 0;
if (base != NULL && if (base != NULL) {
(error = git_buf_joinpath(&path, base, filename)) < GIT_SUCCESS) if ((error = git_buf_joinpath(&path, base, filename)) < GIT_SUCCESS)
goto cleanup; goto cleanup;
filename = path.ptr;
}
/* either get attr_file from cache or read from disk */ /* either get attr_file from cache or read from disk */
file = git_hashtable_lookup(cache->files, path.ptr); file = git_hashtable_lookup(cache->files, filename);
if (file == NULL && git_futils_exists(path.ptr) == GIT_SUCCESS) { if (file == NULL && git_futils_exists(filename) == GIT_SUCCESS) {
error = (*loader)(repo, path.ptr, &file); error = (*loader)(repo, filename, &file);
add_to_cache = (error == GIT_SUCCESS); add_to_cache = (error == GIT_SUCCESS);
} }
......
...@@ -181,7 +181,7 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf) ...@@ -181,7 +181,7 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf)
{ {
size_t copylen; size_t copylen;
assert(data && datasize); assert(data && datasize && buf);
data[0] = '\0'; data[0] = '\0';
......
...@@ -23,6 +23,8 @@ static int load_ignore_file( ...@@ -23,6 +23,8 @@ static int load_ignore_file(
if ((error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS) if ((error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS)
error = git_attr_file__new(&ignores); error = git_attr_file__new(&ignores);
ignores->path = git__strdup(path);
scan = fbuf.data; scan = fbuf.data;
while (error == GIT_SUCCESS && *scan) { while (error == GIT_SUCCESS && *scan) {
...@@ -49,10 +51,10 @@ static int load_ignore_file( ...@@ -49,10 +51,10 @@ static int load_ignore_file(
} }
git_futils_freebuffer(&fbuf); git_futils_freebuffer(&fbuf);
git__free(match);
if (error != GIT_SUCCESS) { if (error != GIT_SUCCESS) {
git__rethrow(error, "Could not open ignore file '%s'", path); git__rethrow(error, "Could not open ignore file '%s'", path);
git__free(match);
git_attr_file__free(ignores); git_attr_file__free(ignores);
} else { } else {
*out = ignores; *out = ignores;
......
...@@ -329,6 +329,7 @@ int git_path_walk_up( ...@@ -329,6 +329,7 @@ int git_path_walk_up(
iter.ptr = path->ptr; iter.ptr = path->ptr;
iter.size = path->size; iter.size = path->size;
iter.asize = path->asize;
while (scan >= stop) { while (scan >= stop) {
if ((error = cb(data, &iter)) < GIT_SUCCESS) if ((error = cb(data, &iter)) < GIT_SUCCESS)
...@@ -343,7 +344,8 @@ int git_path_walk_up( ...@@ -343,7 +344,8 @@ int git_path_walk_up(
} }
} }
iter.ptr[scan] = oldc; if (scan >= 0)
iter.ptr[scan] = oldc;
return error; return error;
} }
...@@ -678,28 +678,15 @@ cleanup: ...@@ -678,28 +678,15 @@ cleanup:
* *
*/ */
struct alphasorted_dirent_info { static char *alphasorted_dirent_info_new(const git_buf *path)
int is_dir;
char path[GIT_FLEX_ARRAY]; /* more */
};
static struct alphasorted_dirent_info *alphasorted_dirent_info_new(const git_buf *path)
{ {
int is_dir, size; char *di = git__malloc(path->size + 2);
struct alphasorted_dirent_info *di; if (!di)
return di;
is_dir = git_futils_isdir(path->ptr) == GIT_SUCCESS ? 1 : 0;
size = sizeof(*di) + path->size + is_dir + 1;
di = git__calloc(size, 1);
if (di == NULL)
return NULL;
git_buf_copy_cstr(di->path, path->size + 1, path); git_buf_copy_cstr(di, path->size + 1, path);
if (is_dir) {
di->is_dir = 1;
if (git_futils_isdir(path->ptr) == GIT_SUCCESS) {
/* /*
* Append a forward slash to the name to force folders * Append a forward slash to the name to force folders
* to be ordered in a similar way than in a tree * to be ordered in a similar way than in a tree
...@@ -707,23 +694,16 @@ static struct alphasorted_dirent_info *alphasorted_dirent_info_new(const git_buf ...@@ -707,23 +694,16 @@ static struct alphasorted_dirent_info *alphasorted_dirent_info_new(const git_buf
* The file "subdir" should appear before the file "subdir.txt" * The file "subdir" should appear before the file "subdir.txt"
* The folder "subdir" should appear after the file "subdir.txt" * The folder "subdir" should appear after the file "subdir.txt"
*/ */
di->path[path->size] = '/'; di[path->size] = '/';
di[path->size + 1] = '\0';
} }
return di; return di;
} }
static int alphasorted_dirent_info_cmp(const void *a, const void *b)
{
struct alphasorted_dirent_info *stra = (struct alphasorted_dirent_info *)a;
struct alphasorted_dirent_info *strb = (struct alphasorted_dirent_info *)b;
return strcmp(stra->path, strb->path);
}
static int alphasorted_dirent_cb(void *state, git_buf *full_path) static int alphasorted_dirent_cb(void *state, git_buf *full_path)
{ {
struct alphasorted_dirent_info *entry; char *entry;
git_vector *entry_names; git_vector *entry_names;
entry_names = (git_vector *)state; entry_names = (git_vector *)state;
...@@ -745,13 +725,13 @@ static int alphasorted_futils_direach( ...@@ -745,13 +725,13 @@ static int alphasorted_futils_direach(
int (*fn)(void *, git_buf *), int (*fn)(void *, git_buf *),
void *arg) void *arg)
{ {
struct alphasorted_dirent_info *entry; char *entry;
git_vector entry_names; git_vector entry_names;
unsigned int idx; unsigned int idx;
int error = GIT_SUCCESS; int error = GIT_SUCCESS;
git_buf entry_path = GIT_BUF_INIT; git_buf entry_path = GIT_BUF_INIT;
if (git_vector_init(&entry_names, 16, alphasorted_dirent_info_cmp) < GIT_SUCCESS) if (git_vector_init(&entry_names, 16, git__strcmp_cb) < GIT_SUCCESS)
return GIT_ENOMEM; return GIT_ENOMEM;
error = git_futils_direach(path, alphasorted_dirent_cb, &entry_names); error = git_futils_direach(path, alphasorted_dirent_cb, &entry_names);
...@@ -759,17 +739,18 @@ static int alphasorted_futils_direach( ...@@ -759,17 +739,18 @@ static int alphasorted_futils_direach(
git_vector_sort(&entry_names); git_vector_sort(&entry_names);
for (idx = 0; idx < entry_names.length; ++idx) { for (idx = 0; idx < entry_names.length; ++idx) {
entry = (struct alphasorted_dirent_info *)git_vector_get(&entry_names, idx); entry = (char *)git_vector_get(&entry_names, idx);
/* We have to walk the entire vector even if there was an error, /* We have to walk the entire vector even if there was an error,
* in order to free up memory, but we stop making callbacks after * in order to free up memory, but we stop making callbacks after
* an error. * an error.
*/ */
if (error == GIT_SUCCESS) if (error == GIT_SUCCESS)
error = git_buf_sets(&entry_path, entry->path); error = git_buf_sets(&entry_path, entry);
if (error == GIT_SUCCESS) { if (error == GIT_SUCCESS) {
((struct status_st *)arg)->is_dir = entry->is_dir; ((struct status_st *)arg)->is_dir =
(entry[entry_path.size - 1] == '/');
error = fn(arg, &entry_path); error = fn(arg, &entry_path);
} }
......
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