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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
diff --git a/src/attr.c b/src/attr.c
index 06a6601..cbc2a5b 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -227,14 +227,16 @@ int git_attr_cache__push_file(
git_attr_file *file;
int add_to_cache = 0;
- if (base != NULL &&
- (error = git_buf_joinpath(&path, base, filename)) < GIT_SUCCESS)
- goto cleanup;
+ if (base != NULL) {
+ if ((error = git_buf_joinpath(&path, base, filename)) < GIT_SUCCESS)
+ goto cleanup;
+ filename = path.ptr;
+ }
/* either get attr_file from cache or read from disk */
- file = git_hashtable_lookup(cache->files, path.ptr);
- if (file == NULL && git_futils_exists(path.ptr) == GIT_SUCCESS) {
- error = (*loader)(repo, path.ptr, &file);
+ file = git_hashtable_lookup(cache->files, filename);
+ if (file == NULL && git_futils_exists(filename) == GIT_SUCCESS) {
+ error = (*loader)(repo, filename, &file);
add_to_cache = (error == GIT_SUCCESS);
}
diff --git a/src/buffer.c b/src/buffer.c
index b685425..c57e4aa 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -181,7 +181,7 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf)
{
size_t copylen;
- assert(data && datasize);
+ assert(data && datasize && buf);
data[0] = '\0';
diff --git a/src/ignore.c b/src/ignore.c
index fa71d49..cdc3eda 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -23,6 +23,8 @@ static int load_ignore_file(
if ((error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS)
error = git_attr_file__new(&ignores);
+ ignores->path = git__strdup(path);
+
scan = fbuf.data;
while (error == GIT_SUCCESS && *scan) {
@@ -49,10 +51,10 @@ static int load_ignore_file(
}
git_futils_freebuffer(&fbuf);
+ git__free(match);
if (error != GIT_SUCCESS) {
git__rethrow(error, "Could not open ignore file '%s'", path);
- git__free(match);
git_attr_file__free(ignores);
} else {
*out = ignores;
diff --git a/src/path.c b/src/path.c
index 4888123..03ebfe0 100644
--- a/src/path.c
+++ b/src/path.c
@@ -329,6 +329,7 @@ int git_path_walk_up(
iter.ptr = path->ptr;
iter.size = path->size;
+ iter.asize = path->asize;
while (scan >= stop) {
if ((error = cb(data, &iter)) < GIT_SUCCESS)
@@ -343,7 +344,8 @@ int git_path_walk_up(
}
}
- iter.ptr[scan] = oldc;
+ if (scan >= 0)
+ iter.ptr[scan] = oldc;
return error;
}
diff --git a/src/status.c b/src/status.c
index a926938..72ee7b0 100644
--- a/src/status.c
+++ b/src/status.c
@@ -678,28 +678,15 @@ cleanup:
*
*/
-struct alphasorted_dirent_info {
- int is_dir;
- char path[GIT_FLEX_ARRAY]; /* more */
-};
-
-static struct alphasorted_dirent_info *alphasorted_dirent_info_new(const git_buf *path)
+static char *alphasorted_dirent_info_new(const git_buf *path)
{
- int is_dir, size;
- struct alphasorted_dirent_info *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;
+ char *di = git__malloc(path->size + 2);
+ if (!di)
+ return di;
- git_buf_copy_cstr(di->path, path->size + 1, path);
-
- if (is_dir) {
- di->is_dir = 1;
+ git_buf_copy_cstr(di, path->size + 1, path);
+ if (git_futils_isdir(path->ptr) == GIT_SUCCESS) {
/*
* Append a forward slash to the name to force folders
* 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
* The file "subdir" should appear before 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;
}
-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)
{
- struct alphasorted_dirent_info *entry;
+ char *entry;
git_vector *entry_names;
entry_names = (git_vector *)state;
@@ -745,13 +725,13 @@ static int alphasorted_futils_direach(
int (*fn)(void *, git_buf *),
void *arg)
{
- struct alphasorted_dirent_info *entry;
+ char *entry;
git_vector entry_names;
unsigned int idx;
int error = GIT_SUCCESS;
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;
error = git_futils_direach(path, alphasorted_dirent_cb, &entry_names);
@@ -759,17 +739,18 @@ static int alphasorted_futils_direach(
git_vector_sort(&entry_names);
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,
* in order to free up memory, but we stop making callbacks after
* an error.
*/
if (error == GIT_SUCCESS)
- error = git_buf_sets(&entry_path, entry->path);
+ error = git_buf_sets(&entry_path, entry);
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);
}