bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

user destructor for unresolved GLR semantic value


From: Joel E. Denny
Subject: user destructor for unresolved GLR semantic value
Date: Wed, 24 Aug 2005 18:23:21 -0400 (EDT)

In the case of an error during a split GLR parse, a bison-2.0b-generated
parser invokes user destructors for unresolved semantic values.
Unresolved basically means uninitialized.  That can lead to seg faults.

At the end of this email is a test program that demonstrates this.  As
written, the appropriate behavior is to write `syntax is ambiguous' on
stderr and exit with status 0.  However, because of the bug, as long as
the uninitialized value of start does not happen to be the same as
global__magic_value, it will write `syntax is ambiguous' and `Bad
destructor call.' on stderr and exit with non-zero status.  Running the
test case a couple of times ought to significantly reduce the chance of
the values being the same.  Maybe there's a better approach?

Following the test case is a patch relative to my latest cvs co.  I merely
added another parameter to yydestruct() to specify whether any user
destructor should actually be invoked.  For tokens, the yydestruct()
caller always specifies yytrue.  Otherwise, the yydestruct() caller passes
the yyGLRState yyresolved member.  I also modified the definition of
b4_yydestruct_generate() in "c.m4" in such a way that "yacc.c" does not
need to be modified.

Joel

-------------------------------------------------------------------
%{
  #include <stdio.h>
  #include <stdlib.h>
  #include <time.h>
  void yyerror( const char * msg );
  int yylex();
  int global__magic_value;
%}

%glr-parser
%union { int value; }
%type <value> start

%destructor {
  if ( $$ != global__magic_value ) {
    fprintf( stderr, "Bad destructor call.\n" );
    exit( EXIT_FAILURE );
  }
} start

%%

start:
   'a' { $$ = global__magic_value; }
   | 'a' { $$ = global__magic_value; }
   ;

%%

int yylex() {
  static int once = 0;
  if ( !once ) { once = 1; return 'a'; }
  return 0;
}

void yyerror( const char * msg ) {
  printf( "%s\n", msg );
}

int main() {
  srand( time(NULL) );
  global__magic_value = rand();
  yyparse();
  return 0;
}
-------------------------------------------------------------------

Index: data/c.m4
===================================================================
RCS file: /cvsroot/bison/bison/data/c.m4,v
retrieving revision 1.30
diff -p -u -r1.30 c.m4
--- data/c.m4   24 Jul 2005 07:24:22 -0000      1.30
+++ data/c.m4   24 Aug 2005 22:17:18 -0000
@@ -340,11 +340,13 @@ m4_popdef([b4_dollar_dollar])dnl
 ])


-# b4_yydestruct_generate(FUNCTION-DECLARATOR)
+# b4_yydestruct_generate(FUNCTION-DECLARATOR, USER-DESTRUCTOR)
 # -------------------------------------------
 # Generate the "yydestruct" function, which declaration is issued using
 # FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C
-# or "b4_c_function_def" for K&R.
+# or "b4_c_function_def" for K&R.  If USER-DESTRUCTOR is "true", add the extra
+# yybool yyuser_destructor argument specifying whether the user destructor
+# should actually be invoked.
 m4_define([b4_yydestruct_generate],
 [[/*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -355,7 +357,8 @@ m4_define([b4_yydestruct_generate],
     [[const char *yymsg],    [yymsg]],
     [[int yytype],           [yytype]],
     [[YYSTYPE *yyvaluep],    [yyvaluep]]b4_location_if([,
-    [[YYLTYPE *yylocationp], [yylocationp]]]))[
+    [[YYLTYPE *yylocationp], [yylocationp]]])m4_if([$2], [true], [,
+    [[yybool yyuser_destructor]]]))[
 {
   /* Pacify ``unused variable'' warnings.  */
   (void) yyvaluep;
@@ -364,7 +367,10 @@ m4_define([b4_yydestruct_generate],
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
+]m4_if([$2], [true], [
+  if (!yyuser_destructor)
+    return;
+])[
   switch (yytype)
     {
 ]m4_map([b4_symbol_actions], m4_defn([b4_symbol_destructors]))[
Index: data/glr.c
===================================================================
RCS file: /cvsroot/bison/bison/data/glr.c,v
retrieving revision 1.114
diff -p -u -r1.114 glr.c
--- data/glr.c  22 Aug 2005 02:31:10 -0000      1.114
+++ data/glr.c  24 Aug 2005 22:17:18 -0000
@@ -884,7 +884,7 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYST
 [
                              /* Bison grammar-table manipulation.  */

-]b4_yydestruct_generate([b4_c_ansi_function_def])[
+]b4_yydestruct_generate([b4_c_ansi_function_def],[true])[

 /** Number of symbols composing the right hand side of rule #RULE. */
 static inline int
@@ -1926,7 +1926,8 @@ yyrecoverSyntaxError (yyGLRStack* yystac
            yyerror_range[2].yystate.yyloc = *yyllocp;
            YYLLOC_DEFAULT (yys->yyloc, yyerror_range, 2);]])[
            yydestruct ("Error: discarding",
-                       *yytokenp, yylvalp]b4_location_if([, yyllocp])[);
+                       *yytokenp, yylvalp]b4_location_if([, yyllocp])[,
+                       yytrue);
          }
        YYDPRINTF ((stderr, "Reading a token: "));
        yychar = YYLEX;
@@ -1983,7 +1984,8 @@ yyrecoverSyntaxError (yyGLRStack* yystac
 ]b4_location_if([[      yystack->yyerror_range[1].yystate.yyloc = 
yys->yyloc;]])[
       yydestruct ("Error: popping",
                  yystos[yys->yylrState],
-                 &yys->yysemantics.yysval]b4_location_if([, &yys->yyloc])[);
+                 &yys->yysemantics.yysval]b4_location_if([, &yys->yyloc])[,
+                 yys->yyresolved);
       yystack->yytops.yystates[0] = yys->yypred;
       yystack->yynextFree -= 1;
       yystack->yyspaceLeft += 1;
@@ -2170,7 +2172,7 @@ b4_syncline(address@hidden@], address@hidden@])])dnl
  yyreturn:
   if (yytoken != YYEOF && yytoken != YYEMPTY)
     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, yylvalp]b4_location_if([, yyllocp])[);
+                yytoken, yylvalp]b4_location_if([, yyllocp])[, yytrue);

   /* If the stack is well-formed, pop the stack until it is empty,
      destroying its entries as we go.  But free the stack regardless
@@ -2185,7 +2187,8 @@ b4_syncline(address@hidden@], address@hidden@])])dnl
 ]b4_location_if([[       yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
 )[         yydestruct ("Cleanup: popping",
                        yystos[yys->yylrState],
-                       &yys->yysemantics.yysval]b4_location_if([, 
&yys->yyloc])[);
+                       &yys->yysemantics.yysval]b4_location_if([, 
&yys->yyloc])[,
+                       yys->yyresolved);
            yystates[0] = yys->yypred;
            yystack.yynextFree -= 1;
            yystack.yyspaceLeft += 1;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]