diff options
Diffstat (limited to 'lib/sqfs/xattr_reader.c')
-rw-r--r-- | lib/sqfs/xattr_reader.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/lib/sqfs/xattr_reader.c b/lib/sqfs/xattr_reader.c index 7a881c7..399940f 100644 --- a/lib/sqfs/xattr_reader.c +++ b/lib/sqfs/xattr_reader.c @@ -14,6 +14,7 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <errno.h> struct xattr_reader_t { uint64_t xattr_start; @@ -54,7 +55,7 @@ static int get_id_block_locations(xattr_reader_t *xr, int sqfsfd, if ((xr->num_ids * sizeof(sqfs_xattr_id_t)) % SQFS_META_BLOCK_SIZE) xr->num_id_blocks += 1; - xr->id_block_starts = calloc(sizeof(uint64_t), xr->num_id_blocks); + xr->id_block_starts = alloc_array(sizeof(uint64_t), xr->num_id_blocks); if (xr->id_block_starts == NULL) { perror("allocating xattr ID location table"); return -1; @@ -63,7 +64,7 @@ static int get_id_block_locations(xattr_reader_t *xr, int sqfsfd, if (read_data_at("reading xattr ID block locations", super->xattr_id_table_start + sizeof(idtbl), sqfsfd, xr->id_block_starts, - sizeof(xr->id_block_starts[0]) * xr->num_id_blocks)) { + sizeof(uint64_t) * xr->num_id_blocks)) { goto fail; } @@ -127,7 +128,7 @@ static sqfs_xattr_entry_t *read_key(xattr_reader_t *xr) { sqfs_xattr_entry_t key, *out; const char *prefix; - size_t plen; + size_t plen, total; if (meta_reader_read(xr->kvrd, &key, sizeof(key))) return NULL; @@ -143,10 +144,16 @@ static sqfs_xattr_entry_t *read_key(xattr_reader_t *xr) } plen = strlen(prefix); - out = calloc(1, sizeof(*out) + plen + key.size + 1); + + if (SZ_ADD_OV(plen, key.size, &total) || SZ_ADD_OV(total, 1, &total) || + SZ_ADD_OV(sizeof(*out), total, &total)) { + errno = EOVERFLOW; + goto fail_alloc; + } + + out = calloc(1, total); if (out == NULL) { - perror("restoring xattr key"); - return NULL; + goto fail_alloc; } *out = key; @@ -158,14 +165,17 @@ static sqfs_xattr_entry_t *read_key(xattr_reader_t *xr) } return out; +fail_alloc: + perror("allocating xattr key"); + return NULL; } static sqfs_xattr_value_t *read_value(xattr_reader_t *xr, const sqfs_xattr_entry_t *key) { + size_t offset, new_offset, size; sqfs_xattr_value_t value, *out; uint64_t ref, start, new_start; - size_t offset, new_offset; if (meta_reader_read(xr->kvrd, &value, sizeof(value))) return NULL; @@ -197,12 +207,16 @@ static sqfs_xattr_value_t *read_value(xattr_reader_t *xr, value.size = le32toh(value.size); - out = calloc(1, sizeof(*out) + value.size); - if (out == NULL) { - perror("reading xattr value"); - return NULL; + if (SZ_ADD_OV(sizeof(*out), value.size, &size) || + SZ_ADD_OV(size, 1, &size)) { + errno = EOVERFLOW; + goto fail_alloc; } + out = calloc(1, size); + if (out == NULL) + goto fail_alloc; + *out = value; if (meta_reader_read(xr->kvrd, out->value, value.size)) @@ -214,6 +228,9 @@ static sqfs_xattr_value_t *read_value(xattr_reader_t *xr, } return out; +fail_alloc: + perror("allocating xattr value"); + return NULL; fail: free(out); return NULL; @@ -283,7 +300,6 @@ int xattr_reader_restore_node(xattr_reader_t *xr, fstree_t *fs, { sqfs_xattr_id_t desc; tree_xattr_t *it; - size_t size; if (xr->kvrd == NULL || xr->idrd == NULL) return 0; @@ -301,10 +317,8 @@ int xattr_reader_restore_node(xattr_reader_t *xr, fstree_t *fs, if (get_xattr_desc(xr, xattr, &desc)) return -1; - size = sizeof(*node->xattr); - size += sizeof(node->xattr->attr[0]) * desc.count; - - node->xattr = calloc(1, size); + node->xattr = alloc_flex(sizeof(*node->xattr), + sizeof(node->xattr->attr[0]), desc.count); if (node->xattr == NULL) { perror("creating xattr structure"); return -1; |