Hi,
this diff merges NetBSD's revision 1.20 into our tree: There are
some memory leaks in resetDosDirSection.
This is not a simple merge, I have added some things:
- rootDir was not properly freed in NetBSD's commit
(actually it's put into a "free dir entry queue")
- also free memory if root directory checks fail
- I use goto's instead of rewriting the code every single time
- kept our local styles (like xperror vs perr)
- after free, set values to NULL; better safe than sorry and also
in sync with other functions
Tobias
Index: dir.c
===================================================================
RCS file: /cvs/src/sbin/fsck_msdos/dir.c,v
retrieving revision 1.23
diff -u -p -r1.23 dir.c
--- dir.c 18 Jun 2014 17:29:07 -0000 1.23
+++ dir.c 30 Jun 2014 19:19:26 -0000
@@ -219,18 +219,27 @@ resetDosDirSection(struct bootblock *boo
b1 = boot->RootDirEnts * 32;
b2 = boot->SecPerClust * boot->BytesPerSec;
- if (!(buffer = malloc(b1 > b2 ? b1 : b2))
- || !(delbuf = malloc(b2))
- || !(rootDir = newDosDirEntry())) {
+ if ((buffer = malloc(b1 > b2 ? b1 : b2)) == NULL) {
xperror("No space for directory");
return (FSFATAL);
}
+
+ if ((delbuf = malloc(b2)) == NULL) {
+ xperror("No space for directory delbuf");
+ goto fail_delbuf;
+ }
+
+ if ((rootDir = newDosDirEntry()) == NULL) {
+ xperror("No space for directory entry");
+ goto fail_root;
+ }
+
(void)memset(rootDir, 0, sizeof *rootDir);
if (boot->flags & FAT32) {
if (boot->RootCl < CLUST_FIRST || boot->RootCl >=
boot->NumClusters) {
pfatal("Root directory starts with cluster out of
range(%u)\n",
boot->RootCl);
- return (FSFATAL);
+ goto fail;
}
cl = fat[boot->RootCl].next;
if (cl < CLUST_FIRST
@@ -243,7 +252,7 @@ resetDosDirSection(struct bootblock *boo
rsrvdcltype(cl));
else {
pfatal("Root directory doesn't start a cluster
chain\n");
- return (FSFATAL);
+ goto fail;
}
if (ask(1, "Fix")) {
fat[boot->RootCl].next = CLUST_FREE;
@@ -257,6 +266,16 @@ resetDosDirSection(struct bootblock *boo
}
return (ret);
+fail:
+ freeDosDirEntry(rootDir);
+ rootDir = NULL;
+fail_root:
+ free(delbuf);
+ delbuf = NULL;
+fail_delbuf:
+ free(buffer);
+ buffer = NULL;
+ return (FSFATAL);
}
/*