diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-07-23 08:34:11 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-07-23 08:48:04 +0200 |
commit | e6c869ab1753986b032463f2e0bd5fad7bc70e0f (patch) | |
tree | 6ef2ecc7a55ecb1fa9087e7d0e0628a7eb9616c8 /lib/sqfs | |
parent | 88d53c4c124a6e3979a7b4f79b3f95bfc3706604 (diff) |
Fix tree node scanning
- Bail early on empty directories without touching the meta readers.
- Aport the directory read loop if we can't even read a header anymore,
no matter if there are bytes remaining.
- Also add that same condition to the inner loop.
The later two actually caused a numeric overflow on some particularly
malformed squashfs images, going into a RAM filling infinite loop.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs')
-rw-r--r-- | lib/sqfs/deserialize_fstree.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/lib/sqfs/deserialize_fstree.c b/lib/sqfs/deserialize_fstree.c index e90e1c1..bc1d6e4 100644 --- a/lib/sqfs/deserialize_fstree.c +++ b/lib/sqfs/deserialize_fstree.c @@ -38,27 +38,31 @@ static int fill_dir(meta_reader_t *ir, meta_reader_t *dr, tree_node_t *root, size_t size, diff; uint32_t i; + size = root->data.dir->size; + if (size <= sizeof(hdr)) + return 0; + block_start = root->data.dir->start_block; block_start += super->directory_table_start; if (meta_reader_seek(dr, block_start, root->data.dir->block_offset)) return -1; - size = root->data.dir->size; - - while (size != 0) { + while (size > sizeof(hdr)) { if (meta_reader_read_dir_header(dr, &hdr)) return -1; - size -= sizeof(hdr) > size ? size : sizeof(hdr); + size -= sizeof(hdr); - for (i = 0; i <= hdr.count; ++i) { + for (i = 0; i <= hdr.count && size > sizeof(*ent); ++i) { ent = meta_reader_read_dir_ent(dr); if (ent == NULL) return -1; diff = sizeof(*ent) + strlen((char *)ent->name); - size -= diff > size ? size : diff; + if (diff > size) + break; + size -= diff; if (should_skip(ent->type, flags)) { free(ent); |