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…
	
		Reference in New Issue