diff options
author | Rob Clark <robdclark@gmail.com> | 2017-09-12 23:40:01 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-09-15 16:03:15 +0300 |
commit | 725ffdb5cbcc4b8a9726a68cc6ae0713266ba5a9 (patch) | |
tree | 4224ac06f68e5547a64d34fbbac9e581be101ab8 /fs/fat/fat.c | |
parent | 265edc03d5a19550d92cbd6e10631d5a15bdd1d5 (diff) | |
download | u-boot-725ffdb5cbcc4b8a9726a68cc6ae0713266ba5a9.tar.xz |
fs/fat: fix fatbuf leak
A new fatbuf was allocated by get_fs_info() (called by fat_itr_root()),
but not freed, resulting in eventually running out of memory. Spotted
by running 'ls -r' in a large FAT filesystem from Shell.efi.
fatbuf is mainly used to cache FAT entry lookups (get_fatent())..
possibly once fat_write.c it can move into the iterator to simplify
this.
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ćukasz Majewski <lukma@denx.de>
Diffstat (limited to 'fs/fat/fat.c')
-rw-r--r-- | fs/fat/fat.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index f5f74c12ff..f0284398b4 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1042,6 +1042,7 @@ int fat_exists(const char *filename) return 0; ret = fat_itr_resolve(itr, filename, TYPE_ANY); + free(fsdata.fatbuf); return ret == 0; } @@ -1061,17 +1062,19 @@ int fat_size(const char *filename, loff_t *size) * Directories don't have size, but fs_size() is not * expected to fail if passed a directory path: */ + free(fsdata.fatbuf); fat_itr_root(itr, &fsdata); if (!fat_itr_resolve(itr, filename, TYPE_DIR)) { *size = 0; - return 0; + ret = 0; } - return ret; + goto out; } *size = FAT2CPU32(itr->dent->size); - - return 0; +out: + free(fsdata.fatbuf); + return ret; } int file_fat_read_at(const char *filename, loff_t pos, void *buffer, @@ -1087,10 +1090,14 @@ int file_fat_read_at(const char *filename, loff_t pos, void *buffer, ret = fat_itr_resolve(itr, filename, TYPE_FILE); if (ret) - return ret; + goto out; printf("reading %s\n", filename); - return get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread); + ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread); + +out: + free(fsdata.fatbuf); + return ret; } int file_fat_read(const char *filename, void *buffer, int maxsize) @@ -1126,7 +1133,7 @@ typedef struct { int fat_opendir(const char *filename, struct fs_dir_stream **dirsp) { - fat_dir *dir = malloc(sizeof(*dir)); + fat_dir *dir = calloc(1, sizeof(*dir)); int ret; if (!dir) @@ -1144,6 +1151,7 @@ int fat_opendir(const char *filename, struct fs_dir_stream **dirsp) return 0; fail: + free(dir->fsdata.fatbuf); free(dir); return ret; } @@ -1174,6 +1182,7 @@ int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp) void fat_closedir(struct fs_dir_stream *dirs) { fat_dir *dir = (fat_dir *)dirs; + free(dir->fsdata.fatbuf); free(dir); } |