Re: fsck_msdos: memleak merge with NetBSD

2014-07-08 Thread Ted Unangst
On Mon, Jun 30, 2014 at 21:26, Tobias Stoeckmann wrote:
 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

 +fail:
 + freeDosDirEntry(rootDir);
 + rootDir = NULL;
 +fail_root:
 + free(delbuf);
 + delbuf = NULL;
 +fail_delbuf:
 + free(buffer);
 + buffer = NULL;
 + return (FSFATAL);

I think it's safe to just have one goto label? free(NULL) is fine. a
small preference, but it seems less error prone when there's one cleanup
section that does what's necessary, as opposed to the jumping code
needing to determine where to jump each time.



Re: fsck_msdos: memleak merge with NetBSD

2014-07-08 Thread Tobias Stoeckmann
On Tue, Jul 08, 2014 at 03:01:58PM -0400, Ted Unangst wrote:
 I think it's safe to just have one goto label? free(NULL) is fine.

That's true.  If we go into that direction, we can also use the cleanup
function that would be done at the end of directory processing.

Also put two variables static that are not used anywhere else, easier
to verify that there are no side-effects.

This version looks definitely simpler.


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 -  1.23
+++ dir.c   8 Jul 2014 19:29:54 -
@@ -147,7 +147,7 @@ freeDirTodo(struct dirTodoNode *dt)
 /*
  * The stack of unread directories
  */
-struct dirTodoNode *pendingDirectories = NULL;
+static struct dirTodoNode *pendingDirectories = NULL;
 
 /*
  * Return the full pathname for a directory entry.
@@ -203,7 +203,7 @@ static char longName[DOSLONGNAMELEN] = 
 static u_char *buffer = NULL;
 static u_char *delbuf = NULL;
 
-struct dosDirEntry *rootDir;
+static struct dosDirEntry *rootDir;
 static struct dosDirEntry *lostDir;
 
 /*
@@ -223,14 +223,14 @@ resetDosDirSection(struct bootblock *boo
|| !(delbuf = malloc(b2))
|| !(rootDir = newDosDirEntry())) {
xperror(No space for directory);
-   return (FSFATAL);
+   goto fail;
}
(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 +243,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 +257,9 @@ resetDosDirSection(struct bootblock *boo
}
 
return (ret);
+fail:
+   finishDosDirSection();
+   return (FSFATAL);
 }
 
 /*
Index: ext.h
===
RCS file: /cvs/src/sbin/fsck_msdos/ext.h,v
retrieving revision 1.11
diff -u -p -r1.11 ext.h
--- ext.h   16 Jun 2014 18:33:33 -  1.11
+++ ext.h   8 Jul 2014 19:29:54 -
@@ -46,8 +46,6 @@ extern int rdonly;/* device is opened r
 
 extern struct disklabel lab;
 
-extern struct dosDirEntry *rootDir;
-
 /*
  * function declarations
  */



fsck_msdos: memleak merge with NetBSD

2014-06-30 Thread Tobias Stoeckmann
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 -  1.23
+++ dir.c   30 Jun 2014 19:19:26 -
@@ -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);
 }
 
 /*