diff options
Diffstat (limited to 'lib/fstree')
-rw-r--r-- | lib/fstree/fstree_from_dir.c | 9 | ||||
-rw-r--r-- | lib/fstree/get_path.c | 16 | ||||
-rw-r--r-- | lib/fstree/mknode.c | 40 |
3 files changed, 53 insertions, 12 deletions
diff --git a/lib/fstree/fstree_from_dir.c b/lib/fstree/fstree_from_dir.c index 9aab5df..d6fac86 100644 --- a/lib/fstree/fstree_from_dir.c +++ b/lib/fstree/fstree_from_dir.c @@ -25,6 +25,7 @@ static char *get_file_path(tree_node_t *n, const char *name) { char *ptr, *new; + size_t len; int ret; if (n->parent == NULL) { @@ -41,7 +42,13 @@ static char *get_file_path(tree_node_t *n, const char *name) ret = canonicalize_name(ptr); assert(ret == 0); - new = realloc(ptr, strlen(ptr) + strlen(name) + 2); + if (SZ_ADD_OV(strlen(ptr), strlen(name), &len) || + SZ_ADD_OV(len, 2, &len)) { + errno = EOVERFLOW; + goto fail; + } + + new = realloc(ptr, len); if (new == NULL) goto fail; diff --git a/lib/fstree/get_path.c b/lib/fstree/get_path.c index decf92e..f464ade 100644 --- a/lib/fstree/get_path.c +++ b/lib/fstree/get_path.c @@ -7,9 +7,11 @@ #include "config.h" #include "fstree.h" +#include "util.h" #include <string.h> #include <stdlib.h> +#include <errno.h> char *fstree_get_path(tree_node_t *node) { @@ -21,14 +23,19 @@ char *fstree_get_path(tree_node_t *node) return strdup("/"); for (it = node; it != NULL && it->parent != NULL; it = it->parent) { - len += strlen(it->name) + 1; + if (SZ_ADD_OV(len, strlen(it->name), &len) || + SZ_ADD_OV(len, 1, &len)) + goto fail_ov; } - str = malloc(len + 1); + if (SZ_ADD_OV(len, 1, &len)) + goto fail_ov; + + str = malloc(len); if (str == NULL) return NULL; - ptr = str + len; + ptr = str + len - 1; *ptr = '\0'; for (it = node; it != NULL && it->parent != NULL; it = it->parent) { @@ -40,4 +47,7 @@ char *fstree_get_path(tree_node_t *node) } return str; +fail_ov: + errno = EOVERFLOW; + return NULL; } diff --git a/lib/fstree/mknode.c b/lib/fstree/mknode.c index 9132458..1c3b3a0 100644 --- a/lib/fstree/mknode.c +++ b/lib/fstree/mknode.c @@ -17,7 +17,7 @@ tree_node_t *fstree_mknode(fstree_t *fs, tree_node_t *parent, const char *name, size_t name_len, const char *extra, const struct stat *sb) { - size_t size = sizeof(tree_node_t), block_count = 0; + size_t size = sizeof(tree_node_t), block_count = 0, total; tree_node_t *n; char *ptr; @@ -27,24 +27,45 @@ tree_node_t *fstree_mknode(fstree_t *fs, tree_node_t *parent, const char *name, errno = EINVAL; return NULL; } - size += strlen(extra) + 1; + if (SZ_ADD_OV(size, strlen(extra), &size) || + SZ_ADD_OV(size, 1, &size)) { + goto fail_ov; + } break; case S_IFDIR: - size += sizeof(*n->data.dir); + if (SZ_ADD_OV(size, sizeof(*n->data.dir), &size)) + goto fail_ov; break; case S_IFREG: block_count = (sb->st_size / fs->block_size); if ((sb->st_size % fs->block_size) != 0) ++block_count; - size += sizeof(*n->data.file); - size += block_count * sizeof(n->data.file->blocks[0]); - if (extra != NULL) - size += strlen(extra) + 1; + if (SZ_MUL_OV(block_count, sizeof(n->data.file->blocks[0]), + &total)) { + goto fail_ov; + } + + if (SZ_ADD_OV(size, sizeof(*n->data.file), &size) || + SZ_ADD_OV(size, total, &size)) { + goto fail_ov; + } + + if (extra != NULL) { + if (SZ_ADD_OV(size, strlen(extra), &size) || + SZ_ADD_OV(size, 1, &size)) { + goto fail_ov; + } + } break; } - n = calloc(1, size + name_len + 1); + if (SZ_ADD_OV(size, name_len, &total) || + SZ_ADD_OV(total, 1, &total)) { + goto fail_ov; + } + + n = calloc(1, total); if (n == NULL) return NULL; @@ -91,4 +112,7 @@ tree_node_t *fstree_mknode(fstree_t *fs, tree_node_t *parent, const char *name, n->name = (char *)n + size; memcpy(n->name, name, name_len); return n; +fail_ov: + errno = EOVERFLOW; + return NULL; } |