Stop unterminated here-docs from leaking memory
authorFather Chrysostomos <sprout@cpan.org>
Mon, 27 Aug 2012 06:10:28 +0000 (23:10 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 28 Aug 2012 06:24:00 +0000 (23:24 -0700)
MANIFEST
t/op/svleak.pl [new file with mode: 0644]
t/op/svleak.t
toke.c

index 41a4aa5..70b52d2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -5370,6 +5370,7 @@ t/op/sub_lval.t                   See if lvalue subroutines work
 t/op/substr.t                  See if substr works
 t/op/substr_thr.t              See if substr works in another thread
 t/op/sub.t                     See if subroutines work
+t/op/svleak.pl                 Test file for svleak.t
 t/op/svleak.t                  See if stuff leaks SVs
 t/op/switch.t                  See if switches (given/when) work
 t/op/symbolcache.t             See if undef/delete works on stashes with functions
diff --git a/t/op/svleak.pl b/t/op/svleak.pl
new file mode 100644 (file)
index 0000000..9e1352e
--- /dev/null
@@ -0,0 +1 @@
+<<END
index b0e72f4..3a3d052 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 
 use Config;
 
-plan tests => 22;
+plan tests => 25;
 
 # run some code N times. If the number of SVs at the end of loop N is
 # greater than (N-1)*delta at the end of loop 1, we've got a leak
@@ -172,3 +172,12 @@ SKIP: {
     leak(2, 0, sub { eval q{ my $x = "x"; "abc" =~ /$x/ for 1..5 } }, '#114356');
 }
 
+SKIP: {
+    skip "disabled under -Dmad (eval leaks)" if $Config{mad};
+    leak(2, 0, sub { eval '"${<<END}"
+                 ' }, 'unterminated here-doc in quotes in multiline eval');
+    leak(2, 0, sub { eval '"${<<END
+               }"' }, 'unterminated here-doc in multiline quotes in eval');
+    leak(2, 0, sub { eval { do './op/svleak.pl' } },
+        'unterminated here-doc in file');
+}
diff --git a/toke.c b/toke.c
index fa8f5e7..c607071 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -9681,6 +9681,8 @@ S_scan_heredoc(pTHX_ register char *s)
                ++PL_parser->herelines;
        }
        if (s >= bufend) {
+           SvREFCNT_dec(herewas);
+           SvREFCNT_dec(tmpstr);
            CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            missingterm(PL_tokenbuf + 1);
        }
@@ -9705,6 +9707,8 @@ S_scan_heredoc(pTHX_ register char *s)
                ++PL_parser->herelines;
        }
        if (s >= PL_bufend) {
+           SvREFCNT_dec(herewas);
+           SvREFCNT_dec(tmpstr);
            CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            missingterm(PL_tokenbuf + 1);
        }
@@ -9759,6 +9763,8 @@ S_scan_heredoc(pTHX_ register char *s)
        CopLINE_set(PL_curcop, PL_multi_start + PL_parser->herelines + 1);
        if (!lex_next_chunk(LEX_NO_TERM)
         && (!SvCUR(tmpstr) || SvEND(tmpstr)[-1] != '\n')) {
+           SvREFCNT_dec(herewas);
+           SvREFCNT_dec(tmpstr);
            CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            missingterm(PL_tokenbuf + 1);
        }