DATA MATRIX: Avoid crash on invalid input
authorJohn Darrington <john@darrington.wattle.id.au>
Thu, 11 May 2017 08:40:51 +0000 (10:40 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Thu, 11 May 2017 08:40:51 +0000 (10:40 +0200)
src/language/data-io/matrix-data.c
tests/language/data-io/matrix-data.at

index 4370908acaa58fd8b15c97a68987707f9855cb2e..752a0be3d26105c5930aa8e1b15b0b093ffcebd1 100644 (file)
@@ -126,7 +126,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
   const struct caseproto *proto = casereader_get_proto (casereader0);
   struct casewriter *writer;
   writer = autopaging_writer_create (proto);
-
+  struct ccase *prev_case = NULL;
   double **matrices = NULL;
   size_t n_splits = 0;
 
@@ -170,6 +170,13 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
       if (0 == strncasecmp (val, "corr    ", ROWTYPE_WIDTH) ||
          0 == strncasecmp (val, "cov     ", ROWTYPE_WIDTH))
        {
+         if (row >= mformat->n_continuous_vars)
+           {
+             msg (SE,
+                  _("There are %d variable declared but the data has at least %d matrix rows."),
+                  mformat->n_continuous_vars, row + 1);
+             goto error;
+           }
          int col;
          for (col = c_offset; col < mformat->n_continuous_vars; ++col)
            {
@@ -198,7 +205,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
      temporary matrix */
   const int idx = var_get_dict_index (mformat->varname);
   row = 0;
-  struct ccase *prev_case = NULL;
+
   prev_split_hash = 1;
   n_splits = 0;
   for (; (c = casereader_read (casereader0)) != NULL; prev_case = c)
@@ -288,6 +295,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
       casewriter_write (writer, outcase);
     }
 
+
   if (prev_case)
     case_unref (prev_case);
 
@@ -298,6 +306,17 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
   struct casereader *reader1 = casewriter_make_reader (writer);
   casereader_destroy (casereader0);
   return reader1;
+
+
+error:
+  if (prev_case)
+    case_unref (prev_case);
+
+  for (i = 0 ; i < n_splits; ++i)
+    free (matrices[i]);
+  free (matrices);
+  casereader_destroy (casereader0);
+  return NULL;
 }
 
 int
index 2f39f5817f27f5f059be228a96644f20dcbc4694..058dc3f08e4c3acbf16b36ee5ef08a1b8779d5cd 100644 (file)
@@ -362,3 +362,41 @@ var06,9.22,.01
 ])
 
 AT_CLEANUP
+
+
+AT_SETUP([Matrix data - too many rows])
+
+dnl Test for a crash which occurred when the matrix had more rows declared
+dnl than variables to hold them.
+AT_DATA([matrix-data.pspp], [dnl
+matrix data
+    variables = rowtype_
+    var01 var02 var03 var04
+    / format = upper diagonal .
+begin data
+    mean     21.4  5.0  72.9  17.4
+    sd       6.5  1.6  22.8  5.7
+    n       106  106  106  106
+    corr    1.00  .32  .48  .28
+    corr    1.00  .72  .54  .44
+    corr    1.00  .50  .59  .64
+    corr    1.00  .62  .49  -.30
+    corr    1.00  .56  -.38  .52
+    corr    1.00  -.73  .91  .80
+    corr    1.00  -.65  -.60
+    corr    1.00  .70
+    corr    1.00
+end data .
+
+execute.
+])
+
+
+AT_CHECK([pspp -O format=csv matrix-data.pspp], [1], [dnl
+matrix-data.pspp:13: error: MATRIX DATA: There are 4 variable declared but the data has at least 5 matrix rows.
+
+matrix-data.pspp:20: error: EXECUTE: EXECUTE is allowed only after the active dataset has been defined.
+])
+
+
+AT_CLEANUP