]> git.saurik.com Git - bison.git/commitdiff
named references: fix double free.
authorAkim Demaille <demaille@gostai.com>
Wed, 2 Mar 2011 16:06:58 +0000 (17:06 +0100)
committerAkim Demaille <demaille@gostai.com>
Wed, 9 Mar 2011 20:04:17 +0000 (21:04 +0100)
In `rhs[name]: "a" | "b"', do not free "name" twice.
Reported by Tys Lefering.
<http://lists.gnu.org/archive/html/bug-bison/2010-06/msg00002.html>

* src/named-ref.h, src/named-ref.c (named_ref_copy): New.
* src/parse-gram.y (current_lhs): Rename as...
(current_lhs_symbol): this.
(current_lhs): New function.  Use it to free the current lhs
named reference.
* src/reader.c: Bind lhs to a copy of the current named reference.
* src/symlist.c: Rely on free (0) being valid.
* tests/named-refs.at: Test this.

ChangeLog
THANKS
src/named-ref.c
src/named-ref.h
src/parse-gram.y
src/reader.c
src/symlist.c
tests/named-refs.at

index 4bb16a83aff6526efa887013ceaa1021ff12d164..448e54aaf772256b5eb57ce42a8ea12d50121dfd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2011-03-09  Akim Demaille  <akim@lrde.epita.fr>
+
+       named references: fix double free.
+       In `rhs[name]: "a" | "b"', do not free "name" twice.
+       Reported by Tys Lefering.
+       <http://lists.gnu.org/archive/html/bug-bison/2010-06/msg00002.html>
+       * src/named-ref.h, src/named-ref.c (named_ref_copy): New.
+       * src/parse-gram.y (current_lhs): Rename as...
+       (current_lhs_symbol): this.
+       (current_lhs): New function.  Use it to free the current lhs
+       named reference.
+       * src/reader.c: Bind lhs to a copy of the current named reference.
+       * src/symlist.c: Rely on free (0) being valid.
+       * tests/named-refs.at: Test this.
+
 2011-03-09  Akim Demaille  <akim@lrde.epita.fr>
 
        tests: style changes.
diff --git a/THANKS b/THANKS
index ac6047a4877d1d92500f54f6e7ed96ea21e17889..ad6f37930aba1dc99ff60ad0874cc6322c6f90fe 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -102,7 +102,7 @@ Tom Lane                  tgl@sss.pgh.pa.us
 Tom Tromey                tromey@cygnus.com
 Tommy Nordgren            tommy.nordgren@chello.se
 Troy A. Johnson           troyj@ecn.purdue.edu
-Tys Lefering              twlevo@xs4all.nl
+Tys Lefering              twlevo@gmail.com
 Vin Shelton               acs@alumni.princeton.edu
 Wayne Green               wayne@infosavvy.com
 Wolfram Wagner            ww@mpi-sb.mpg.de
index 4bf3da12e323d7198bcd4ba6b47e5b2528d5e3ed..132c74146d566625a2cb4021797967b1e74c73fc 100644 (file)
@@ -33,6 +33,12 @@ named_ref_new (uniqstr id, location loc)
   return res;
 }
 
+named_ref *
+named_ref_copy (const named_ref *r)
+{
+  return named_ref_new (r->id, r->loc);
+}
+
 void
 named_ref_free (named_ref *r)
 {
index 0f96e463ea848fc3343d495ad50a4270e34efd9b..46d9d8d42af8a5d4251c4fd739fbbec14a694cdf 100644 (file)
@@ -37,6 +37,9 @@ typedef struct named_ref
 /* Allocate a named reference object. */
 named_ref *named_ref_new (uniqstr id, location loc);
 
+/* Allocate and return a copy.  */
+named_ref *named_ref_copy (const named_ref *r);
+
 /* Free a named reference object. */
 void named_ref_free (named_ref *r);
 
index 8871f67203fd763a19ca9efb1f22320f161ca97b..8c2e18d1102f2be9a71a70d69a4a9433110d627e 100644 (file)
@@ -61,11 +61,30 @@ static void add_param (char const *type, char *decl, location loc);
 
 static symbol_class current_class = unknown_sym;
 static uniqstr current_type = NULL;
-static symbol *current_lhs;
+static symbol *current_lhs_symbol;
 static location current_lhs_location;
 static named_ref *current_lhs_named_ref;
 static int current_prec = 0;
 
+/** Set the new current left-hand side symbol, possibly common
+ * to several right-hand side parts of rule.
+ */
+static
+void
+current_lhs(symbol *sym, location loc, named_ref *ref)
+{
+  current_lhs_symbol = sym;
+  current_lhs_location = loc;
+  /* In order to simplify memory management, named references for lhs
+     are always assigned by deep copy into the current symbol_list
+     node.  This is because a single named-ref in the grammar may
+     result in several uses when the user factors lhs between several
+     rules using "|".  Therefore free the parser's original copy.  */
+  free (current_lhs_named_ref);
+  current_lhs_named_ref = ref;
+}
+
+
 #define YYTYPE_INT16 int_fast16_t
 #define YYTYPE_INT8 int_fast8_t
 #define YYTYPE_UINT16 uint_fast16_t
@@ -526,8 +545,11 @@ rules_or_grammar_declaration:
 ;
 
 rules:
-  id_colon named_ref.opt { current_lhs = $1; current_lhs_location = @1;
-    current_lhs_named_ref = $2; } rhses.1
+  id_colon named_ref.opt { current_lhs ($1, @1, $2); } rhses.1
+  {
+    /* Free the current lhs. */
+    current_lhs (0, @1, 0);
+  }
 ;
 
 rhses.1:
@@ -538,7 +560,7 @@ rhses.1:
 
 rhs:
   /* Nothing.  */
-    { grammar_current_rule_begin (current_lhs, current_lhs_location,
+    { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
                                  current_lhs_named_ref); }
 | rhs symbol named_ref.opt
     { grammar_current_rule_symbol_append ($2, @2, $3); }
index 9153f2101bf2c78ba115e35735cc5f2c62239d21..86cc82c9677ca7b1fc668bb97c307c43e015e5f0 100644 (file)
@@ -231,7 +231,7 @@ grammar_current_rule_begin (symbol *lhs, location loc,
 
   p = grammar_symbol_append (lhs, loc);
   if (lhs_name)
-    assign_named_ref(p, lhs_name);
+    assign_named_ref (p, named_ref_copy (lhs_name));
 
   current_rule = grammar_end;
 
index e717c3e1a4775774aa2e47b4005557ffb1f175c4..190d0073a4feb6c94cc873dfbc61e440baeeed77 100644 (file)
@@ -151,8 +151,7 @@ symbol_list_free (symbol_list *list)
   for (node = list; node; node = next)
     {
       next = node->next;
-      if (node->named_ref)
-        named_ref_free (node->named_ref);
+      named_ref_free (node->named_ref);
       free (node);
     }
 }
index 98f45a532b6be83cd018d1673d75c5efd1d3c8f2..ff414a93dd0b22be5185de76b86ee51a738b2673 100644 (file)
@@ -472,6 +472,19 @@ AT_CLEANUP
 
 #######################################################################
 
+# Bison used to free twice the named ref for "a", since a single copy
+# was used in two rules.
+AT_SETUP([Factored LHS])
+AT_DATA_GRAMMAR([test.y],
+[[
+%%
+start[a]: "foo" | "bar";
+]])
+AT_BISON_CHECK([-o test.c test.y])
+AT_CLEANUP
+
+#######################################################################
+
 AT_SETUP([Unresolved references])
 AT_DATA_GRAMMAR([test.y],
 [[