lalr1.cc: fix exception safety

lalr1.cc does not reclaim its memory when ended by an exception.

Reported by Oleksii Taran:
http://lists.gnu.org/archive/html/help-bison/2012-09/msg00000.html

* data/lalr1.cc (yyparse): Protect the whole yyparse by a try-catch
block that cleans the stack and the lookahead.
This commit is contained in:
Akim Demaille
2012-09-20 16:59:29 +02:00
parent cff926615f
commit 7e1fabbeae
2 changed files with 39 additions and 7 deletions

1
THANKS
View File

@@ -80,6 +80,7 @@ Nicolas Tisserand nicolas.tisserand@epita.fr
Noah Friedman friedman@gnu.org Noah Friedman friedman@gnu.org
Odd Arild Olsen oao@fibula.no Odd Arild Olsen oao@fibula.no
Oleg Smolsky oleg.smolsky@pacific-simulators.co.nz Oleg Smolsky oleg.smolsky@pacific-simulators.co.nz
Oleksii Taran oleksii.taran@gmail.com
Paolo Bonzini bonzini@gnu.org Paolo Bonzini bonzini@gnu.org
Pascal Bart pascal.bart@epita.fr Pascal Bart pascal.bart@epita.fr
Paul Eggert eggert@cs.ucla.edu Paul Eggert eggert@cs.ucla.edu

View File

@@ -533,6 +533,10 @@ do { \
int yyresult; int yyresult;
// FIXME: This shoud be completely indented. It is not yet to
// avoid gratuitous conflicts when merging into the master branch.
try
{
YYCDEBUG << "Starting parse" << std::endl; YYCDEBUG << "Starting parse" << std::endl;
]m4_ifdef([b4_initial_action], [ ]m4_ifdef([b4_initial_action], [
@@ -573,14 +577,13 @@ b4_dollar_popdef])[]dnl
/* Read a lookahead token. */ /* Read a lookahead token. */
if (yychar == yyempty_) if (yychar == yyempty_)
{ {
YYCDEBUG << "Reading a token: "; YYCDEBUG << "Reading a token: ";
yychar = ]b4_c_function_call([yylex], [int], yychar = ]b4_c_function_call([yylex], [int],
[b4_api_PREFIX[STYPE*], [&yylval]][]dnl [b4_api_PREFIX[STYPE*], [&yylval]][]dnl
b4_locations_if([, [[location*], [&yylloc]]])dnl b4_locations_if([, [[location*], [&yylloc]]])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
} }
/* Convert token to internal form. */ /* Convert token to internal form. */
if (yychar <= yyeof_) if (yychar <= yyeof_)
{ {
@@ -651,17 +654,21 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
else else
yyval = yysemantic_stack_[0]; yyval = yysemantic_stack_[0];
// Compute the default @@$.
{ {
slice<location_type, location_stack_type> slice (yylocation_stack_, yylen); slice<location_type, location_stack_type> slice (yylocation_stack_, yylen);
YYLLOC_DEFAULT (yyloc, slice, yylen); YYLLOC_DEFAULT (yyloc, slice, yylen);
} }
// Perform the reduction.
YY_REDUCE_PRINT (yyn); YY_REDUCE_PRINT (yyn);
switch (yyn) switch (yyn)
{ {
]b4_user_actions[ ]b4_user_actions[
default: default:
break; break;
} }
/* User semantic actions sometimes alter yychar, and that requires /* User semantic actions sometimes alter yychar, and that requires
that yytoken be updated with the new translation. We take the that yytoken be updated with the new translation. We take the
approach of translating immediately before every use of yytoken. approach of translating immediately before every use of yytoken.
@@ -831,6 +838,30 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
} }
return yyresult; return yyresult;
}
catch (...)
{
YYCDEBUG << "Exception caught" << std::endl;
if (yychar != yyempty_)
{
/* Make sure we have latest lookahead translation. See
comments at user semantic actions for why this is
necessary. */
yytoken = yytranslate_ (yychar);
yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval,
&yylloc);
}
while (yystate_stack_.height () != 1)
{
yydestruct_ ("Cleanup: popping",
yystos_[yystate_stack_[0]],
&yysemantic_stack_[0],
&yylocation_stack_[0]);
yypop_ ();
}
throw;
}
} }
// Generate an error message. // Generate an error message.