pivot-table: Fix pivot_table_dump() null pointer dereference in special case.
[pspp] / src / output / pivot-table.c
index 6bb446ed8ea5bb2895274a8907e58c88e5caf367..4fd6283396d2f2634c246656b621d31043e01202 100644 (file)
@@ -968,7 +968,7 @@ clone_category (struct pivot_category *old,
     .extra_depth = old->extra_depth,
 
     .subs = (old->n_subs
-             ? xzalloc (old->n_subs * sizeof *new->subs)
+             ? xcalloc (old->n_subs, sizeof *new->subs)
              : NULL),
     .n_subs = old->n_subs,
     .allocated_subs = old->n_subs,
@@ -1006,9 +1006,9 @@ clone_dimension (struct pivot_dimension *old, struct pivot_table *new_pt)
     .axis_type = old->axis_type,
     .level = old->level,
     .top_index = old->top_index,
-    .data_leaves = xzalloc (old->n_leaves * sizeof *new->data_leaves),
-    .presentation_leaves = xzalloc (old->n_leaves
-                                    * sizeof *new->presentation_leaves),
+    .data_leaves = xcalloc (old->n_leaves , sizeof *new->data_leaves),
+    .presentation_leaves = xcalloc (old->n_leaves
+                                    , sizeof *new->presentation_leaves),
     .n_leaves = old->n_leaves,
     .allocated_leaves = old->n_leaves,
     .hide_all_labels = old->hide_all_labels,
@@ -1939,6 +1939,8 @@ compose_headings (const struct pivot_table *pt,
 static void
 free_headings (const struct pivot_axis *axis, char ***headings)
 {
+  if (!headings)
+    return;
   for (size_t i = 0; i < axis->label_depth; i++)
     {
       for (size_t j = 0; j < axis->extent; j++)
@@ -2094,21 +2096,30 @@ pivot_table_dump (const struct pivot_table *table, int indentation)
       size_t *row_enumeration = pivot_table_enumerate_axis (
         table, PIVOT_AXIS_ROW, layer_indexes, table->look->omit_empty, NULL);
 
+      /* Print column headings.
+
+         Ordinarily the test for nonnull 'column_headings' would be
+         unnecessary, because 'column_headings' is null only if the axis's
+         label_depth is 0, but there is a special case for the column axis only
+         in pivot_table_assign_label_depth(). */
       char ***column_headings = compose_headings (
         table, &table->axes[PIVOT_AXIS_COLUMN], column_enumeration);
-      for (size_t y = 0; y < table->axes[PIVOT_AXIS_COLUMN].label_depth; y++)
+      if (column_headings)
         {
-          indent (indentation + 1);
-          for (size_t x = 0; x < table->axes[PIVOT_AXIS_COLUMN].extent; x++)
+          for (size_t y = 0; y < table->axes[PIVOT_AXIS_COLUMN].label_depth; y++)
             {
-              if (x)
-                fputs ("; ", stdout);
-              if (column_headings[y][x])
-                fputs (column_headings[y][x], stdout);
+              indent (indentation + 1);
+              for (size_t x = 0; x < table->axes[PIVOT_AXIS_COLUMN].extent; x++)
+                {
+                  if (x)
+                    fputs ("; ", stdout);
+                  if (column_headings && column_headings[y] && column_headings[y][x])
+                    fputs (column_headings[y][x], stdout);
+                }
+              putchar ('\n');
             }
-          putchar ('\n');
+          free_headings (&table->axes[PIVOT_AXIS_COLUMN], column_headings);
         }
-      free_headings (&table->axes[PIVOT_AXIS_COLUMN], column_headings);
 
       indent (indentation + 1);
       printf ("-----------------------------------------------\n");
@@ -2844,13 +2855,22 @@ pivot_value_new_value (const union value *value, int width,
 /* Returns a new pivot_value for VARIABLE. */
 struct pivot_value *
 pivot_value_new_variable (const struct variable *variable)
+{
+  return pivot_value_new_variable__ (var_get_name (variable),
+                                     var_get_label (variable));
+}
+
+/* Returns a new pivot_value for a variable with the given NAME and optional
+   LABEL. */
+struct pivot_value *
+pivot_value_new_variable__ (const char *name, const char *label)
 {
   struct pivot_value *value = xmalloc (sizeof *value);
   *value = (struct pivot_value) {
     .variable = {
       .type = PIVOT_VALUE_VARIABLE,
-      .var_name = xstrdup (var_get_name (variable)),
-      .var_label = xstrdup_if_nonempty (var_get_label (variable)),
+      .var_name = xstrdup (name),
+      .var_label = xstrdup_if_nonempty (label),
     },
   };
   return value;