Fix various mad eval leaks
authorFather Chrysostomos <sprout@cpan.org>
Wed, 14 Nov 2012 05:54:32 +0000 (21:54 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Wed, 14 Nov 2012 06:50:01 +0000 (22:50 -0800)
Several SVs that exist for the sake of mad dumps were being set up
even for normal execution.

t/op/svleak.t
toke.c

index 95e1a3a..0b4db43 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 
 use Config;
 
-plan tests => 67;
+plan tests => 68;
 
 # 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
@@ -32,13 +32,12 @@ sub leak {
     cmp_ok($sv1-$sv0, '<=', ($n-1)*$delta, @rest);
 }
 
-# Like leak, but run a string eval instead; takes into account existing
-# string eval leaks under -Dmad (except when -Dmad leaks two or
-# more SVs). The code is used instead of the test name
+# Like leak, but run a string eval instead.
+# The code is used instead of the test name
 # if the name is absent.
 sub eleak {
     my ($n,$delta,$code,@rest) = @_;
-    leak $n, $delta + !!$Config{mad}, sub { eval $code },
+    leak $n, $delta, sub { eval $code },
          @rest ? @rest : $code
 }
 
@@ -189,12 +188,9 @@ leak(2,0,sub { !$^V }, '[perl #109762] version object in boolean context');
 
 # [perl #114356] run-time rexexp with unchanging pattern got
 # inflated refcounts
+eleak(2, 0, 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 q{ my $x = "x"; "abc" =~ /$x/ for 1..5 } }, '#114356');
-}
-
+eleak(2, 0, 'sub', '"sub" with nothing following');
 eleak(2, 0, '+sub:a{}', 'anon subs with invalid attributes');
 eleak(2, 0, 'no warnings; sub a{1 1}', 'sub with syntax error');
 eleak(2, 0, 'no warnings; sub {1 1}', 'anon sub with syntax error');
@@ -204,7 +200,7 @@ eleak(2, 0, '"${<<END}"
                  ', 'unterminated here-doc in quotes in multiline eval');
 eleak(2, 0, '"${<<END
                }"', 'unterminated here-doc in multiline quotes in eval');
-leak(2, !!$Config{mad}, sub { eval { do './op/svleak.pl' } },
+leak(2, 0, sub { eval { do './op/svleak.pl' } },
         'unterminated here-doc in file');
 eleak(2, 0, 'tr/9-0//');
 eleak(2, 0, 'tr/a-z-0//');
@@ -212,7 +208,7 @@ eleak(2, 0, 'no warnings; nonexistent_function 33838',
         'bareword followed by number');
 eleak(2, 0, '//dd;'x20, '"too many errors" when parsing m// flags');
 eleak(2, 0, 's///dd;'x20, '"too many errors" when parsing s/// flags');
-eleak(2, !!$Config{mad}, 'no warnings; 2 2;BEGIN{}',
+eleak(2, 0, 'no warnings; 2 2;BEGIN{}',
       'BEGIN block after syntax error');
 {
     local %INC; # in case Errno is already loaded
@@ -273,7 +269,7 @@ package hhtie {
     sub FIRSTKEY { keys %{$_[0][0]}; each %{$_[0][0]} }
     sub NEXTKEY  { each %{$_[0][0]} }
 }
-leak(2,!!$Config{mad}, sub {
+leak(2, 0, sub {
     eval q`
        BEGIN {
            $hhtie::explosive = 0;
@@ -335,13 +331,12 @@ leak(2, 0, sub {
 # Run-time regexp code blocks
 {
     use re 'eval';
-    my $madness = !!$Config{mad};
     my @tests = ('[(?{})]','(?{})');
     for my $t (@tests) {
-       leak(2, $madness, sub {
+       leak(2, 0, sub {
            / $t/;
        }, "/ \$x/ where \$x is $t does not leak");
-       leak(2, $madness, sub {
+       leak(2, 0, sub {
            /(?{})$t/;
        }, "/(?{})\$x/ where \$x is $t does not leak");
     }
diff --git a/toke.c b/toke.c
index 0389417..6027af3 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -4696,9 +4696,11 @@ Perl_yylex(pTHX)
 #ifdef PERL_MAD
            while (PL_bufptr != PL_bufend &&
              PL_bufptr[0] == '\\' && PL_bufptr[1] == 'E') {
-               if (!PL_thiswhite)
+               if (PL_madskills) {
+                 if (!PL_thiswhite)
                    PL_thiswhite = newSVpvs("");
-               sv_catpvn(PL_thiswhite, PL_bufptr, 2);
+                 sv_catpvn(PL_thiswhite, PL_bufptr, 2);
+               }
                PL_bufptr += 2;
            }
 #else
@@ -4714,9 +4716,11 @@ Perl_yylex(pTHX)
            s = PL_bufptr + 1;
            if (s[1] == '\\' && s[2] == 'E') {
 #ifdef PERL_MAD
-               if (!PL_thiswhite)
+               if (PL_madskills) {
+                 if (!PL_thiswhite)
                    PL_thiswhite = newSVpvs("");
-               sv_catpvn(PL_thiswhite, PL_bufptr, 4);
+                 sv_catpvn(PL_thiswhite, PL_bufptr, 4);
+               }
 #endif
                PL_bufptr = s + 3;
                PL_lex_state = LEX_INTERPCONCAT;
@@ -5374,9 +5378,11 @@ Perl_yylex(pTHX)
     case ' ': case '\t': case '\f': case 013:
 #ifdef PERL_MAD
        PL_realtokenstart = -1;
-       if (!PL_thiswhite)
+       if (PL_madskills) {
+         if (!PL_thiswhite)
            PL_thiswhite = newSVpvs("");
-       sv_catpvn(PL_thiswhite, s, 1);
+         sv_catpvn(PL_thiswhite, s, 1);
+       }
 #endif
        s++;
        goto retry;
@@ -6090,7 +6096,7 @@ Perl_yylex(pTHX)
        force_next(formbrack ? '.' : '}');
        if (formbrack) LEAVE;
 #ifdef PERL_MAD
-       if (!PL_thistoken)
+       if (PL_madskills && !PL_thistoken)
            PL_thistoken = newSVpvs("");
 #endif
        if (formbrack == 2) { /* means . where arguments were expected */
@@ -8428,7 +8434,9 @@ Perl_yylex(pTHX)
                SV *tmpwhite = 0;
 
                char *tstart = SvPVX(PL_linestr) + PL_realtokenstart;
-               SV *subtoken = newSVpvn_flags(tstart, s - tstart, SvUTF8(PL_linestr));
+               SV *subtoken = PL_madskills
+                  ? newSVpvn_flags(tstart, s - tstart, SvUTF8(PL_linestr))
+                  : NULL;
                PL_thistoken = 0;
 
                d = s;
@@ -10336,7 +10344,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims, int re_reparse)
     s += termlen;
 #ifdef PERL_MAD
     tstart = SvPVX(PL_linestr) + stuffstart;
-    if (!PL_thisopen && !keep_delims) {
+    if (PL_madskills && !PL_thisopen && !keep_delims) {
        PL_thisopen = newSVpvn(tstart, s - tstart);
        stuffstart = s - SvPVX(PL_linestr);
     }