Fix numerous memory leaks.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 12 Jan 2019 21:03:46 +0000 (13:03 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 13 Jan 2019 00:59:35 +0000 (16:59 -0800)
16 files changed:
src/language/data-io/dataset.c
src/language/dictionary/sys-file-info.c
src/language/stats/crosstabs.q
src/language/stats/factor.c
src/language/stats/oneway.c
src/language/stats/rank.c
src/language/utilities/output.c
src/math/categoricals.c
src/output/ascii.c
src/output/charts/boxplot.c
src/output/odt.c
src/output/pivot-output.c
src/output/pivot-table.c
src/output/pivot-table.h
tests/libpspp/line-reader-test.c
tests/output/render-test.c

index cf25f74799f3031e68dc34b95c41c1ae084ef9b8..d0d4f0a8d371af818c884c2109209174cf9b44b0 100644 (file)
@@ -273,6 +273,8 @@ cmd_dataset_display (struct lexer *lexer UNUSED, struct dataset *ds)
                         pivot_value_new_user_text_nocopy (text));
     }
 
+  free (datasets);
+
   pivot_table_submit (table);
 
   return CMD_SUCCESS;
index 9cb551044914098e389c044e0d48e8098a856365..80fa903b066ca704f05d5e1572c2b42270707760 100644 (file)
@@ -249,6 +249,7 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds UNUSED)
   display_value_labels (vars, n_vars);
   display_attributes (dict_get_attributes (dataset_dict (ds)),
                       vars, n_vars, DF_ATTRIBUTES);
+  free (vars);
 
   dict_unref (d);
 
index dfafbe9f3eba199717d66ce2e8ce8a736d1bd6f3..0665b75e6f74bf1cc3d9355ff3477ff6546b5532 100644 (file)
@@ -394,12 +394,8 @@ exit:
   for (xt = &proc.pivots[0]; xt < &proc.pivots[proc.n_pivots]; xt++)
     {
       free (xt->vars);
-      /* We must not call value_destroy on const_values because
-         it is a wild pointer; it never pointed to anything owned
-         by the crosstabulation.
-
-         The rest of the data was allocated and destroyed at a
-         lower level already. */
+      free (xt->const_vars);
+      free (xt->const_indexes);
     }
   free (proc.pivots);
 
@@ -475,6 +471,7 @@ crs_custom_tables (struct lexer *lexer, struct dataset *ds,
       xt->vars = xcalloc (n_by, sizeof *xt->vars);
       xt->n_consts = 0;
       xt->const_vars = NULL;
+      xt->const_indexes = NULL;
 
       for (j = 0; j < n_by; j++)
         xt->vars[j].var = by[j][by_iter[j]];
@@ -780,6 +777,7 @@ postcalc (struct crosstabs_proc *proc)
               struct crosstabulation subset;
               make_crosstabulation_subset (xt, row0, row1, &subset);
               output_crosstabulation (proc, &subset);
+              free (subset.const_indexes);
             }
         }
       if (proc->barchart)
@@ -1015,7 +1013,8 @@ output_crosstabulation (struct crosstabs_proc *proc, struct crosstabulation *xt)
            ds_cstr (&vars));
 
       ds_destroy (&vars);
-      free_var_values (xt, COL_VAR);
+      for (size_t i = 0; i < xt->n_vars; i++)
+        free_var_values (xt, i);
       return;
     }
 
@@ -1081,6 +1080,7 @@ output_crosstabulation (struct crosstabs_proc *proc, struct crosstabulation *xt)
       free (x.mat);
       free (x.row_tot);
       free (x.col_tot);
+      free (x.const_indexes);
     }
 
   if (table)
@@ -1504,12 +1504,8 @@ compare_value_3way_inv (const void *a_, const void *b_, const void *width_)
 
 /* Given an array of ENTRY_CNT table_entry structures starting at
    ENTRIES, creates a sorted list of the values that the variable
-   with index VAR_IDX takes on.  The values are returned as a
-   malloc()'d array stored in *VALUES, with the number of values
-   stored in *VALUE_CNT.
-
-   The caller must eventually free *VALUES, but each pointer in *VALUES points
-   to existing data not owned by *VALUES itself. */
+   with index VAR_IDX takes on.  Stores the array of the values in
+   XT->values and the number of values in XT->n_values. */
 static void
 enum_var_values (const struct crosstabulation *xt, int var_idx,
                  bool descending)
@@ -1564,7 +1560,7 @@ static void
 free_var_values (const struct crosstabulation *xt, int var_idx)
 {
   struct xtab_var *xv = &xt->vars[var_idx];
-  //free (xv->values);
+  free (xv->values);
   xv->values = NULL;
   xv->n_values = 0;
 }
@@ -1689,6 +1685,8 @@ display_crosstabulation (struct crosstabs_proc *proc,
             }
         }
     }
+
+  free (indexes);
 }
 
 static void calc_r (struct crosstabulation *,
@@ -1787,6 +1785,8 @@ display_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt,
   struct pivot_value *total = pivot_value_new_number (xt->total);
   pivot_value_set_rc (sym, total, PIVOT_RC_COUNT);
   pivot_table_put (sym, indexes, sym->n_dimensions, total);
+
+  free (indexes);
 }
 
 static bool calc_risk (struct crosstabulation *,
@@ -1894,6 +1894,8 @@ display_directional (struct crosstabs_proc *proc,
                              pivot_value_new_number (entries[j]));
           }
     }
+
+  free (indexes);
 }
 \f
 /* Statistical calculations. */
index 797c5a67255eb920df2fb107bce3b8c003111aba..18341b8db50d470e2c4ac5d3c2128ec63f512921 100644 (file)
@@ -1533,6 +1533,10 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
        {
          do_factor_by_matrix (&factor, id);
 
+          gsl_matrix_free (id->ai_cov);
+          id->ai_cov = NULL;
+          gsl_matrix_free (id->ai_cor);
+          id->ai_cor = NULL;
          gsl_matrix_free (id->mm.corr);
          id->mm.corr = NULL;
          gsl_matrix_free (id->mm.cov);
index ef20cbafbf1135810df8bf1bfdd0d5dbe714aa46..7f28b75b8a45098de84fb736d452642e0ffdde59 100644 (file)
@@ -551,7 +551,10 @@ cmd_oneway (struct lexer *lexer, struct dataset *ds)
            }
 
          if ( ll_count (coefficient_list) <= 0)
-           goto error;
+            {
+              destroy_coeff_list (cl);
+              goto error;
+            }
 
          ll_push_tail (&oneway.contrast_list, &cl->ll);
        }
index cd3833dbba7a78583ad0aa5016754c8990ad863c..4b6a2034aa5e6edcc81feb382cc41119cf4b14ed 100644 (file)
@@ -865,6 +865,7 @@ cmd_rank (struct lexer *lexer, struct dataset *ds)
                     pivot_table_put2 (table, j, row_idx,
                                       pivot_value_new_user_text (entry, -1));
                 }
+              ds_destroy (&group_vars);
            }
        }
 
index a699fdf5f5e4ef9968f14bdb24c4bf180bd4ada9..567314eb6c7fe278610d8335d31cf8c698019cc3 100644 (file)
@@ -135,6 +135,7 @@ cmd_output (struct lexer *lexer, struct dataset *ds UNUSED)
        }
     }
 
+  string_set_destroy (&rc_names);
   return CMD_SUCCESS;
 
  error:
index 30c4c567ce607bc1baaeaceeab599c86ba2fd1f5..3f9dc0097539eb5b72137866bab815e70e5d99f1 100644 (file)
@@ -276,6 +276,7 @@ categoricals_destroy (struct categoricals *cat)
       free (cat->iap[i].enc_sum);
       hmap_destroy (&cat->iap[i].ivmap);
     }
+  free (cat->iap);
 
   /* Interate over each variable and delete its value map.
 
index 4bad73aeceef5d32f70051ed89431d165eb1898c..2193f35224ee19ec0f4fca870797019b29a7a6f8 100644 (file)
@@ -450,16 +450,21 @@ ascii_output_table_item (struct ascii_driver *a,
 }
 
 static void
-ascii_output_text (struct ascii_driver *a, const char *text)
+ascii_output_table_item_unref (struct ascii_driver *a,
+                               struct table_item *table_item)
 {
-  struct table_item *table_item;
-
-  table_item = table_item_create (table_from_string (TABLE_HALIGN_LEFT, text),
-                                  NULL, NULL);
   ascii_output_table_item (a, table_item);
   table_item_unref (table_item);
 }
 
+static void
+ascii_output_text (struct ascii_driver *a, const char *text)
+{
+  ascii_output_table_item_unref (
+    a, table_item_create (table_from_string (TABLE_HALIGN_LEFT, text),
+                          NULL, NULL));
+}
+
 static void
 ascii_submit (struct output_driver *driver,
               const struct output_item *output_item)
@@ -509,7 +514,8 @@ ascii_submit (struct output_driver *driver,
           break;
 
         default:
-          ascii_output_table_item (a, text_item_to_table_item (text_item_ref (text_item)));
+          ascii_output_table_item_unref (
+            a, text_item_to_table_item (text_item_ref (text_item)));
           break;
         }
     }
index 0a933195d04e59adbab217c5e52ed6743d41d0e0..0abb971f44a28909cf7939c3b78b2dc57ede2937 100644 (file)
@@ -41,7 +41,11 @@ boxplot_add_box (struct boxplot *boxplot,
                  struct box_whisker *bw, const char *label)
 {
   if (boxplot == NULL)
-    return;
+    {
+      struct statistic *statistic = &bw->parent.parent;
+      statistic->destroy (statistic);
+      return;
+    }
 
   struct boxplot_box *box;
   if (boxplot->n_boxes >= boxplot->boxes_allocated)
index 56b26bb1ac6db335c8227d651e8bb7b7087b2e43..90a76186a7d81f7cdedd7f8510388aa30a0306ae 100644 (file)
@@ -56,6 +56,7 @@ struct odt_driver
   struct output_driver driver;
 
   struct zip_writer *zip;     /* ZIP file writer. */
+  struct file_handle *handle; /* Handle for 'file_name'. */
   char *file_name;            /* Output file name. */
 
   /* content.xml */
@@ -302,6 +303,7 @@ odt_create (struct file_handle *fh, enum settings_output_devices device_type,
   output_driver_init (d, &odt_driver_class, file_name, device_type);
 
   odt->zip = zip;
+  odt->handle = fh;
   odt->file_name = xstrdup (file_name);
 
   if (!create_mimetype (zip))
@@ -379,6 +381,7 @@ odt_destroy (struct output_driver *driver)
       zip_writer_close (odt->zip);
     }
 
+  fh_unref (odt->handle);
   free (odt->file_name);
   free (odt);
 }
index d6925ceb83030a4f30f6ff3f8206f2d1cbc13daa..44d5f885b851c9affe1460cec668d9260fa0ad2e 100644 (file)
@@ -349,15 +349,19 @@ pivot_table_submit_layer (const struct pivot_table *st,
 
   struct footnote **footnotes = xcalloc (st->n_footnotes, sizeof *footnotes);
   for (size_t i = 0; i < st->n_footnotes; i++)
-    footnotes[i] = tab_create_footnote (
-      table, i,
-      pivot_value_to_string (st->footnotes[i]->content,
-                             st->show_values, st->show_variables),
-      pivot_value_to_string (st->footnotes[i]->marker,
-                             st->show_values, st->show_variables),
-      area_style_override (table->container, &st->areas[PIVOT_AREA_FOOTER],
-                           st->footnotes[i]->content->cell_style,
-                           st->footnotes[i]->content->font_style));
+    {
+      char *content = pivot_value_to_string (
+        st->footnotes[i]->content, st->show_values, st->show_variables);
+      char *marker = pivot_value_to_string (
+        st->footnotes[i]->marker, st->show_values, st->show_variables);
+      footnotes[i] = tab_create_footnote (
+        table, i, content, marker,
+        area_style_override (table->container, &st->areas[PIVOT_AREA_FOOTER],
+                             st->footnotes[i]->content->cell_style,
+                             st->footnotes[i]->content->font_style));
+      free (marker);
+      free (content);
+    }
 
   compose_headings (table,
                     &st->axes[PIVOT_AXIS_COLUMN], H, &st->axes[PIVOT_AXIS_ROW],
@@ -479,11 +483,12 @@ pivot_table_submit_layer (const struct pivot_table *st,
       table_item_text_destroy (caption);
     }
 
+  free (footnotes);
   table_item_submit (ti);
 }
 
 void
-pivot_table_submit (const struct pivot_table *st)
+pivot_table_submit (struct pivot_table *st)
 {
   pivot_table_assign_label_depth (CONST_CAST (struct pivot_table *, st));
 
@@ -506,4 +511,6 @@ pivot_table_submit (const struct pivot_table *st)
     pivot_table_submit_layer (st, st->current_layer);
 
   settings_set_decimal_char (old_decimal);
+
+  pivot_table_destroy (st);
 }
index 674fe2cdf5c6b80babb44bd7619fb866eb1420ff..41337cde73eccecfef006de01a2a92f3bedf53b0 100644 (file)
@@ -293,6 +293,7 @@ pivot_dimension_destroy (struct pivot_dimension *d)
   pivot_category_destroy (d->root);
   free (d->data_leaves);
   free (d->presentation_leaves);
+  free (d);
 }
 
 /* Returns the first leaf node in an in-order traversal that is a child of
@@ -505,6 +506,7 @@ pivot_category_destroy (struct pivot_category *c)
   pivot_value_destroy (c->name);
   for (size_t i = 0; i < c->n_subs; i++)
     pivot_category_destroy (c->subs[i]);
+  free (c->subs);
   free (c);
 }
 \f
@@ -1800,7 +1802,8 @@ pivot_value_destroy (struct pivot_value *value)
           free (value->numeric.value_label);
           break;
 
-        case SETTINGS_VALUE_SHOW_VALUE:
+        case PIVOT_VALUE_STRING:
+          free (value->string.s);
           free (value->string.var_name);
           free (value->string.value_label);
           break;
index 474b3acde250b916e0a0c559cb04d952cbb2efa2..6104cb13133b04a0de008c9a99756e84e7e90d4a 100644 (file)
@@ -453,7 +453,7 @@ void pivot_table_set_weight_format (struct pivot_table *,
 bool pivot_table_is_empty (const struct pivot_table *);
 
 /* Output. */
-void pivot_table_submit (const struct pivot_table *);
+void pivot_table_submit (struct pivot_table *);
 
 /* Data cells. */
 void pivot_table_put (struct pivot_table *, const size_t *dindexes, size_t n,
index fef9eb639013764ef4ac2eab1f0bcb3c4c7c10ad..c43cfb989a0cb8fb50fb792fc63ac57193440c74 100644 (file)
@@ -53,7 +53,6 @@ cmd_read (int argc, char *argv[])
   struct line_reader *r;
   const char *filename;
   struct string line;
-  char *encoding;
 
   if (argc != 4)
     error (1, 0, "bad syntax for `%s' command; use `%s help' for help",
@@ -67,7 +66,7 @@ cmd_read (int argc, char *argv[])
   if (r == NULL)
     error (1, errno, "line_reader_open failed");
 
-  encoding = xstrdup (line_reader_get_encoding (r));
+  char *encoding = xstrdup (line_reader_get_encoding (r));
   printf ("encoded in %s", encoding);
   if (line_reader_is_auto (r))
     printf (" (auto)");
@@ -98,6 +97,7 @@ cmd_read (int argc, char *argv[])
 
       ds_clear (&line);
     }
+  free (encoding);
 
   if (!strcmp(filename, "-"))
     line_reader_free (r);
index e5eea91d94fefd0b2f9ae921e87699bf3b5eb5bf..421b9be0663dd6a2abc8793fba4e2e995e239a99 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "data/file-handle-def.h"
 #include "libpspp/assertion.h"
 #include "libpspp/compiler.h"
 #include "libpspp/string-map.h"
@@ -126,6 +127,7 @@ main (int argc, char **argv)
     fclose (input);
 
   output_engine_pop ();
+  fh_done ();
 
   return 0;
 }