spreadsheet: Avoid sharing a dictionary between spreadsheet and client.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 31 Jan 2016 20:28:54 +0000 (12:28 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 31 Jan 2016 20:29:18 +0000 (12:29 -0800)
Spreadsheet implementations keep a copy of the dictionary that they build
to simplify reading cases.  Until now, they shared that dictionary, in a
modifiable way, with their client.  This meant, however, that if the client
modified the dictionary, it could screw up reading further cases from the
spreadsheet.

This commit fixes the problem by forcing clients to make their own copy of
the dictionary if they want to modify it.

Bug #44158.

src/data/gnumeric-reader.c
src/data/ods-reader.c
src/data/spreadsheet-reader.h
src/language/data-io/get-data.c
src/ui/gui/psppire-import-assistant.c

index 0783e10f7c1b33452222b82238d95d51ae582004..7033448d8b4dc23a7c63b2d967854d551e0f47d9 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013  Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013, 2016  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
@@ -185,10 +185,13 @@ gnumeric_unref (struct spreadsheet *s)
        {
          xmlFree (r->sheets[i].name);
        }
-    
+
+
       free (r->sheets);
       state_data_destroy (&r->msd);
 
+      dict_destroy (r->dict);
+
       free (s->file_name);
 
       free (r);
@@ -872,8 +875,6 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet,
     }
 
   free (var_spec);
-  dict_destroy (spreadsheet->dict);
-  spreadsheet->dict = NULL;
 
   gnm_file_casereader_destroy (NULL, r);
 
index c5ada6e09101bc3977ee2ecb67af59b0621aed6f..2f058b044d8ac8892115ff53b498a96e7f8c78bf 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
+   Copyright (C) 2011, 2012, 2013, 2016 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
@@ -170,7 +170,9 @@ ods_unref (struct spreadsheet *s)
        {
          xmlFree (r->sheets[i].name);
        }
-       
+
+      dict_destroy (r->dict);
+
       zip_reader_destroy (r->zreader);
       free (r->sheets);
       free (s->file_name);
@@ -919,8 +921,6 @@ ods_make_reader (struct spreadsheet *spreadsheet,
 
   free (var_spec);
 
-  dict_destroy (r->spreadsheet.dict);
-  r->spreadsheet.dict = NULL;
   ods_file_casereader_destroy (NULL, r);
 
   return NULL;
index c03cf71642135f0ef12331e247a4fe44d58fb9a7..0f0819b249bbdf6633acbf65949db236611188bc 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2010, 2016 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
@@ -66,8 +66,9 @@ struct spreadsheet
   /* The total number of sheets in the "workbook" */
   int n_sheets;
 
-  /* The dictionary */
-  struct dictionary *dict;
+  /* The dictionary for client's reference.
+     Client must clone if it needs a permanent or modifiable copy. */
+  const struct dictionary *dict;
 
   int ref_cnt;
 };
index 2bf419659d18e52ae99a91455c05dcd8a5b698df..995be8e7ce896212cd9775af4789c1aa1441360a 100644 (file)
@@ -110,41 +110,30 @@ cmd_get_data (struct lexer *lexer, struct dataset *ds)
       lex_match_id (lexer, "ODS"))
     {
       char *filename = NULL;
-      struct casereader *reader = NULL;
-      struct dictionary *dict = NULL;
-
       if (!parse_spreadsheet (lexer, &filename, &opts))
        goto error;
 
+      struct spreadsheet *spreadsheet = NULL;
       if ( gnm_read_support && 0 == strncasecmp (tok, "GNM", 3))
-       {
-         struct spreadsheet *spreadsheet = gnumeric_probe (filename, true);
-         if (spreadsheet == NULL)
-           goto error;
-         reader = gnumeric_make_reader (spreadsheet, &opts);
-         dict = spreadsheet->dict;
-         gnumeric_unref (spreadsheet);
-       }
+        spreadsheet = gnumeric_probe (filename, true);
       else if ( odf_read_support && 0 == strncasecmp (tok, "ODS", 3))
-       {
-         struct spreadsheet *spreadsheet = ods_probe (filename, true);
-         if (spreadsheet == NULL)
-           goto error;
-         reader = ods_make_reader (spreadsheet, &opts);
-         dict = spreadsheet->dict;
-         ods_unref (spreadsheet);
-       }
+        spreadsheet = ods_probe (filename, true);
 
       free (filename);
+      if (spreadsheet == NULL)
+        goto error;
 
+      struct casereader *reader = spreadsheet_make_reader (spreadsheet, &opts);
       if (reader)
        {
-         dataset_set_dict (ds, dict);
+         dataset_set_dict (ds, dict_clone (spreadsheet->dict));
          dataset_set_source (ds, reader);
          free (tok);
          destroy_spreadsheet_read_info (&opts);
+         spreadsheet_unref (spreadsheet);
          return CMD_SUCCESS;
        }
+      spreadsheet_unref (spreadsheet);
     }
   else
     msg (SE, _("Unsupported TYPE %s."), tok);
index a7d29f2a8cf0391e8c8edf31e3023954bcc7fb20..1b6cf570afd10b99ff95a2c1c34ccc4fec43694a 100644 (file)
@@ -2047,7 +2047,7 @@ prepare_formats_page (PsppireImportAssistant *ia)
        case SPREADSHEET_GNUMERIC:
          {
            reader = spreadsheet_make_reader (ia->spreadsheet, &sro);
-           ia->dict = ia->spreadsheet->dict;
+           ia->dict = dict_clone (ia->spreadsheet->dict);
          }
          break;
        default: