fs/squashfs: fix reading of fragmented files
authorJoao Marcos Costa <jmcosta944@gmail.com>
Mon, 17 May 2021 21:20:38 +0000 (18:20 -0300)
committerTom Rini <trini@konsulko.com>
Thu, 10 Jun 2021 00:58:20 +0000 (20:58 -0400)
The fragmented files were not correctly read because of two issues:

- The squashfs_file_info struct has a field named 'comp', which tells if
the file's fragment is compressed or not. This field was always set to
'true' in sqfs_get_regfile_info and sqfs_get_lregfile_info. It should
actually take sqfs_frag_lookup's return value. This patch addresses
these two assignments.

- In sqfs_read, the fragments (compressed or not) were copied to the
output buffer through a for loop which was reading data at the wrong
offset. Replace these loops by equivalent calls to memcpy, with the
right parameters.

I tested this patch by comparing the MD5 checksum of a few fragmented
files with the respective md5sum output in sandbox, considering both
compressed and uncompressed fragments.

Signed-off-by: Joao Marcos Costa <jmcosta944@gmail.com>
Tested-by: Richard Genoud <richard.genoud@posteo.net>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
fs/squashfs/sqfs.c

index 997be2d..92ab8ac 100644 (file)
@@ -1253,7 +1253,7 @@ static int sqfs_get_regfile_info(struct squashfs_reg_inode *reg,
                                       fentry);
                if (ret < 0)
                        return -EINVAL;
-               finfo->comp = true;
+               finfo->comp = ret;
                if (fentry->size < 1 || fentry->start == 0x7FFFFFFF)
                        return -EINVAL;
        } else {
@@ -1291,7 +1291,7 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
                                       fentry);
                if (ret < 0)
                        return -EINVAL;
-               finfo->comp = true;
+               finfo->comp = ret;
                if (fentry->size < 1 || fentry->start == 0x7FFFFFFF)
                        return -EINVAL;
        } else {
@@ -1547,20 +1547,16 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                        goto out;
                }
 
-               for (j = *actread; j < finfo.size; j++) {
-                       memcpy(buf + j, &fragment_block[finfo.offset + j], 1);
-                       (*actread)++;
-               }
+               memcpy(buf + *actread, &fragment_block[finfo.offset], finfo.size - *actread);
+               *actread = finfo.size;
 
                free(fragment_block);
 
        } else if (finfo.frag && !finfo.comp) {
                fragment_block = (void *)fragment + table_offset;
 
-               for (j = *actread; j < finfo.size; j++) {
-                       memcpy(buf + j, &fragment_block[finfo.offset + j], 1);
-                       (*actread)++;
-               }
+               memcpy(buf + *actread, &fragment_block[finfo.offset], finfo.size - *actread);
+               *actread = finfo.size;
        }
 
 out: