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
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
}
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');
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,
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//');
'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
'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
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;
# 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");
}