Commit 725ffdb5cbcc4b8a9726a68cc6ae0713266ba5a9

Authored by Rob Clark
Committed by Tom Rini
1 parent 265edc03d5

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>

Showing 1 changed file with 16 additions and 7 deletions Side-by-side Diff

... ... @@ -1042,6 +1042,7 @@
1042 1042 return 0;
1043 1043  
1044 1044 ret = fat_itr_resolve(itr, filename, TYPE_ANY);
  1045 + free(fsdata.fatbuf);
1045 1046 return ret == 0;
1046 1047 }
1047 1048  
1048 1049  
1049 1050  
1050 1051  
... ... @@ -1061,17 +1062,19 @@
1061 1062 * Directories don't have size, but fs_size() is not
1062 1063 * expected to fail if passed a directory path:
1063 1064 */
  1065 + free(fsdata.fatbuf);
1064 1066 fat_itr_root(itr, &fsdata);
1065 1067 if (!fat_itr_resolve(itr, filename, TYPE_DIR)) {
1066 1068 *size = 0;
1067   - return 0;
  1069 + ret = 0;
1068 1070 }
1069   - return ret;
  1071 + goto out;
1070 1072 }
1071 1073  
1072 1074 *size = FAT2CPU32(itr->dent->size);
1073   -
1074   - return 0;
  1075 +out:
  1076 + free(fsdata.fatbuf);
  1077 + return ret;
1075 1078 }
1076 1079  
1077 1080 int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
1078 1081  
... ... @@ -1087,10 +1090,14 @@
1087 1090  
1088 1091 ret = fat_itr_resolve(itr, filename, TYPE_FILE);
1089 1092 if (ret)
1090   - return ret;
  1093 + goto out;
1091 1094  
1092 1095 printf("reading %s\n", filename);
1093   - return get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
  1096 + ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
  1097 +
  1098 +out:
  1099 + free(fsdata.fatbuf);
  1100 + return ret;
1094 1101 }
1095 1102  
1096 1103 int file_fat_read(const char *filename, void *buffer, int maxsize)
... ... @@ -1126,7 +1133,7 @@
1126 1133  
1127 1134 int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
1128 1135 {
1129   - fat_dir *dir = malloc(sizeof(*dir));
  1136 + fat_dir *dir = calloc(1, sizeof(*dir));
1130 1137 int ret;
1131 1138  
1132 1139 if (!dir)
... ... @@ -1144,6 +1151,7 @@
1144 1151 return 0;
1145 1152  
1146 1153 fail:
  1154 + free(dir->fsdata.fatbuf);
1147 1155 free(dir);
1148 1156 return ret;
1149 1157 }
... ... @@ -1174,6 +1182,7 @@
1174 1182 void fat_closedir(struct fs_dir_stream *dirs)
1175 1183 {
1176 1184 fat_dir *dir = (fat_dir *)dirs;
  1185 + free(dir->fsdata.fatbuf);
1177 1186 free(dir);
1178 1187 }
1179 1188