From: Paul Eggert Date: Mon, 18 Jul 2005 18:09:40 +0000 (+0000) Subject: Improve tests for stack overflow in GLR parser. X-Git-Tag: BISON-2_1~83 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/6100a9aa2e68e992396e3e1da954921dc1fee801 Improve tests for stack overflow in GLR parser. Problem reported by twlevo@xs4all.nl. * data/glr.c (struct yyGLRStack): Remove yyerrflag member. All uses removed. (yyStackOverflow): Just longjmp, but with value 2 so that caller can handle the problem. (YYCHK1): Use goto (a la yacc.c) rather than setting a flag. (yyparse): New local variable yyresult to record the result. Use result of setjmp to set it, rather than storing itinto struct. (yyDone): Remove label. (yyacceptlab, yyabortlab, yyoverflowlab, yyreturn): New labels, to mimic yacc.c. Do not discard lookahead if it's EOF (possible if YYABORT is used). * tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Exit with yyparse status; put status > 1 into diagnostic. Check that status==2 works. * tests/calc.at, tests/cxx-type.at, tests/glr-regression.at: Use exit status 3 for failure to open (which shouldn't happen). --- diff --git a/ChangeLog b/ChangeLog index 0f8d338d..a93c813c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2005-07-18 Paul Eggert + + Improve tests for stack overflow in GLR parser. + Problem reported by twlevo@xs4all.nl. + * data/glr.c (struct yyGLRStack): Remove yyerrflag member. + All uses removed. + (yyStackOverflow): Just longjmp, but with value 2 so that caller + can handle the problem. + (YYCHK1): Use goto (a la yacc.c) rather than setting a flag. + (yyparse): New local variable yyresult to record the result. + Use result of setjmp to set it, rather than storing itinto + struct. + (yyDone): Remove label. + (yyacceptlab, yyabortlab, yyoverflowlab, yyreturn): New labels, + to mimic yacc.c. Do not discard lookahead if it's EOF (possible + if YYABORT is used). + * tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Exit with + yyparse status; put status > 1 into diagnostic. + Check that status==2 works. + * tests/calc.at, tests/cxx-type.at, tests/glr-regression.at: + Use exit status 3 for failure to open (which shouldn't happen). + 2005-07-17 Paul Eggert * tests/conflicts.at (%nonassoc and eof): Don't exit with status diff --git a/data/glr.c b/data/glr.c index f1cf4dc9..23f5669f 100644 --- a/data/glr.c +++ b/data/glr.c @@ -657,7 +657,6 @@ union yyGLRStackItem { }; struct yyGLRStack { - int yyerrflag; int yyerrState; ]b4_location_if([[ /* To compute the location of the error token. */ yyGLRStackItem yyerror_range[3];]])[ @@ -681,7 +680,6 @@ static void yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[); static void yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yymsg) { - yystack->yyerrflag = 1; if (yymsg != NULL) yyerror (]b4_yyerror_args[yymsg); longjmp (yystack->yyexception_buffer, 1); @@ -690,7 +688,7 @@ yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yymsg) static void yyStackOverflow (yyGLRStack* yystack]b4_pure_formals[) { - yyFail (yystack]b4_pure_args[, "parser stack overflow"); + longjmp (yystack->yyexception_buffer, 2); } #if YYDEBUG || YYERROR_VERBOSE @@ -957,7 +955,6 @@ static void yyfreeStateSet (yyGLRStateSet* yyset) static yybool yyinitGLRStack (yyGLRStack* yystack, size_t yysize) { - yystack->yyerrflag = 0; yystack->yyerrState = 0; yynerrs = 0; yystack->yyspaceLeft = yysize; @@ -1933,11 +1930,9 @@ yyrecoverSyntaxError (yyGLRStack* yystack, default: \ break; \ case yyabort: \ - yystack.yyerrflag = 1; \ - goto yyDone; \ + goto yyabortlab; \ case yyaccept: \ - yystack.yyerrflag = 0; \ - goto yyDone; \ + goto yyacceptlab; \ case yyerr: \ goto yyuser_error; \ } \ @@ -1950,6 +1945,7 @@ yyrecoverSyntaxError (yyGLRStack* yystack, ]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[ { + int yyresult; yySymbol yytoken; yyGLRStack yystack; size_t yyposn; @@ -1984,10 +1980,13 @@ m4_popdef([b4_at_dollar])dnl /* Line __line__ of glr.c. */ b4_syncline([@oline@], [@ofile@])])dnl [ - if (setjmp (yystack.yyexception_buffer) != 0) - goto yyDone; if (! yyinitGLRStack (&yystack, YYINITDEPTH)) - yyStackOverflow (&yystack]b4_lpure_args[); + goto yyoverflowlab; + switch (setjmp (yystack.yyexception_buffer)) + { + case 1: goto yyabortlab; + case 2: goto yyoverflowlab; + } yystack.yytokenp = &yytoken; yyglrShift (&yystack, 0, 0, 0, yylval, &yylloc]b4_user_args[); yyposn = 0; @@ -2007,7 +2006,7 @@ b4_syncline([@oline@], [@ofile@])])dnl yyStateNum yystate = yystack.yytops.yystates[0]->yylrState; YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) - goto yyDone; + goto yyacceptlab; if (yyisDefaultedState (yystate)) { yyrule = yydefaultAction (yystate); @@ -2089,14 +2088,27 @@ b4_syncline([@oline@], [@ofile@])])dnl yyrecoverSyntaxError (&yystack, yylvalp, yyllocp]b4_user_args[); yyposn = yystack.yytops.yystates[0]->yyposn; } - yyDone: - /* On YYABORT, free the lookahead. */ - if (yystack.yyerrflag == 1 && yytoken != YYEMPTY) + + yyacceptlab: + yyresult = 0; + goto yyreturn; + + yyabortlab: + yyresult = 1; + goto yyreturn; + + yyoverflowlab: + yyerror (]b4_lyyerror_args["parser stack overflow"); + yyresult = 2; + /* Fall through. */ + + yyreturn: + if (yytoken != YYEOF && yytoken != YYEMPTY) yydestruct ("Error: discarding lookahead", yytoken, yylvalp]b4_location_if([, yyllocp])[); yyfreeGLRStack (&yystack); - return yystack.yyerrflag; + return yyresult; } /* DEBUGGING ONLY */ diff --git a/tests/actions.at b/tests/actions.at index 7231e7e6..55e51c6f 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -337,16 +337,18 @@ yyerror (const char *msg) int main (int argc, const char *argv[]) { + int status; yydebug = !!getenv ("YYDEBUG"); assert (argc == 2); yysource = argv[1]; - if (yyparse ()) + status = yyparse (); + switch (status) { - printf ("Parsing FAILED.\n"); - exit (1); + case 0: printf ("Successful parse.\n"); break; + case 1: printf ("Parsing FAILED.\n"); break; + default: printf ("Parsing FAILED (status %d).\n", status); break; } - printf ("Successful parse.\n"); - return 0; + return status; } ]]) @@ -450,7 +452,7 @@ Parsing FAILED. # Upon stack overflow, all symbols on the stack should be destroyed. # Only check for yacc.c. AT_YACC_IF([ -AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 1, +AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 2, [[sending: '(' (0@0-9) sending: 'x' (1@10-19) thing (1@10-19): 'x' (1@10-19) @@ -493,7 +495,7 @@ Freeing nterm line (9@90-119) Freeing nterm line (6@60-89) Freeing nterm line (3@30-59) Freeing nterm line (0@0-29) -Parsing FAILED. +Parsing FAILED (status 2). ]]) ]) diff --git a/tests/calc.at b/tests/calc.at index db92f700..65148fc9 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -288,7 +288,7 @@ power (int base, int exponent) { int res = 1; if (exponent < 0) - exit (1); + exit (3); for (/* Niente */; exponent; --exponent) res *= base; return res; @@ -315,7 +315,7 @@ main (int argc, const char **argv) if (!yyin) { perror (argv[1]); - exit (1); + return 3; } ]AT_LALR1_CC_IF([], [m4_bmatch([$4], [%debug], diff --git a/tests/cxx-type.at b/tests/cxx-type.at index f9c093c5..0fcdfdb6 100644 --- a/tests/cxx-type.at +++ b/tests/cxx-type.at @@ -115,8 +115,8 @@ main (int argc, char **argv) if (argc != 2) abort (); if (!freopen (argv[1], "r", stdin)) - abort (); - exit (yyparse ()); + return 3; + return yyparse (); } int diff --git a/tests/glr-regression.at b/tests/glr-regression.at index bcb7773b..e6534624 100644 --- a/tests/glr-regression.at +++ b/tests/glr-regression.at @@ -202,7 +202,7 @@ int main (int argc, char **argv) { yyin = stdin; - if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 1; + if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 3; return yyparse (); } ]]) @@ -312,7 +312,7 @@ int yylex (void) int main(int argc, char* argv[]) { yyin = stdin; - if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 1; + if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 3; return yyparse (); } ]])