diff options
author | Ruslan Zakirov <ruz@bestpractical.com> | 2012-10-23 20:04:37 +0400 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-10-25 20:02:55 -0700 |
commit | 33b889b0162a4f12e7c2a8d184afb63213130f07 (patch) | |
tree | c9be6100eb767fa7fc0139b86ebe421346e5c056 /t | |
parent | 1104029a0824d177415806f3d30cecd2c5c399a1 (diff) | |
download | perl-33b889b0162a4f12e7c2a8d184afb63213130f07.tar.gz |
test memory leaks around magic get dieing
Leaks happen when newSV is allocated, but then
copy operaton dies in get magic leaving not freed
scalar around.
Most of new tests check leaks in code path executing
sv_mortalcopy which has such problem. Two cases has
the same pattern, but don't use sv_mortalcopy. Can be
found with the following command:
grep -n -A3 'newSV\>' *.c | grep -B3 sv_set
Diffstat (limited to 't')
-rw-r--r-- | t/op/svleak.t | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/t/op/svleak.t b/t/op/svleak.t index 82d7e1650e..07d9125c67 100644 --- a/t/op/svleak.t +++ b/t/op/svleak.t @@ -15,7 +15,7 @@ BEGIN { use Config; -plan tests => 32; +plan tests => 37; # 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 @@ -200,21 +200,25 @@ leak(2, 0, sub { undef $h; }, 'tied hash iteration does not leak'); +package explosive_scalar { + sub TIESCALAR { my $self = shift; bless [undef, {@_}], $self } + sub FETCH { die 'FETCH' if $_[0][1]{FETCH}; $_[0][0] } + sub STORE { die 'STORE' if $_[0][1]{STORE}; $_[0][0] = $_[1] } +} +tie my $die_on_fetch, 'explosive_scalar', FETCH => 1; + # List assignment was leaking when assigning explosive scalars to # aggregates. -package sty { - sub TIESCALAR { bless [] } - sub FETCH { die } -} leak(2, 0, sub { - tie my $x, sty; - eval {%a = ($x, 0)}; # key - eval {%a = (0, $x)}; # value - eval {%a = ($x,$x)}; # both + eval {%a = ($die_on_fetch, 0)}; # key + eval {%a = (0, $die_on_fetch)}; # value + eval {%a = ($die_on_fetch, $die_on_fetch)}; # both }, 'hash assignment does not leak'); leak(2, 0, sub { - tie my $x, sty; - eval {@a = ($x)}; + eval {@a = ($die_on_fetch)}; + eval {($die_on_fetch, $b) = ($b, $die_on_fetch)}; + # restore + tie $die_on_fetch, 'explosive_scalar', FETCH => 1; }, 'array assignment does not leak'); # [perl #107000] @@ -236,3 +240,41 @@ leak(2,!!$Config{mad}, sub { { 1; } `; }, 'hint-hash copying does not leak'); + +package explosive_array { + sub TIEARRAY { bless [[], {}], $_[0] } + sub FETCH { die if $_[0]->[1]{FETCH}; $_[0]->[0][$_[1]] } + sub FETCHSIZE { die if $_[0]->[1]{FETCHSIZE}; scalar @{ $_[0]->[0] } } + sub STORE { die if $_[0]->[1]{STORE}; $_[0]->[0][$_[1]] = $_[2] } + sub CLEAR { die if $_[0]->[1]{CLEAR}; @{$_[0]->[0]} = () } + sub EXTEND { die if $_[0]->[1]{EXTEND}; return } + sub explode { my $self = shift; $self->[1] = {@_} } +} + +leak(2, 0, sub { + tie my @a, 'explosive_array'; + tied(@a)->explode( STORE => 1 ); + my $x = 0; + eval { @a = ($x) }; +}, 'explosive array assignment does not leak'); + +leak(2, 0, sub { + my ($a, $b); + eval { warn $die_on_fetch }; +}, 'explosive warn argument'); + +leak(2, 0, sub { + my $foo = sub { return $die_on_fetch }; + my $res = eval { $foo->() }; + my @res = eval { $foo->() }; +}, 'function returning explosive does not leak'); + +leak(2, 0, sub { + my $res = eval { {$die_on_fetch, 0} }; + $res = eval { {0, $die_on_fetch} }; +}, 'building anon hash with explosives does not leak'); + +leak(2, 0, sub { + my @a; + eval { push @a, $die_on_fetch }; +}, 'pushing exploding scalar does not leak'); |