[PATCH v2] erofs-utils: fix a memory leak of multiple devices

Yue Hu zbestahu at gmail.com
Fri Jul 22 15:36:10 AEST 2022


The memory allocated for multiple devices should be freed after use.
Let's add a helper to fix it since there is more than one to use it.

Signed-off-by: Yue Hu <huyue2 at coolpad.com>
---
 dump/main.c              |  4 +++-
 fsck/main.c              |  4 +++-
 fuse/main.c              |  2 ++
 include/erofs/internal.h |  1 +
 lib/super.c              | 12 +++++++++++-
 5 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/dump/main.c b/dump/main.c
index 40e850a..f2a09b6 100644
--- a/dump/main.c
+++ b/dump/main.c
@@ -630,12 +630,14 @@ int main(int argc, char **argv)
 
 	if (dumpcfg.show_extent && !dumpcfg.show_inode) {
 		usage();
-		goto exit_dev_close;
+		goto exit_put_super;
 	}
 
 	if (dumpcfg.show_inode)
 		erofsdump_show_fileinfo(dumpcfg.show_extent);
 
+exit_put_super:
+	erofs_put_super();
 exit_dev_close:
 	dev_close();
 exit:
diff --git a/fsck/main.c b/fsck/main.c
index 5a2f659..8ed3fc5 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -818,7 +818,7 @@ int main(int argc, char **argv)
 
 	if (erofs_sb_has_sb_chksum() && erofs_check_sb_chksum()) {
 		erofs_err("failed to verify superblock checksum");
-		goto exit_dev_close;
+		goto exit_put_super;
 	}
 
 	err = erofsfsck_check_inode(sbi.root_nid, sbi.root_nid);
@@ -843,6 +843,8 @@ int main(int argc, char **argv)
 		}
 	}
 
+exit_put_super:
+	erofs_put_super();
 exit_dev_close:
 	dev_close();
 exit:
diff --git a/fuse/main.c b/fuse/main.c
index 95f939e..3e55bb8 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -299,6 +299,8 @@ int main(int argc, char *argv[])
 	}
 
 	ret = fuse_main(args.argc, args.argv, &erofs_ops, NULL);
+
+	erofs_put_super();
 err_dev_close:
 	blob_closeall();
 	dev_close();
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 6a70f11..48498fe 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -318,6 +318,7 @@ struct erofs_map_dev {
 
 /* super.c */
 int erofs_read_superblock(void);
+void erofs_put_super(void);
 
 /* namei.c */
 int erofs_read_inode_from_disk(struct erofs_inode *vi);
diff --git a/lib/super.c b/lib/super.c
index f486eb7..b267412 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -46,14 +46,18 @@ static int erofs_init_devices(struct erofs_sb_info *sbi,
 
 	sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
 	sbi->devs = calloc(ondisk_extradevs, sizeof(*sbi->devs));
+	if (!sbi->devs)
+		return -ENOMEM;
 	pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
 	for (i = 0; i < ondisk_extradevs; ++i) {
 		struct erofs_deviceslot dis;
 		int ret;
 
 		ret = dev_read(0, &dis, pos, sizeof(dis));
-		if (ret < 0)
+		if (ret < 0) {
+			free(sbi->devs);
 			return ret;
+		}
 
 		sbi->devs[i].mapped_blkaddr = dis.mapped_blkaddr;
 		sbi->total_blocks += dis.blocks;
@@ -109,3 +113,9 @@ int erofs_read_superblock(void)
 	memcpy(&sbi.uuid, dsb->uuid, sizeof(dsb->uuid));
 	return erofs_init_devices(&sbi, dsb);
 }
+
+void erofs_put_super(void)
+{
+	if (sbi.devs)
+		free(sbi.devs);
+}
-- 
2.17.1



More information about the Linux-erofs mailing list