From eb1b07409f0ccad9970c8a60ded9f2a56d205b9c Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Sat, 28 Jul 2007 04:27:32 +0000 Subject: [PATCH] Fix push parsing memory leak reported by Brandon Lucia at . * THANKS: Add Brandon Lucia. * data/push.c (yypstate_delete): Free the stack if it was reallocated but the parse never completed and thus freed it. * tests/Makefile.am (TESTSUITE_AT): Add push.at. * tests/testsuite.at: Include push.at. * test/push.at: New. (Push Parsing: Memory Leak for Early Deletion): New test case. --- ChangeLog | 12 +++++++ THANKS | 1 + data/push.c | 6 ++++ tests/Makefile.am | 3 +- tests/push.at | 82 ++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 3 ++ 6 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/push.at diff --git a/ChangeLog b/ChangeLog index 205ce5ef..a11ca86c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2007-07-27 Joel E. Denny + + Fix push parsing memory leak reported by Brandon Lucia at + . + * THANKS: Add Brandon Lucia. + * data/push.c (yypstate_delete): Free the stack if it was reallocated + but the parse never completed and thus freed it. + * tests/Makefile.am (TESTSUITE_AT): Add push.at. + * tests/testsuite.at: Include push.at. + * test/push.at: New. + (Push Parsing: Memory Leak for Early Deletion): New test case. + 2007-07-17 Joel E. Denny Improve handling of multiple S/R conflicts in the same state and of S/R diff --git a/THANKS b/THANKS index 23823699..d0e84fc5 100644 --- a/THANKS +++ b/THANKS @@ -15,6 +15,7 @@ Baron Schwartz baron@sequent.org Benoit Perrot benoit.perrot@epita.fr Bert Deknuydt Bert.Deknuydt@esat.kuleuven.ac.be Bob Rossi bob@brasko.net +Brandon Lucia blucia@gmail.com Bruce Lilly blilly@erols.com Bruno Haible bruno@clisp.org Charles-Henri de Boysson de-boy_c@epita.fr diff --git a/data/push.c b/data/push.c index ee9aa671..c72d1573 100644 --- a/data/push.c +++ b/data/push.c @@ -1124,6 +1124,12 @@ b4_push_if( ]b4_c_function_def([[yypstate_delete]], [[void]], [[[yypstate *yyps]], [[yyps]]])[ { +#ifndef yyoverflow + /* If the stack was reallocated but the parse did not complete, then the + stack still needs to be freed. */ + if (!yyps->yynew && yyps->yyss != yyps->yyssa) + YYSTACK_FREE (yyps->yyss); +#endif free (yyps); } diff --git a/tests/Makefile.am b/tests/Makefile.am index 64999869..d10f035b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -53,7 +53,8 @@ TESTSUITE_AT = \ torture.at existing.at regression.at \ c++.at \ java.at \ - cxx-type.at glr-regression.at + cxx-type.at glr-regression.at \ + push.at TESTSUITE = $(srcdir)/testsuite diff --git a/tests/push.at b/tests/push.at new file mode 100644 index 00000000..62593d3e --- /dev/null +++ b/tests/push.at @@ -0,0 +1,82 @@ +# Checking Push Parsing. -*- Autotest -*- +# Copyright (C) 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +AT_BANNER([[Push Parsing Tests]]) + +## ---------------------------------------------- ## +## Push Parsing: Memory Leak for Early Deletion. ## +## ---------------------------------------------- ## + +AT_SETUP([[Push Parsing: Memory Leak for Early Deletion]]) + +# Requires Valgrind. + +AT_DATA_GRAMMAR([[input.y]], +[[ +%{ + #include + #include + #define YYINITDEPTH 1 + void yyerror (char const *msg); +%} + +%pure-parser %push-parser + +%% + +start: 'a' 'b' 'c' ; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +main (void) +{ + yypstate *yyps; + YYSTYPE yylval; + + /* Make sure we don't try to free yyps->yyss in this case. */ + yyps = yypstate_new (); + yypstate_delete (yyps); + + /* yypstate_delete used to leak yyps->yyss if the stack was reallocated but + the parse did not return on success, syntax error, or memory + exhaustion. */ + yyps = yypstate_new (); + assert (yypush_parse (yyps, 'a', &yylval) == YYPUSH_MORE); + yypstate_delete (yyps); + + yyps = yypstate_new (); + assert (yypush_parse (yyps, 'a', &yylval) == YYPUSH_MORE); + assert (yypush_parse (yyps, 'b', &yylval) == YYPUSH_MORE); + yypstate_delete (yyps); + + return 0; +} +]]) + +AT_CHECK([[bison -o input.c input.y]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 569acfb8..f522cf64 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -80,5 +80,8 @@ m4_include([cxx-type.at]) # Regression tests m4_include([glr-regression.at]) +# Push parsing specific tests. +m4_include([push.at]) + m4_popdef([AT_CHECK]) m4_popdef([ORIGINAL_AT_CHECK]) -- 2.45.2