Fix potential crash if matrix file variables are of unexpected types
[pspp] / src / language / data-io / matrix-reader.c
index 2c0aee2fec825cdec389ae45ec38d8c8ec343013..afeffe54dab41c697809b30943a9f043cdfb4ec8 100644 (file)
@@ -77,7 +77,6 @@ s_0 ROWTYPE_   VARNAME_   v_0         v_1         v_2
 
 struct matrix_reader
 {
-  const struct dictionary *dict;
   const struct variable *varname;
   const struct variable *rowtype;
   struct casegrouper *grouper;
@@ -86,8 +85,8 @@ struct matrix_reader
   gsl_matrix *mean_vectors;
   gsl_matrix *var_vectors;
 
-  gsl_matrix *correlation;
-  gsl_matrix *covariance;
+  //  gsl_matrix *correlation;
+  //  gsl_matrix *covariance;
 };
 
 struct matrix_reader *
@@ -96,7 +95,6 @@ create_matrix_reader_from_case_reader (const struct dictionary *dict, struct cas
 {
   struct matrix_reader *mr = xzalloc (sizeof *mr);
 
-  mr->dict = dict;
   mr->varname = dict_lookup_var (dict, "varname_");
   if (mr->varname == NULL)
     {
@@ -105,6 +103,14 @@ create_matrix_reader_from_case_reader (const struct dictionary *dict, struct cas
       return NULL;
     }
 
+  if (!var_is_alpha (mr->varname))
+    {
+      msg (ME, _("Matrix dataset variable %s should be of string type."),
+          "VARNAME_");
+      free (mr);
+      return NULL;
+    }
+
   mr->rowtype = dict_lookup_var (dict, "rowtype_");
   if (mr->rowtype == NULL)
     {
@@ -113,6 +119,14 @@ create_matrix_reader_from_case_reader (const struct dictionary *dict, struct cas
       return NULL;
     }
 
+  if (!var_is_alpha (mr->rowtype))
+    {
+      msg (ME, _("Matrix dataset variable %s should be of string type."),
+          "ROWTYPE_");
+      free (mr);
+      return NULL;
+    }
+
   size_t dvarcnt;
   const struct variable **dvars = NULL;
   dict_get_vars (dict, &dvars, &dvarcnt, DC_SCRATCH);
@@ -186,8 +200,6 @@ next_matrix_from_reader (struct matrix_material *mm,
   gsl_matrix_free (mr->n_vectors);
   gsl_matrix_free (mr->mean_vectors);
   gsl_matrix_free (mr->var_vectors);
-  gsl_matrix_free (mr->correlation);
-  gsl_matrix_free (mr->covariance);
 
   if (!casegrouper_get_next_group (mr->grouper, &group))
     return false;
@@ -200,19 +212,16 @@ next_matrix_from_reader (struct matrix_material *mm,
   mm->mean_matrix = mr->mean_vectors;
   mm->var_matrix = mr->var_vectors;
 
-  mr->correlation  = NULL;
-  mr->covariance   = NULL;
-
   // FIXME: Make this into a hash table.
   unsigned long *table = xmalloc (sizeof (*table) * n_vars);
   int i;
   for (i = 0; i < n_vars; ++i)
     {
       const int w = var_get_width (mr->varname);
-      uint8_t s[w];
+      char s[w];
       memset (s, 0, w);
       const char *name = var_get_name (vars[i]);
-      strcpy (s, name);
+      strncpy (s, name, w);
       unsigned long h = hash_bytes (s, w, 0);
       table[i] = h;
     }
@@ -224,8 +233,7 @@ next_matrix_from_reader (struct matrix_material *mm,
       int col, row;
       for (col = 0; col < n_vars; ++col)
        {
-         const struct variable *cv
-           = vars ? vars[col] : dict_get_var (mr->dict, var_get_dict_index (mr->varname) + 1 + col);
+         const struct variable *cv = vars[col];
          double x = case_data (c, cv)->f;
          if (0 == strncasecmp ((char *)value_str (uv, 8), "N       ", 8))
            for (row = 0; row < n_vars; ++row)
@@ -256,22 +264,18 @@ next_matrix_from_reader (struct matrix_material *mm,
       if (mrow == -1)
        continue;
 
-
       if (0 == strncasecmp ((char *) value_str (uv, 8), "CORR    ", 8))
        {
-         matrix_fill_row (&mr->correlation, c, mrow, vars, n_vars);
+         matrix_fill_row (&mm->corr, c, mrow, vars, n_vars);
        }
       else if (0 == strncasecmp ((char *) value_str (uv, 8), "COV     ", 8))
        {
-         matrix_fill_row (&mr->covariance, c, mrow, vars, n_vars);
+         matrix_fill_row (&mm->cov, c, mrow, vars, n_vars);
        }
     }
 
   casereader_destroy (group);
 
-  mm->cov = mr->covariance;
-  mm->corr = mr->correlation;
-
   free (table);
 
   return true;