summaryrefslogtreecommitdiff
path: root/pad.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-11-14 06:10:37 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-11-14 09:53:47 -0800
commit3ac7ff8feea83945e8004db016e86c3a7ba1c8b0 (patch)
treeb8474af89ce94dac8d31cd640ddb88dc0064054d /pad.c
parent8ca8859f11d3a842e8fc7a0c1d2bb21e709d5a3b (diff)
downloadperl-3ac7ff8feea83945e8004db016e86c3a7ba1c8b0.tar.gz
Stop eval "END OF TERMS" from leaking
I found this memory leak by evaluating lines of the Copying file as Perl code. :-) The parser requires yylex to return exactly one token with each call. Sometimes yylex needs to record a few tokens ahead of time, so its puts them in its forced token stack. The next call to yylex then pops the pending token off that stack. Ops belong to their subroutines. If the subroutine is freed before its root is attached, all the ops created when PL_compcv pointed to that sub are freed as well. To avoid crashes, the ops on the savestack and the forced token stack are specially marked so they are not freed when the sub is freed. When it comes to evaluating "END OF TERMS AND CONDITIONS", the END token causes a subroutine to be created and placed in PL_compcv. The OF token is treated by the lexer as a method call on the TERMS pack- age. The TERMS token is placed in the forced token stack as an sv in an op for a WORD token, and a METHOD token for OF is returned. As soon as the parser sees the OF, it generates an error, which results in LEAVE_SCOPE being called, which frees the subroutine for END while TERMS is still on the forced token stack. So the subroutine’s op cleanup skips that op. Then the parser calls back into the lexer, which returns the TERMS token from the forced token stack. Since there has been an error, the parser discards that token, so the op is never freed. The forced token stack cleanup that happens in parser_free does not catch this, as the token is no longer on that stack. Earlier, to solve the problem of yylex returning freed ops to the parser, resulting in crashes, I set the op_savefree flag on ops on the forced token stack. But that resulted in a leak. So now I am using a different approach: When the sub is freed and frees all its ops, have it also look in the parser’s forced token stack, freeing any ops that belong to it, and setting the point- ers to null.
Diffstat (limited to 'pad.c')
-rw-r--r--pad.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/pad.c b/pad.c
index cc34ade378..12d23b077d 100644
--- a/pad.c
+++ b/pad.c
@@ -370,6 +370,8 @@ Perl_cv_undef(pTHX_ CV *cv)
PAD_SAVE_SETNULLPAD();
/* discard any leaked ops */
+ if (PL_parser)
+ parser_free_nexttoke_ops(PL_parser, (OPSLAB *)CvSTART(cv));
opslab_force_free((OPSLAB *)CvSTART(cv));
CvSTART(cv) = NULL;