leak: Free list of drives and mountpoints in guestfish.
authorRichard W.M. Jones <rjones@redhat.com>
Tue, 21 Sep 2010 18:40:23 +0000 (19:40 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Tue, 21 Sep 2010 18:51:22 +0000 (19:51 +0100)
Previously the list of -a, -d, -m, -N parameters were leaked.  This
change frees them explicitly.

This is not such an important fix since guestfish is a one-shot
program, but it aids in finding other leaks in future.

(Found by valgrind).

fish/fish.c
fish/fish.h
fish/prep.c

index 9ca57be..de11b2f 100644 (file)
@@ -73,6 +73,8 @@ static void set_up_terminal (void);
 static char add_drives (struct drv *drv, char next_drive);
 static void prepare_drives (struct drv *drv);
 static void mount_mps (struct mp *mp);
+static void free_drives (struct drv *drv);
+static void free_mps (struct mp *mp);
 static int launch (void);
 static void interactive (void);
 static void shell_script (void);
@@ -485,6 +487,10 @@ main (int argc, char *argv[])
     mount_mps (mps);
   }
 
+  /* Free up data structures, no longer needed after this point. */
+  free_drives (drvs);
+  free_mps (mps);
+
   /* Remote control? */
   if (remote_control_listen && remote_control) {
     fprintf (stderr,
@@ -688,6 +694,38 @@ prepare_drives (struct drv *drv)
   }
 }
 
+static void
+free_drives (struct drv *drv)
+{
+  if (!drv) return;
+  free_drives (drv->next);
+
+  switch (drv->type) {
+  case drv_a: free (drv->a.filename); break;
+  case drv_d: free (drv->d.guest); break;
+  case drv_N:
+    free (drv->N.filename);
+    free (drv->N.device);
+    free_prep_data (drv->N.data);
+    break;
+  default: ;                    /* keep GCC happy */
+  }
+  free (drv);
+}
+
+static void
+free_mps (struct mp *mp)
+{
+  if (!mp) return;
+  free_mps (mp->next);
+
+  /* The drive and mountpoint fields are not allocated
+   * from the heap, so we should not free them here.
+   */
+
+  free (mp);
+}
+
 static int
 launch (void)
 {
index 609cbc2..f6e1aeb 100644 (file)
@@ -124,7 +124,7 @@ extern int run_more (const char *cmd, int argc, char *argv[]);
 struct prep_data {
   const struct prep *prep;
   const char *orig_type_string;
-  const char **params;
+  char **params;
 };
 typedef struct prep_data prep_data;
 extern void list_prepared_drives (void);
@@ -133,6 +133,7 @@ extern prep_data *create_prepared_file (const char *type_string,
 extern void prepare_drive (const char *filename, prep_data *data,
                            const char *device);
 extern void prep_error (prep_data *data, const char *filename, const char *fs, ...) __attribute__((noreturn, format (printf,3,4)));
+extern void free_prep_data (prep_data *data);
 
 /* in prep_lv.c */
 extern int vg_lv_parse (const char *device, char **vg, char **lv);
index 8b83071..9a6b64e 100644 (file)
@@ -116,7 +116,7 @@ Use 'guestfish -N help' to list possible values for the -N parameter.\n"),
   }
 
   for (i = 0; i < data->prep->nr_params; ++i)
-    data->params[i] = data->prep->params[i].pdefault;
+    data->params[i] = bad_cast (data->prep->params[i].pdefault);
 
   /* Parse the optional parameters. */
   const char *p = type_string + len;
@@ -167,3 +167,15 @@ prep_error (prep_data *data, const char *filename, const char *fs, ...)
 
   exit (EXIT_FAILURE);
 }
+
+void
+free_prep_data (prep_data *data)
+{
+  size_t i;
+
+  for (i = 0; i < data->prep->nr_params; ++i)
+    if (data->params[i] != data->prep->params[i].pdefault)
+      free (data->params[i]);
+  free (data->params);
+  free (data);
+}