This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop cv-to-glob assignment redef warnings from leaking
[perl5.git] / t / op / svleak.t
index 8416656..a3c14b8 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 
 use Config;
 
-plan tests => 65;
+plan tests => 107;
 
 # 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
 }
 
@@ -70,6 +69,45 @@ leak(5, 0, sub {},                 "basic check 1 of leak test infrastructure");
 leak(5, 0, sub {push @a,1;pop @a}, "basic check 2 of leak test infrastructure");
 leak(5, 1, sub {push @a,1;},       "basic check 3 of leak test infrastructure");
 
+# Fatal warnings
+my $f = "use warnings FATAL =>";
+my $all = "$f 'all';";
+eleak(2, 0, "$f 'deprecated'; qq|\\c\{|", 'qq|\c{| with fatal warnings');
+eleak(2, 0, "$f 'syntax'; qq|\\c`|", 'qq|\c`| with fatal warnings');
+eleak(2, 0, "$all /\$\\ /", '/$\ / with fatal warnings');
+eleak(2, 0, "$all s//\\1/", 's//\1/ with fatal warnings');
+eleak(2, 0, "$all qq|\\i|", 'qq|\i| with fatal warnings');
+eleak(2, 0, "$f 'digit'; qq|\\o{9}|", 'qq|\o{9}| with fatal warnings');
+eleak(2, 0, "$f 'misc'; sub foo{} sub foo:lvalue",
+     'ignored :lvalue with fatal warnings');
+eleak(2, 0, "no warnings; use feature ':all'; $f 'misc';
+             my sub foo{} sub foo:lvalue",
+     'ignored mysub :lvalue with fatal warnings');
+eleak(2, 0, "no warnings; use feature ':all'; $all
+             my sub foo{} sub foo:lvalue{}",
+     'fatal mysub redef warning');
+eleak(2, 0, "$all sub foo{} sub foo{}", 'fatal sub redef warning');
+eleak(2, 0, "$all *x=sub {}",
+     'fatal sub redef warning with sub-to-glob assignment');
+eleak(2, 0, "$all *x=sub() {1}",
+     'fatal const sub redef warning with sub-to-glob assignment');
+$::TODO = 'still leaks';
+eleak(2, 0, "$all XS::APItest::newCONSTSUB(\\%main::=>name=>0=>1)",
+     'newXS sub redefinition with fatal warnings');
+eleak(2, 0, "$f 'misc'; my\$a,my\$a", 'double my with fatal warnings');
+eleak(2, 0, "$f 'misc'; our\$a,our\$a", 'double our with fatal warnings');
+eleak(2, 0, "$f 'closure';
+             sub foo { my \$x; format=\n\@\n\$x\n.\n} write; ",
+     'write beyond end of page with fatal warnings');
+eleak(2, 0, "$all /(?{})?/ ", '(?{})? with fatal warnings');
+eleak(2, 0, "$all /(?{})+/ ", '(?{})+ with fatal warnings');
+eleak(2, 0, "$all /[\\i]/ ", 'invalid charclass escape with fatal warns');
+eleak(2, 0, "$all /[:foo:]/ ", '/[:foo:]/ with fatal warnings');
+eleak(2, 0, "$all /[a-\\d]/ ", '[a-\d] char class with fatal warnings');
+eleak(2, 0, "$all v111111111111111111111111111111111111111111111111",
+     'vstring num overflow with fatal warnings');
+undef $::TODO;
+
 eleak(2, 0, 'sub{<*>}');
 
 eleak(2, 0, 'goto sub {}', 'goto &sub in eval');
@@ -147,6 +185,9 @@ SKIP:
   ok(!$weak, "hash referenced weakened SV released");
 }
 
+# prototype() errors
+leak(2,0, sub { eval { prototype "CORE::fu" } }, 'prototype errors');
+
 # RT #72246: rcatline memory leak on bad $/
 
 leak(2, 0,
@@ -182,27 +223,39 @@ eleak(2,0,'/[\xdf]/i');
 eleak(2,0,'s![^/]!!');
 eleak(2,0,'/[pp]/');
 eleak(2,0,'/[[:ascii:]]/');
+eleak(2,0,'/[[.zog.]]/');
+eleak(2,0,'/[.zog.]/');
+eleak(2,0,'chr(0x100) =~ /[[:punct:]]/');
+eleak(2,0,'chr(0x100) =~ /[[:^punct:]]/');
+eleak(2,0,'chr(0x100) =~ /\P{Assigned}/');
+leak(2,0,sub { /(??{})/ }, '/(??{})/');
 
 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');
+eleak(2, 0, 'no warnings; use feature ":all"; my sub a{1 1}',
+     'my sub with syntax error');
+
+# Reification (or lack thereof)
+leak(2, 0, sub { sub { local $_[0]; shift }->(1) },
+    'local $_[0] on surreal @_, followed by shift');
+leak(2, 0, sub { sub { local $_[0]; \@_ }->(1) },
+    'local $_[0] on surreal @_, followed by reification');
 
 # Syntax errors
 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//');
@@ -210,7 +263,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
@@ -218,10 +271,19 @@ eleak(2, !!$Config{mad}, 'no warnings; 2 2;BEGIN{}',
                 'implicit "use Errno" after syntax error');
 }
 eleak(2, 0, "\"\$\0\356\"", 'qq containing $ <null> something');
-{
-    local $::TODO = 'eval "END blah blah" still leaks';
-    eleak(2, 0, 'END OF TERMS AND CONDITIONS', 'END followed by words');
-}
+eleak(2, 0, 'END OF TERMS AND CONDITIONS', 'END followed by words');
+eleak(2, 0, "qq|\\c|;"x10,     '"too many errors" from qq"\c"');
+$::TODO = 'still leaks';
+eleak(2, 0, "qq|\\N{%}|"x10,   '"too many errors" from qq"\N{%}"');
+undef $::TODO;
+eleak(2, 0, "qq|\\o|;"x10,     '"too many errors" from qq"\o"');
+eleak(2, 0, "qq|\\x{|;"x10,    '"too many errors" from qq"\x{"');
+eleak(2, 0, "qq|\\N|;"x10,     '"too many errors" from qq"\N"');
+eleak(2, 0, "qq|\\N{|;"x10,    '"too many errors" from qq"\N{"');
+eleak(2, 0, "qq|\\N{U+GETG}|;"x10,'"too many errors" from qq"\N{U+JUNK}"');
+$::TODO = 'still leaks';
+eleak(2, 0, "qq|\\N{au}|;"x10, '"too many errors" from qq"\N{invalid}"');
+undef $::TODO;
 
 
 # [perl #114764] Attributes leak scalars
@@ -271,7 +333,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;
@@ -333,13 +395,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");
     }