sys-file-reader: Tolerate variable labels longer than 255 bytes.
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 21 May 2010 04:54:56 +0000 (21:54 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 21 May 2010 04:54:56 +0000 (21:54 -0700)
Michel Boaventura provided a system file with a 256-byte variable label
that PSPP rejected.  This commit allows it to be read.

doc/dev/system-file-format.texi
src/data/sys-file-reader.c
tests/dissect-sysfile.c

index 1309cb79195d7bcb04705b624e70c90abc251654..757867cab230f5a7d6b11936d5b00951120f7332 100644 (file)
@@ -267,8 +267,10 @@ stops (@samp{.}).  The variable name is padded on the right with spaces.
 
 @item int32 label_len;
 This field is present only if @code{has_var_label} is set to 1.  It is
-set to the length, in characters, of the variable label, which must be a
-number between 0 and 120.
+set to the length, in characters, of the variable label.  The
+documented maximum length varies from 120 to 255 based on SPSS
+version, but some files have been seen with longer labels.  PSPP
+accepts longer labels and truncates them to 255 bytes on input.
 
 @item char label[];
 This field is present only if @code{has_var_label} is set to 1.  It has
@@ -426,7 +428,9 @@ in length.  Its type and width cannot be determined until the
 following value label variables record (see below) is read.
 
 @item char label_len;
-The label's length, in bytes.
+The label's length, in bytes.  The documented maximum length varies
+from 60 to 120 based on SPSS version.  PSPP supports value labels up
+to 255 bytes long.
 
 @item char label[];
 @code{label_len} bytes of the actual label, followed by up to 7 bytes
index d2b105c0255ea7da523463f7c7caa232950f63c6..48a5188fb65fe39586804774c6e1f96b09ea0a92 100644 (file)
@@ -614,16 +614,20 @@ read_variable_record (struct sfm_reader *r, struct dictionary *dict,
     sys_error (r, _("Variable label indicator field is not 0 or 1."));
   if (has_variable_label == 1)
     {
-      size_t len;
+      size_t len, read_len;
       char label[255 + 1];
 
       len = read_int (r);
-      if (len >= sizeof label)
-        sys_error (r, _("Variable %s has label of invalid length %zu."),
-                   name, len);
-      read_string (r, label, len + 1);
+
+      /* Read up to 255 bytes of label. */
+      read_len = MIN (sizeof label - 1, len);
+      read_string (r, label, read_len + 1);
       var_set_label (var, label);
 
+      /* Skip unread label bytes. */
+      skip_bytes (r, len - read_len);
+
+      /* Skip label padding up to multiple of 4 bytes. */
       skip_bytes (r, ROUND_UP (len, 4) - len);
     }
 
index 25e2f7f43712b3ffbede9994e711071d03f12e39..3d26a0fb0275c448faa728d529c8ed72022dbd92 100644 (file)
@@ -357,16 +357,20 @@ read_variable_record (struct sfm_reader *r)
   if (has_variable_label == 1)
     {
       long long int offset = ftello (r->file);
-      size_t len;
+      size_t len, read_len;
       char label[255 + 1];
 
       len = read_int (r);
-      if (len >= sizeof label)
-        sys_error (r, _("Variable %s has label of invalid length %zu."),
-                   name, len);
-      read_string (r, label, len + 1);
+
+      /* Read up to 255 bytes of label. */
+      read_len = MIN (sizeof label - 1, len);
+      read_string (r, label, read_len + 1);
       printf("\t%08llx Variable label: \"%s\"\n", offset, label);
 
+      /* Skip unread label bytes. */
+      skip_bytes (r, len - read_len);
+
+      /* Skip label padding up to multiple of 4 bytes. */
       skip_bytes (r, ROUND_UP (len, 4) - len);
     }