mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-09-22 14:21:29 +02:00
fs/squashfs: sqfs_read: fix memory leak on finfo.blk_sizes
finfo.blk_sizes may not be freed in case of error in the for loop Setting it to null and freeing it at the end makes prevents that from happening. Reviewed-by: Joao Marcos Costa <jmcosta944@gmail.com> Signed-off-by: Richard Genoud <richard.genoud@posteo.net>
This commit is contained in:
parent
33686804d2
commit
571b67ee1d
@ -1305,8 +1305,8 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
|
|||||||
int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
||||||
loff_t *actread)
|
loff_t *actread)
|
||||||
{
|
{
|
||||||
char *dir, *fragment_block, *datablock = NULL, *data_buffer = NULL;
|
char *dir = NULL, *fragment_block, *datablock = NULL, *data_buffer = NULL;
|
||||||
char *fragment, *file, *resolved, *data;
|
char *fragment = NULL, *file = NULL, *resolved, *data;
|
||||||
u64 start, n_blks, table_size, data_offset, table_offset;
|
u64 start, n_blks, table_size, data_offset, table_offset;
|
||||||
int ret, j, i_number, datablk_count = 0;
|
int ret, j, i_number, datablk_count = 0;
|
||||||
struct squashfs_super_block *sblk = ctxt.sblk;
|
struct squashfs_super_block *sblk = ctxt.sblk;
|
||||||
@ -1331,7 +1331,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
sqfs_split_path(&file, &dir, filename);
|
sqfs_split_path(&file, &dir, filename);
|
||||||
ret = sqfs_opendir(dir, &dirsp);
|
ret = sqfs_opendir(dir, &dirsp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirs = (struct squashfs_dir_stream *)dirsp;
|
dirs = (struct squashfs_dir_stream *)dirsp;
|
||||||
@ -1350,7 +1350,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
printf("File not found.\n");
|
printf("File not found.\n");
|
||||||
*actread = 0;
|
*actread = 0;
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
i_number = dirs->dir_header->inode_number + dirs->entry->inode_offset;
|
i_number = dirs->dir_header->inode_number + dirs->entry->inode_offset;
|
||||||
@ -1365,7 +1365,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
sblk->block_size);
|
sblk->block_size);
|
||||||
if (datablk_count < 0) {
|
if (datablk_count < 0) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(finfo.blk_sizes, ipos + sizeof(*reg),
|
memcpy(finfo.blk_sizes, ipos + sizeof(*reg),
|
||||||
@ -1378,7 +1378,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
sblk->block_size);
|
sblk->block_size);
|
||||||
if (datablk_count < 0) {
|
if (datablk_count < 0) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(finfo.blk_sizes, ipos + sizeof(*lreg),
|
memcpy(finfo.blk_sizes, ipos + sizeof(*lreg),
|
||||||
@ -1390,7 +1390,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
resolved = sqfs_resolve_symlink(symlink, filename);
|
resolved = sqfs_resolve_symlink(symlink, filename);
|
||||||
ret = sqfs_read(resolved, buf, offset, len, actread);
|
ret = sqfs_read(resolved, buf, offset, len, actread);
|
||||||
free(resolved);
|
free(resolved);
|
||||||
goto free_paths;
|
goto out;
|
||||||
case SQFS_BLKDEV_TYPE:
|
case SQFS_BLKDEV_TYPE:
|
||||||
case SQFS_CHRDEV_TYPE:
|
case SQFS_CHRDEV_TYPE:
|
||||||
case SQFS_LBLKDEV_TYPE:
|
case SQFS_LBLKDEV_TYPE:
|
||||||
@ -1402,14 +1402,14 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
default:
|
default:
|
||||||
printf("Unsupported entry type\n");
|
printf("Unsupported entry type\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the user specifies a length, check its sanity */
|
/* If the user specifies a length, check its sanity */
|
||||||
if (len) {
|
if (len) {
|
||||||
if (len > finfo.size) {
|
if (len > finfo.size) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
finfo.size = len;
|
finfo.size = len;
|
||||||
@ -1420,7 +1420,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
datablock = malloc(get_unaligned_le32(&sblk->block_size));
|
datablock = malloc(get_unaligned_le32(&sblk->block_size));
|
||||||
if (!datablock) {
|
if (!datablock) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_paths;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1435,7 +1435,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
|
|
||||||
if (!data_buffer) {
|
if (!data_buffer) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_datablk;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sqfs_disk_read(start, n_blks, data_buffer);
|
ret = sqfs_disk_read(start, n_blks, data_buffer);
|
||||||
@ -1446,7 +1446,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
* image with mksquashfs's -b <block_size> option.
|
* image with mksquashfs's -b <block_size> option.
|
||||||
*/
|
*/
|
||||||
printf("Error: too many data blocks to be read.\n");
|
printf("Error: too many data blocks to be read.\n");
|
||||||
goto free_buffer;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = data_buffer + table_offset;
|
data = data_buffer + table_offset;
|
||||||
@ -1457,7 +1457,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
ret = sqfs_decompress(&ctxt, datablock, &dest_len,
|
ret = sqfs_decompress(&ctxt, datablock, &dest_len,
|
||||||
data, table_size);
|
data, table_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_buffer;
|
goto out;
|
||||||
|
|
||||||
memcpy(buf + offset + *actread, datablock, dest_len);
|
memcpy(buf + offset + *actread, datablock, dest_len);
|
||||||
*actread += dest_len;
|
*actread += dest_len;
|
||||||
@ -1471,14 +1471,12 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
data_buffer = NULL;
|
data_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(finfo.blk_sizes);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is no need to continue if the file is not fragmented.
|
* There is no need to continue if the file is not fragmented.
|
||||||
*/
|
*/
|
||||||
if (!finfo.frag) {
|
if (!finfo.frag) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto free_buffer;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = frag_entry.start / ctxt.cur_dev->blksz;
|
start = frag_entry.start / ctxt.cur_dev->blksz;
|
||||||
@ -1490,12 +1488,12 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
|
|
||||||
if (!fragment) {
|
if (!fragment) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_buffer;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sqfs_disk_read(start, n_blks, fragment);
|
ret = sqfs_disk_read(start, n_blks, fragment);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto free_fragment;
|
goto out;
|
||||||
|
|
||||||
/* File compressed and fragmented */
|
/* File compressed and fragmented */
|
||||||
if (finfo.frag && finfo.comp) {
|
if (finfo.frag && finfo.comp) {
|
||||||
@ -1503,7 +1501,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
fragment_block = malloc(dest_len);
|
fragment_block = malloc(dest_len);
|
||||||
if (!fragment_block) {
|
if (!fragment_block) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_fragment;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sqfs_decompress(&ctxt, fragment_block, &dest_len,
|
ret = sqfs_decompress(&ctxt, fragment_block, &dest_len,
|
||||||
@ -1511,7 +1509,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
frag_entry.size);
|
frag_entry.size);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
free(fragment_block);
|
free(fragment_block);
|
||||||
goto free_fragment;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = offset + *actread; j < finfo.size; j++) {
|
for (j = offset + *actread; j < finfo.size; j++) {
|
||||||
@ -1530,17 +1528,15 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_fragment:
|
out:
|
||||||
free(fragment);
|
free(fragment);
|
||||||
free_buffer:
|
if (datablk_count) {
|
||||||
if (datablk_count)
|
|
||||||
free(data_buffer);
|
free(data_buffer);
|
||||||
free_datablk:
|
|
||||||
if (datablk_count)
|
|
||||||
free(datablock);
|
free(datablock);
|
||||||
free_paths:
|
}
|
||||||
free(file);
|
free(file);
|
||||||
free(dir);
|
free(dir);
|
||||||
|
free(finfo.blk_sizes);
|
||||||
sqfs_closedir(dirsp);
|
sqfs_closedir(dirsp);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user