fs/fat: Check malloc return values and fix memory leaks

Check malloc() return values and properly unwind on errors so
memory allocated for fat_itr structures get freed properly.

Also fixes a leak of fsdata.fatbuf in fat_size().

Fixes: 2460098cffacd1 ("fs/fat: Reduce stack usage")
Reported-by: Coverity (CID: 167225, 167233, 167234)
Signed-off-by: Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
Reviewed-by: Tom Rini <trini@konsulko.com>
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 35941c1..7fe7843 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1039,12 +1039,15 @@
 	int ret;
 
 	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr)
+		return 0;
 	ret = fat_itr_root(itr, &fsdata);
 	if (ret)
-		return 0;
+		goto out;
 
 	ret = fat_itr_resolve(itr, filename, TYPE_ANY);
 	free(fsdata.fatbuf);
+out:
 	free(itr);
 	return ret == 0;
 }
@@ -1056,9 +1059,11 @@
 	int ret;
 
 	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr)
+		return -ENOMEM;
 	ret = fat_itr_root(itr, &fsdata);
 	if (ret)
-		return ret;
+		goto out_free_itr;
 
 	ret = fat_itr_resolve(itr, filename, TYPE_FILE);
 	if (ret) {
@@ -1072,12 +1077,13 @@
 			*size = 0;
 			ret = 0;
 		}
-		goto out;
+		goto out_free_both;
 	}
 
 	*size = FAT2CPU32(itr->dent->size);
+out_free_both:
 	free(fsdata.fatbuf);
-out:
+out_free_itr:
 	free(itr);
 	return ret;
 }
@@ -1090,19 +1096,22 @@
 	int ret;
 
 	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr)
+		return -ENOMEM;
 	ret = fat_itr_root(itr, &fsdata);
 	if (ret)
-		return ret;
+		goto out_free_itr;
 
 	ret = fat_itr_resolve(itr, filename, TYPE_FILE);
 	if (ret)
-		goto out;
+		goto out_free_both;
 
 	printf("reading %s\n", filename);
 	ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
 
-out:
+out_free_both:
 	free(fsdata.fatbuf);
+out_free_itr:
 	free(itr);
 	return ret;
 }
@@ -1148,17 +1157,18 @@
 
 	ret = fat_itr_root(&dir->itr, &dir->fsdata);
 	if (ret)
-		goto fail;
+		goto fail_free_dir;
 
 	ret = fat_itr_resolve(&dir->itr, filename, TYPE_DIR);
 	if (ret)
-		goto fail;
+		goto fail_free_both;
 
 	*dirsp = (struct fs_dir_stream *)dir;
 	return 0;
 
-fail:
+fail_free_both:
 	free(dir->fsdata.fatbuf);
+fail_free_dir:
 	free(dir);
 	return ret;
 }