summaryrefslogtreecommitdiff
path: root/lib/sqfs
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-23 08:34:11 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-23 08:48:04 +0200
commite6c869ab1753986b032463f2e0bd5fad7bc70e0f (patch)
tree6ef2ecc7a55ecb1fa9087e7d0e0628a7eb9616c8 /lib/sqfs
parent88d53c4c124a6e3979a7b4f79b3f95bfc3706604 (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.c16
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);