sys-file-reader: Avoid hanging forever if a system file has no variables.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 25 Jul 2015 19:41:44 +0000 (12:41 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 25 Jul 2015 19:42:00 +0000 (12:42 -0700)
doc/dev/system-file-format.texi
src/data/sys-file-reader.c
src/language/data-io/get.c
tests/data/pc+-file-reader.at
tests/data/sys-file-reader.at

index d100aa9d24d59fcd6265e73e70310d6b556403f8..4eb061580db5878b467fdbf4f6608f61d114972b 100644 (file)
@@ -262,6 +262,10 @@ wider than 255 bytes.  Such very long string variables are represented
 by a number of narrower string variables.  @xref{Very Long String
 Record}, for details.
 
+A system file should contain at least one variable and thus at least
+one variable record, but system files have been observed in the wild
+without any variables (thus, no data either).
+
 @example
 int32               rec_type;
 int32               type;
index caab3d9b156ea812edff675fb440038785abc5a1..2607369ea85fe0a40c43905b8972ca3ca0781845 100644 (file)
@@ -2660,7 +2660,7 @@ sys_file_casereader_read (struct casereader *reader, void *r_)
   int retval;
   int i;
 
-  if (r->error)
+  if (r->error || !r->sfm_var_cnt)
     return NULL;
 
   c = case_create (r->proto);
index 9a788a01e3a67922ddad51177cadef6cefbbb418..2440bd900b9d2ee01fcfac78342f70f88004c36b 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006-2007, 2010-15 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
 #include "language/lexer/lexer.h"
 #include "libpspp/compiler.h"
 #include "libpspp/misc.h"
+#include "libpspp/message.h"
 #include "libpspp/str.h"
 
 #include "gl/xalloc.h"
@@ -126,6 +127,13 @@ parse_read_command (struct lexer *lexer, struct dataset *ds,
   if (reader == NULL)
     goto error;
 
+  if (dict_get_var_cnt (dict) == 0)
+    {
+      msg (SE, _("%s: Data file dictionary has no variables."),
+           fh_get_name (fh));
+      goto error;
+    }
+
   stage = case_map_stage_create (dict);
 
   while (lex_token (lexer) != T_ENDCMD)
index 7b88ef4adb6caf7d29e5e3ab0c60948ccdcb5c46..a968e5dac02b9682cb55df6b36f9bf9a1a2e1d32 100644 (file)
@@ -928,6 +928,8 @@ GET FILE='pc+-file.sav' ENCODING='us-ascii'.
 ])
 AT_CHECK([pspp -O format=csv pc+-file.sps], [1], [dnl
 error: `pc+-file.sav' near offset 0x1b0: Record 1 has length 192 (expected 224).
+
+pc+-file.sps:1: error: GET: `pc+-file.sav': Data file dictionary has no variables.
 ])
 AT_CLEANUP
 
index e9b262e86425d8a23ce7fd5629b5516b6d2d208c..019d873081b898e2cc42fb28db338e07030e79a6 100644 (file)
@@ -1557,6 +1557,43 @@ AT_CLEANUP
 \f
 AT_BANNER([system file reader - negative])
 
+AT_SETUP([no variables])
+AT_KEYWORDS([sack synthetic system file negative])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+0; dnl Nominal case size (empty)
+0; dnl Not compressed
+0; dnl Not weighted
+0; dnl 0 cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -O format=csv sys-file.sps], [1], [dnl
+sys-file.sps:1: error: GET: `sys-file.sav': Data file dictionary has no variables.
+])
+
+  dnl At one point pspp-convert would hang forever if there were no variables,
+  dnl so check against regression.
+  AT_CHECK([pspp-convert sys-file.sav sys-file.txt])
+  AT_CHECK([cat sys-file.txt], [0], [
+])
+done
+AT_CLEANUP
+
 AT_SETUP([unspecified character encoding])
 AT_KEYWORDS([sack synthetic system file positive])
 AT_DATA([sys-file.sack], [dnl