diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-23 13:23:58 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-23 13:44:13 +0200 |
commit | a38b1cbc5e917d945340a6dd9dba4274a2eb8789 (patch) | |
tree | be3a59cc2c3013c95fe5899306232dabff25c9de /lib/fstree/mknode.c | |
parent | 029a8db2701afb0653c6e789c878bb768ceb87e1 (diff) |
Size accounting + alloc() overflow checking, round #2
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/fstree/mknode.c')
-rw-r--r-- | lib/fstree/mknode.c | 40 |
1 files changed, 32 insertions, 8 deletions
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; } |