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>
This commit is contained in:
parent
265edc03d5
commit
725ffdb5cb
23
fs/fat/fat.c
23
fs/fat/fat.c
|
|
@ -1042,6 +1042,7 @@ int fat_exists(const char *filename)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = fat_itr_resolve(itr, filename, TYPE_ANY);
|
ret = fat_itr_resolve(itr, filename, TYPE_ANY);
|
||||||
|
free(fsdata.fatbuf);
|
||||||
return ret == 0;
|
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
|
* Directories don't have size, but fs_size() is not
|
||||||
* expected to fail if passed a directory path:
|
* expected to fail if passed a directory path:
|
||||||
*/
|
*/
|
||||||
|
free(fsdata.fatbuf);
|
||||||
fat_itr_root(itr, &fsdata);
|
fat_itr_root(itr, &fsdata);
|
||||||
if (!fat_itr_resolve(itr, filename, TYPE_DIR)) {
|
if (!fat_itr_resolve(itr, filename, TYPE_DIR)) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
return 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = FAT2CPU32(itr->dent->size);
|
*size = FAT2CPU32(itr->dent->size);
|
||||||
|
out:
|
||||||
return 0;
|
free(fsdata.fatbuf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
|
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);
|
ret = fat_itr_resolve(itr, filename, TYPE_FILE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
printf("reading %s\n", filename);
|
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)
|
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)
|
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;
|
int ret;
|
||||||
|
|
||||||
if (!dir)
|
if (!dir)
|
||||||
|
|
@ -1144,6 +1151,7 @@ int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
free(dir->fsdata.fatbuf);
|
||||||
free(dir);
|
free(dir);
|
||||||
return ret;
|
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)
|
void fat_closedir(struct fs_dir_stream *dirs)
|
||||||
{
|
{
|
||||||
fat_dir *dir = (fat_dir *)dirs;
|
fat_dir *dir = (fat_dir *)dirs;
|
||||||
|
free(dir->fsdata.fatbuf);
|
||||||
free(dir);
|
free(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue