From 1aef11b9589a534333bbecd528efe1022a4bb9bb Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 12 Jan 2019 13:03:46 -0800 Subject: [PATCH] Fix numerous memory leaks. --- src/language/data-io/dataset.c | 2 ++ src/language/dictionary/sys-file-info.c | 1 + src/language/stats/crosstabs.q | 30 +++++++++++++------------ src/language/stats/factor.c | 4 ++++ src/language/stats/oneway.c | 5 ++++- src/language/stats/rank.c | 1 + src/language/utilities/output.c | 1 + src/math/categoricals.c | 1 + src/output/ascii.c | 18 ++++++++++----- src/output/charts/boxplot.c | 6 ++++- src/output/odt.c | 3 +++ src/output/pivot-output.c | 27 +++++++++++++--------- src/output/pivot-table.c | 5 ++++- src/output/pivot-table.h | 2 +- tests/libpspp/line-reader-test.c | 4 ++-- tests/output/render-test.c | 2 ++ 16 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/language/data-io/dataset.c b/src/language/data-io/dataset.c index cf25f74799..d0d4f0a8d3 100644 --- a/src/language/data-io/dataset.c +++ b/src/language/data-io/dataset.c @@ -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; diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 9cb5510449..80fa903b06 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -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); diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index dfafbe9f3e..0665b75e6f 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -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); } /* Statistical calculations. */ diff --git a/src/language/stats/factor.c b/src/language/stats/factor.c index 797c5a6725..18341b8db5 100644 --- a/src/language/stats/factor.c +++ b/src/language/stats/factor.c @@ -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); diff --git a/src/language/stats/oneway.c b/src/language/stats/oneway.c index ef20cbafbf..7f28b75b8a 100644 --- a/src/language/stats/oneway.c +++ b/src/language/stats/oneway.c @@ -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); } diff --git a/src/language/stats/rank.c b/src/language/stats/rank.c index cd3833dbba..4b6a2034aa 100644 --- a/src/language/stats/rank.c +++ b/src/language/stats/rank.c @@ -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); } } diff --git a/src/language/utilities/output.c b/src/language/utilities/output.c index a699fdf5f5..567314eb6c 100644 --- a/src/language/utilities/output.c +++ b/src/language/utilities/output.c @@ -135,6 +135,7 @@ cmd_output (struct lexer *lexer, struct dataset *ds UNUSED) } } + string_set_destroy (&rc_names); return CMD_SUCCESS; error: diff --git a/src/math/categoricals.c b/src/math/categoricals.c index 30c4c567ce..3f9dc00975 100644 --- a/src/math/categoricals.c +++ b/src/math/categoricals.c @@ -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. diff --git a/src/output/ascii.c b/src/output/ascii.c index 4bad73aece..2193f35224 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -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; } } diff --git a/src/output/charts/boxplot.c b/src/output/charts/boxplot.c index 0a933195d0..0abb971f44 100644 --- a/src/output/charts/boxplot.c +++ b/src/output/charts/boxplot.c @@ -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) diff --git a/src/output/odt.c b/src/output/odt.c index 56b26bb1ac..90a76186a7 100644 --- a/src/output/odt.c +++ b/src/output/odt.c @@ -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); } diff --git a/src/output/pivot-output.c b/src/output/pivot-output.c index d6925ceb83..44d5f885b8 100644 --- a/src/output/pivot-output.c +++ b/src/output/pivot-output.c @@ -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); } diff --git a/src/output/pivot-table.c b/src/output/pivot-table.c index 674fe2cdf5..41337cde73 100644 --- a/src/output/pivot-table.c +++ b/src/output/pivot-table.c @@ -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); } @@ -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; diff --git a/src/output/pivot-table.h b/src/output/pivot-table.h index 474b3acde2..6104cb1313 100644 --- a/src/output/pivot-table.h +++ b/src/output/pivot-table.h @@ -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, diff --git a/tests/libpspp/line-reader-test.c b/tests/libpspp/line-reader-test.c index fef9eb6390..c43cfb989a 100644 --- a/tests/libpspp/line-reader-test.c +++ b/tests/libpspp/line-reader-test.c @@ -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); diff --git a/tests/output/render-test.c b/tests/output/render-test.c index e5eea91d94..421b9be066 100644 --- a/tests/output/render-test.c +++ b/tests/output/render-test.c @@ -22,6 +22,7 @@ #include #include +#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; } -- 2.30.2