VECTOR: Check that multiple vectors don't create the same variable name.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 22 Apr 2023 21:51:49 +0000 (14:51 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 22 Apr 2023 21:51:52 +0000 (14:51 -0700)
This is possible but I hadn't realized it before.

Thanks to Youngseok Choi for reporting this bug.
Reported at https://lists.gnu.org/archive/html/bug-gnu-pspp/2023-04/msg00004.html.

src/language/commands/vector.c
tests/language/commands/vector.at

index ba61dcae56de5f46704da4851d42b472f0a5a609..b9407cbb6a5c7959cfcc8bd668edbc983f022140 100644 (file)
@@ -32,6 +32,7 @@
 #include "libpspp/misc.h"
 #include "libpspp/pool.h"
 #include "libpspp/str.h"
+#include "libpspp/string-set.h"
 
 #include "gl/intprops.h"
 #include "gl/xalloc.h"
@@ -116,7 +117,6 @@ cmd_vector (struct lexer *lexer, struct dataset *ds)
           struct fmt_spec format = fmt_for_output (FMT_F, 8, 2);
           bool seen_format = false;
           size_t n_vars = 0;
-          int name_ofs = lex_ofs (lexer) - 2;
           int lparen_ofs = lex_ofs (lexer) - 1;
           while (!lex_match (lexer, T_RPAREN))
             {
@@ -171,6 +171,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds)
 
          /* Check that none of the variables exist and that their names are
              not excessively long. */
+          struct string_set new_names = STRING_SET_INITIALIZER (new_names);
           for (size_t i = 0; i < n_vectors; i++)
             for (size_t j = 0; j < n_vars; j++)
               {
@@ -178,21 +179,32 @@ cmd_vector (struct lexer *lexer, struct dataset *ds)
                 char *error = dict_id_is_valid__ (dict, name);
                 if (error)
                   {
-                    lex_ofs_error (lexer, name_ofs, end_ofs, "%s", error);
+                    lex_ofs_error (lexer, vectors_start, end_ofs, "%s", error);
                     free (error);
                     free (name);
                     goto error;
                   }
                 if (dict_lookup_var (dict, name))
                   {
-                    lex_ofs_error (lexer, name_ofs, end_ofs,
+                    lex_ofs_error (lexer, vectors_start, end_ofs,
                                    _("%s is an existing variable name."),
                                    name);
                     free (name);
+                    string_set_destroy (&new_names);
+                    goto error;
+                  }
+                if (!string_set_insert_nocopy (&new_names, name))
+                  {
+                    /* name was already freed. */
+                    lex_ofs_error (
+                      lexer, vectors_start, end_ofs,
+                      _("Two different vectors add variable %s%zu."),
+                      vectors[i], j + 1);
+                    string_set_destroy (&new_names);
                     goto error;
                   }
-                free (name);
               }
+          string_set_destroy (&new_names);
 
          /* Finally create the variables and vectors. */
           struct variable **vars = pool_nmalloc (pool, n_vars, sizeof *vars);
index 5eeb5bbc067b4e9ddc91e113d38f630fa7449bad..426ab5a0f261c9538dc5c468ced59e1f126e88c0 100644 (file)
@@ -118,6 +118,7 @@ VECTOR v(**).
 VECTOR v(F8.2).
 VECTOR xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(5).
 VECTOR v **.
+VECTOR v v1 (123).
 ])
 AT_DATA([insert.sps], [dnl
 INSERT FILE='vector.sps' ERROR=IGNORE.
@@ -174,5 +175,9 @@ AT_CHECK([pspp --testing-mode -O format=csv insert.sps], [1], [dnl
 "vector.sps:15.10-15.11: error: VECTOR: Syntax error expecting `=' or `@{:@'.
    15 | VECTOR v **.
       |          ^~"
+
+"vector.sps:16.8-16.17: error: VECTOR: Two different vectors add variable v11.
+   16 | VECTOR v v1 (123).
+      |        ^~~~~~~~~~"
 ])
 AT_CLEANUP
\ No newline at end of file