*** empty log message ***
[pspp] / src / sfm-read.c
index 12df275e7f557cc7824709cf0b4a278db8c3fb5f..109c9a1a5a2ca171fa6dfb7a29db1c8581b000c6 100644 (file)
@@ -33,7 +33,7 @@
 #include "file-handle.h"
 #include "filename.h"
 #include "format.h"
-#include "getline.h"
+#include "getl.h"
 #include "hash.h"
 #include "magic.h"
 #include "misc.h"
@@ -41,6 +41,9 @@
 #include "str.h"
 #include "var.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 #include "debug-print.h"
 
 /* System file reader. */
@@ -86,18 +89,18 @@ struct sfm_var
 
 /* Swap bytes *A and *B. */
 static inline void
-bswap (unsigned char *a, unsigned char *b) 
+bswap (char *a, char *b) 
 {
-  unsigned char t = *a;
+  char t = *a;
   *a = *b;
   *b = t;
 }
 
-/* bswap_int32(): Reverse the byte order of 32-bit integer *X. */
+/* Reverse the byte order of 32-bit integer *X. */
 static inline void
 bswap_int32 (int32 *x_)
 {
-  unsigned char *x = (unsigned char *) x_;
+  char *x = (char *) x_;
   bswap (x + 0, x + 3);
   bswap (x + 1, x + 2);
 }
@@ -106,7 +109,7 @@ bswap_int32 (int32 *x_)
 static inline void
 bswap_flt64 (flt64 *x_)
 {
-  unsigned char *x = (unsigned char *) x_;
+  char *x = (char *) x_;
   bswap (x + 0, x + 7);
   bswap (x + 1, x + 6);
   bswap (x + 2, x + 5);
@@ -342,7 +345,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                {
                  const int  n_vars = data.count / 3 ;
                  int i;
-                 if ( data.count % 3 ) 
+                 if ( data.count % 3 || n_vars > dict_get_var_cnt(*dict) 
                    {
                      msg (MW, _("%s: Invalid subrecord length. "
                                 "Record: 7; Subrecord: 11"), 
@@ -350,7 +353,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                      skip = 1;
                    }
 
-                 for ( i = 0 ; i < n_vars ; ++i ) 
+                 for ( i = 0 ; i < min(n_vars, dict_get_var_cnt(*dict)) ; ++i ) 
                    {
                      struct
                      {
@@ -421,6 +424,16 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                           break;
                         }
 
+                      /* Identify any duplicates. */
+                     if ( compare_var_names(short_name, long_name, 0) &&
+                         NULL != dict_lookup_var (*dict, long_name))
+                        {
+                         lose ((ME, _("%s: Duplicate long variable name `%s' "
+                                      "within system file."),
+                                handle_get_filename (r->fh), long_name));
+                          break;
+                        }
+
                       /* Set long name.
                          Renaming a variable may clear the short
                          name, but we want to retain it, so
@@ -745,10 +758,10 @@ read_variables (struct sfm_reader *r,
   *var_by_idx = 0;
 
   /* Pre-allocate variables. */
-  if ( r->value_cnt != -1 
+  if (r->value_cnt != -1
     {
-      *var_by_idx = xmalloc(r->value_cnt * sizeof (**var_by_idx));
-      r->vars = xmalloc( r->value_cnt * sizeof (*r->vars) );
+      *var_by_idx = xnmalloc (r->value_cnt, sizeof **var_by_idx);
+      r->vars = xnmalloc (r->value_cnt, sizeof *r->vars);
     }
 
 
@@ -786,8 +799,8 @@ read_variables (struct sfm_reader *r,
 
       if ( -1 == r->value_cnt ) 
        {
-         *var_by_idx = xrealloc (*var_by_idx, sizeof **var_by_idx * (i + 1));
-         r->vars = xrealloc(r->vars,  (i + 1) * sizeof (*r->vars) );
+         *var_by_idx = xnrealloc (*var_by_idx, i + 1, sizeof **var_by_idx);
+         r->vars = xnrealloc (r->vars, i + 1, sizeof *r->vars);
        }
 
       /* If there was a long string previously, make sure that the
@@ -864,11 +877,17 @@ read_variables (struct sfm_reader *r,
        }
       name[j] = 0;
 
+      if ( ! var_is_valid_name(name, false) ) 
+        lose ((ME, _("%s: Invalid variable name `%s' within system file."),
+               handle_get_filename (r->fh), name));
+
       /* Create variable. */
+
       vv = (*var_by_idx)[i] = dict_create_var (dict, name, sv.type);
       if (vv == NULL) 
         lose ((ME, _("%s: Duplicate variable name `%s' within system file."),
                handle_get_filename (r->fh), name));
+
       var_set_short_name (vv, vv->name);
 
       /* Case reading data. */
@@ -907,63 +926,45 @@ read_variables (struct sfm_reader *r,
       if (sv.n_missing_values != 0)
        {
          flt64 mv[3];
+          int mv_cnt = abs (sv.n_missing_values);
 
          if (vv->width > MAX_SHORT_STRING)
            lose ((ME, _("%s: Long string variable %s may not have missing "
                          "values."),
                    handle_get_filename (r->fh), vv->name));
 
-         assertive_buf_read (r, mv, sizeof *mv * abs (sv.n_missing_values), 0);
+         assertive_buf_read (r, mv, sizeof *mv * mv_cnt, 0);
 
          if (r->reverse_endian && vv->type == NUMERIC)
-           for (j = 0; j < abs (sv.n_missing_values); j++)
+           for (j = 0; j < mv_cnt; j++)
              bswap_flt64 (&mv[j]);
 
          if (sv.n_missing_values > 0)
            {
-             vv->miss_type = sv.n_missing_values;
-             if (vv->type == NUMERIC)
-               for (j = 0; j < sv.n_missing_values; j++)
-                 vv->missing[j].f = mv[j];
-             else
-               for (j = 0; j < sv.n_missing_values; j++)
-                 memcpy (vv->missing[j].s, &mv[j], vv->width);
+              for (j = 0; j < sv.n_missing_values; j++)
+                if (vv->type == NUMERIC)
+                  mv_add_num (&vv->miss, mv[j]);
+                else
+                  mv_add_str (&vv->miss, (char *) &mv[j]);
            }
          else
            {
-             int x = 0;
-
              if (vv->type == ALPHA)
                lose ((ME, _("%s: String variable %s may not have missing "
                              "values specified as a range."),
                        handle_get_filename (r->fh), vv->name));
 
              if (mv[0] == r->lowest)
-               {
-                 vv->miss_type = MISSING_LOW;
-                 vv->missing[x++].f = mv[1];
-               }
+                mv_add_num_range (&vv->miss, LOWEST, mv[1]);
              else if (mv[1] == r->highest)
-               {
-                 vv->miss_type = MISSING_HIGH;
-                 vv->missing[x++].f = mv[0];
-               }
+                mv_add_num_range (&vv->miss, mv[0], HIGHEST);
              else
-               {
-                 vv->miss_type = MISSING_RANGE;
-                 vv->missing[x++].f = mv[0];
-                 vv->missing[x++].f = mv[1];
-               }
+                mv_add_num_range (&vv->miss, mv[0], mv[1]);
 
              if (sv.n_missing_values == -3)
-               {
-                 vv->miss_type += 3;
-                 vv->missing[x++].f = mv[2];
-               }
+                mv_add_num (&vv->miss, mv[2]);
            }
        }
-      else
-       vv->miss_type = MISSING_NONE;
 
       if (!parse_format_spec (r, sv.print, &vv->print, vv)
          || !parse_format_spec (r, sv.write, &vv->write, vv))
@@ -1035,7 +1036,7 @@ read_value_labels (struct sfm_reader *r,
 {
   struct label 
     {
-      unsigned char raw_value[8]; /* Value as uninterpreted bytes. */
+      char raw_value[8];        /* Value as uninterpreted bytes. */
       union value value;        /* Value. */
       char *label;              /* Null-terminated label string. */
     };
@@ -1057,8 +1058,15 @@ read_value_labels (struct sfm_reader *r,
   if (r->reverse_endian)
     bswap_int32 (&n_labels);
 
+  if ( n_labels >= ((int32) ~0) / sizeof *labels)
+    {    
+      corrupt_msg(MW, _("%s: Invalid number of labels: %d.  Ignoring labels."),
+                 handle_get_filename (r->fh), n_labels);
+      n_labels = 0;
+    }
+
   /* Allocate memory. */
-  labels = xmalloc (n_labels * sizeof *labels);
+  labels = xcalloc (n_labels, sizeof *labels);
   for (i = 0; i < n_labels; i++)
     labels[i].label = NULL;
 
@@ -1110,7 +1118,7 @@ read_value_labels (struct sfm_reader *r,
           handle_get_filename (r->fh), n_vars, dict_get_var_cnt (dict)));
 
   /* Read the list of variables. */
-  var = xmalloc (n_vars * sizeof *var);
+  var = xnmalloc (n_vars, sizeof *var);
   for (i = 0; i < n_vars; i++)
     {
       int32 var_idx;
@@ -1158,8 +1166,8 @@ read_value_labels (struct sfm_reader *r,
       
       if (var[0]->type == ALPHA)
         {
-          const int copy_len = min (sizeof (label->raw_value),
-                                    sizeof (label->label));
+          const int copy_len = min (sizeof label->raw_value,
+                                    sizeof label->label);
           memcpy (label->value.s, label->raw_value, copy_len);
         } else {
           flt64 f;
@@ -1298,7 +1306,7 @@ buffer_input (struct sfm_reader *r)
   size_t amt;
 
   if (r->buf == NULL)
-    r->buf = xmalloc (sizeof *r->buf * 128);
+    r->buf = xnmalloc (128, sizeof *r->buf);
   amt = fread (r->buf, sizeof *r->buf, 128, r->file);
   if (ferror (r->file))
     {