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).
This commit is contained in:
Paul Eggert
2005-07-18 18:09:40 +00:00
parent 67fd79c427
commit 6100a9aa2e
6 changed files with 65 additions and 29 deletions

View File

@@ -1,3 +1,25 @@
2005-07-18 Paul Eggert <eggert@cs.ucla.edu>
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 <eggert@cs.ucla.edu> 2005-07-17 Paul Eggert <eggert@cs.ucla.edu>
* tests/conflicts.at (%nonassoc and eof): Don't exit with status * tests/conflicts.at (%nonassoc and eof): Don't exit with status

View File

@@ -657,7 +657,6 @@ union yyGLRStackItem {
}; };
struct yyGLRStack { struct yyGLRStack {
int yyerrflag;
int yyerrState; int yyerrState;
]b4_location_if([[ /* To compute the location of the error token. */ ]b4_location_if([[ /* To compute the location of the error token. */
yyGLRStackItem yyerror_range[3];]])[ yyGLRStackItem yyerror_range[3];]])[
@@ -681,7 +680,6 @@ static void yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[);
static void static void
yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yymsg) yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yymsg)
{ {
yystack->yyerrflag = 1;
if (yymsg != NULL) if (yymsg != NULL)
yyerror (]b4_yyerror_args[yymsg); yyerror (]b4_yyerror_args[yymsg);
longjmp (yystack->yyexception_buffer, 1); longjmp (yystack->yyexception_buffer, 1);
@@ -690,7 +688,7 @@ yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yymsg)
static void static void
yyStackOverflow (yyGLRStack* yystack]b4_pure_formals[) yyStackOverflow (yyGLRStack* yystack]b4_pure_formals[)
{ {
yyFail (yystack]b4_pure_args[, "parser stack overflow"); longjmp (yystack->yyexception_buffer, 2);
} }
#if YYDEBUG || YYERROR_VERBOSE #if YYDEBUG || YYERROR_VERBOSE
@@ -957,7 +955,6 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
static yybool static yybool
yyinitGLRStack (yyGLRStack* yystack, size_t yysize) yyinitGLRStack (yyGLRStack* yystack, size_t yysize)
{ {
yystack->yyerrflag = 0;
yystack->yyerrState = 0; yystack->yyerrState = 0;
yynerrs = 0; yynerrs = 0;
yystack->yyspaceLeft = yysize; yystack->yyspaceLeft = yysize;
@@ -1933,11 +1930,9 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
default: \ default: \
break; \ break; \
case yyabort: \ case yyabort: \
yystack.yyerrflag = 1; \ goto yyabortlab; \
goto yyDone; \
case yyaccept: \ case yyaccept: \
yystack.yyerrflag = 0; \ goto yyacceptlab; \
goto yyDone; \
case yyerr: \ case yyerr: \
goto yyuser_error; \ goto yyuser_error; \
} \ } \
@@ -1950,6 +1945,7 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[ ]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[
{ {
int yyresult;
yySymbol yytoken; yySymbol yytoken;
yyGLRStack yystack; yyGLRStack yystack;
size_t yyposn; size_t yyposn;
@@ -1984,10 +1980,13 @@ m4_popdef([b4_at_dollar])dnl
/* Line __line__ of glr.c. */ /* Line __line__ of glr.c. */
b4_syncline([@oline@], [@ofile@])])dnl b4_syncline([@oline@], [@ofile@])])dnl
[ [
if (setjmp (yystack.yyexception_buffer) != 0)
goto yyDone;
if (! yyinitGLRStack (&yystack, YYINITDEPTH)) 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; yystack.yytokenp = &yytoken;
yyglrShift (&yystack, 0, 0, 0, yylval, &yylloc]b4_user_args[); yyglrShift (&yystack, 0, 0, 0, yylval, &yylloc]b4_user_args[);
yyposn = 0; yyposn = 0;
@@ -2007,7 +2006,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
yyStateNum yystate = yystack.yytops.yystates[0]->yylrState; yyStateNum yystate = yystack.yytops.yystates[0]->yylrState;
YYDPRINTF ((stderr, "Entering state %d\n", yystate)); YYDPRINTF ((stderr, "Entering state %d\n", yystate));
if (yystate == YYFINAL) if (yystate == YYFINAL)
goto yyDone; goto yyacceptlab;
if (yyisDefaultedState (yystate)) if (yyisDefaultedState (yystate))
{ {
yyrule = yydefaultAction (yystate); yyrule = yydefaultAction (yystate);
@@ -2089,14 +2088,27 @@ b4_syncline([@oline@], [@ofile@])])dnl
yyrecoverSyntaxError (&yystack, yylvalp, yyllocp]b4_user_args[); yyrecoverSyntaxError (&yystack, yylvalp, yyllocp]b4_user_args[);
yyposn = yystack.yytops.yystates[0]->yyposn; yyposn = yystack.yytops.yystates[0]->yyposn;
} }
yyDone:
/* On YYABORT, free the lookahead. */ yyacceptlab:
if (yystack.yyerrflag == 1 && yytoken != YYEMPTY) 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", yydestruct ("Error: discarding lookahead",
yytoken, yylvalp]b4_location_if([, yyllocp])[); yytoken, yylvalp]b4_location_if([, yyllocp])[);
yyfreeGLRStack (&yystack); yyfreeGLRStack (&yystack);
return yystack.yyerrflag; return yyresult;
} }
/* DEBUGGING ONLY */ /* DEBUGGING ONLY */

View File

@@ -337,16 +337,18 @@ yyerror (const char *msg)
int int
main (int argc, const char *argv[]) main (int argc, const char *argv[])
{ {
int status;
yydebug = !!getenv ("YYDEBUG"); yydebug = !!getenv ("YYDEBUG");
assert (argc == 2); assert (argc == 2);
yysource = argv[1]; yysource = argv[1];
if (yyparse ()) status = yyparse ();
switch (status)
{ {
printf ("Parsing FAILED.\n"); case 0: printf ("Successful parse.\n"); break;
exit (1); case 1: printf ("Parsing FAILED.\n"); break;
default: printf ("Parsing FAILED (status %d).\n", status); break;
} }
printf ("Successful parse.\n"); return status;
return 0;
} }
]]) ]])
@@ -450,7 +452,7 @@ Parsing FAILED.
# Upon stack overflow, all symbols on the stack should be destroyed. # Upon stack overflow, all symbols on the stack should be destroyed.
# Only check for yacc.c. # Only check for yacc.c.
AT_YACC_IF([ 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: '(' (0@0-9)
sending: 'x' (1@10-19) sending: 'x' (1@10-19)
thing (1@10-19): '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 (6@60-89)
Freeing nterm line (3@30-59) Freeing nterm line (3@30-59)
Freeing nterm line (0@0-29) Freeing nterm line (0@0-29)
Parsing FAILED. Parsing FAILED (status 2).
]]) ]])
]) ])

View File

@@ -288,7 +288,7 @@ power (int base, int exponent)
{ {
int res = 1; int res = 1;
if (exponent < 0) if (exponent < 0)
exit (1); exit (3);
for (/* Niente */; exponent; --exponent) for (/* Niente */; exponent; --exponent)
res *= base; res *= base;
return res; return res;
@@ -315,7 +315,7 @@ main (int argc, const char **argv)
if (!yyin) if (!yyin)
{ {
perror (argv[1]); perror (argv[1]);
exit (1); return 3;
} }
]AT_LALR1_CC_IF([], [m4_bmatch([$4], [%debug], ]AT_LALR1_CC_IF([], [m4_bmatch([$4], [%debug],

View File

@@ -115,8 +115,8 @@ main (int argc, char **argv)
if (argc != 2) if (argc != 2)
abort (); abort ();
if (!freopen (argv[1], "r", stdin)) if (!freopen (argv[1], "r", stdin))
abort (); return 3;
exit (yyparse ()); return yyparse ();
} }
int int

View File

@@ -202,7 +202,7 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
yyin = stdin; yyin = stdin;
if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 1; if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 3;
return yyparse (); return yyparse ();
} }
]]) ]])
@@ -312,7 +312,7 @@ int yylex (void)
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
yyin = stdin; yyin = stdin;
if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 1; if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 3;
return yyparse (); return yyparse ();
} }
]]) ]])