summaryrefslogtreecommitdiff
path: root/lib/overload.t
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2019-02-05 13:48:21 +0000
committerDavid Mitchell <davem@iabyn.com>2019-02-05 14:03:05 +0000
commit4e521aaf3ed717774455b3906bd5aa46bc397319 (patch)
treed438e31c4fdfa0b4a01e34bf704f992dba2f49f2 /lib/overload.t
parent13874762cb298e7f922df49e6c78fd3f2308d860 (diff)
downloadperl-4e521aaf3ed717774455b3906bd5aa46bc397319.tar.gz
Avoid leak in multiconcat with overloading.
RT #133789 In the path taken through pp_multiconcat() when one or more args have side-effects such tieing or overloading, multiconcat has to decide whether to just return the result of all the concatting as-is, or to first assign it to an expression or variable if the op includes an implicit assign (such as $lex = x.y.z or $a[0] = x.y.z). The code was getting this right for those two cases, and was also getting it right for the append cases ($lex .= x.y.z and $a[0] .= x.y.z), which don't need assigns. But for the bare case (x.y.z) it was assigning to the op's targ as well as returning the value. Hence leaking a reference until destruction of the sub and its pad. This commit stops the assign in that last case.
Diffstat (limited to 'lib/overload.t')
-rw-r--r--lib/overload.t21
1 files changed, 20 insertions, 1 deletions
diff --git a/lib/overload.t b/lib/overload.t
index 055daab30f..5f2e0c2902 100644
--- a/lib/overload.t
+++ b/lib/overload.t
@@ -48,7 +48,7 @@ package main;
$| = 1;
BEGIN { require './test.pl'; require './charset_tools.pl' }
-plan tests => 5362;
+plan tests => 5363;
use Scalar::Util qw(tainted);
@@ -3174,3 +3174,22 @@ package Stringify {
::is $count, $stringify, $code;
}
}
+
+# RT #133789: in multiconcat with overload, the overloaded ref returned
+# from the overload method was being assigned to the pad targ, causing
+# a delay to the freeing of the object
+
+package RT33789 {
+ use overload
+ '.' => sub { $_[0] }
+ ;
+
+ my $destroy = 0;
+ sub DESTROY { $destroy++ }
+
+ {
+ my $o = bless [];
+ my $result = '1' . ( '2' . ( '3' . ( '4' . ( '5' . $o ) ) ) );
+ }
+ ::is($destroy, 1, "RT #133789: delayed destroy");
+}