On 2025/9/10 13:14 Gao Xiang wrote: > On 2025/9/10 13:05, Yuezhang Mo wrote: >> This patch addresses 4 memory leaks and 1 allocation issue to >> ensure proper cleanup and allocation: >> >> 1. Fixed memory leak by freeing sbi->zmgr in z_erofs_compress_exit(). >> 2. Fixed memory leak by freeing inode->chunkindexes in erofs_iput(). >> 3. Fixed incorrect allocation of chunk index array in >> erofs_rebuild_write_blob_index() to ensure correct array allocation >> and avoid out-of-bounds access. >> 4. Fixed memory leak of struct erofs_blobchunk not being freed by >> calling erofs_blob_exit() in rebuild mode. >> 5. Fixed memory leak caused by repeated initialization of the first >> blob device's sbi by checking whether sbi has been initialized. >> >> Signed-off-by: Yuezhang Mo <yuezhang...@sony.com> >> Reviewed-by: Friendy Su <friendy...@sony.com> >> Reviewed-by: Daniel Palmer <daniel.pal...@sony.com> >> --- >> lib/compress.c | 2 ++ >> lib/inode.c | 3 +++ >> lib/rebuild.c | 13 ++++++++----- >> mkfs/main.c | 2 +- >> 4 files changed, 14 insertions(+), 6 deletions(-) >> >> diff --git a/lib/compress.c b/lib/compress.c >> index 622a205..dd537ec 100644 >> --- a/lib/compress.c >> +++ b/lib/compress.c >> @@ -2171,5 +2171,7 @@ int z_erofs_compress_exit(struct erofs_sb_info *sbi) >> } >> #endif >> } >> + >> + free(sbi->zmgr); >> return 0; >> } >> diff --git a/lib/inode.c b/lib/inode.c >> index 7ee6b3d..38e2bb2 100644 >> --- a/lib/inode.c >> +++ b/lib/inode.c >> @@ -159,6 +159,9 @@ unsigned int erofs_iput(struct erofs_inode *inode) >> } else { >> free(inode->i_link); >> } >> + >> + if (inode->datalayout == EROFS_INODE_CHUNK_BASED) >> + free(inode->chunkindexes); >> free(inode); >> return 0; >> } >> diff --git a/lib/rebuild.c b/lib/rebuild.c >> index 0358567..461e18e 100644 >> --- a/lib/rebuild.c >> +++ b/lib/rebuild.c >> @@ -186,7 +186,7 @@ static int erofs_rebuild_write_blob_index(struct >> erofs_sb_info *dst_sb, >> >> unit = sizeof(struct erofs_inode_chunk_index); >> inode->extent_isize = count * unit; >> - idx = malloc(max(sizeof(*idx), sizeof(void *))); >> + idx = calloc(count, max(sizeof(*idx), sizeof(void *))); >> if (!idx) >> return -ENOMEM; >> inode->chunkindexes = idx; >> @@ -428,10 +428,13 @@ int erofs_rebuild_load_tree(struct erofs_inode *root, >> struct erofs_sb_info *sbi, >> erofs_uuid_unparse_lower(sbi->uuid, uuid_str); >> fsid = uuid_str; >> } >> - ret = erofs_read_superblock(sbi); >> - if (ret) { >> - erofs_err("failed to read superblock of %s", fsid); >> - return ret; >> + >> + if (!sbi->devs) { > > `sbi->devs` may be NULL if ondisk_extradevs == 0? (see > erofs_init_devices()). > > I think we could just introduce a new `sbi->sb_valid` > boolean, and set up this in erofs_read_superblock() > instead in the short term.
For rebuild mode, ondisk_extradevs is not 0, `sbi->devs` is always set. Is there a case where erofs_read_superblock() is called multiple times if not in rebuild mode? Or will there be such a case in the future? > > Thanks, > Gao Xiang > >> + ret = erofs_read_superblock(sbi); >> + if (ret) { >> + erofs_err("failed to read superblock of %s", fsid); >> + return ret; >> + } >> } >> >> inode.nid = sbi->root_nid; >> diff --git a/mkfs/main.c b/mkfs/main.c >> index 28588db..3dd5815 100644 >> --- a/mkfs/main.c >> +++ b/mkfs/main.c >> @@ -1908,7 +1908,7 @@ exit: >> erofs_dev_close(&g_sbi); >> erofs_cleanup_compress_hints(); >> erofs_cleanup_exclude_rules(); >> - if (cfg.c_chunkbits) >> + if (cfg.c_chunkbits || source_mode == EROFS_MKFS_SOURCE_REBUILD) >> erofs_blob_exit(); >> erofs_xattr_cleanup_name_prefixes(); >> erofs_rebuild_cleanup();