summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-11-20 15:19:59 +0000
committerDavid Mitchell <davem@iabyn.com>2017-11-20 15:26:47 +0000
commit1a98acd9b14cfb3953d2b14eee2394454f92f0c8 (patch)
tree807379a5b20e24270946167bef8793d3027ada1e
parent326c4aeb76b24dfac855bc9662b5143d3a2dbdfe (diff)
downloadperl-1a98acd9b14cfb3953d2b14eee2394454f92f0c8.tar.gz
MULTICONCAT - use distinct TMPS for const overload
Because OP_MULTICONCAT optimises away any const SVs, they have to be recreated if a concat overload method is called. Up until now (for efficiency) the same SvTEMP was used to create each const TEMP. This caused problems if an overload method saved a ref to the argument. This is easily fixed by not reusing the TEMP (and the extra inefficiency is small compared to the overall burden of calling out to an overloaded method). With this patch, the following test code changes from getting "BB" to getting "AB": my @a; use overload '.' => sub { push @a, \$_[1]; $_[0] }; my $o = bless []; my $x = $o . "A" . $o . 'B'; is "${$a[0]}${$a[2]}", "AB", "RT #132385";
-rw-r--r--pp_hot.c15
-rw-r--r--t/op/concat2.t15
2 files changed, 16 insertions, 14 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 61f742f298..d1d02257ed 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1047,7 +1047,6 @@ PP(pp_multiconcat)
SV *left, *right, *res;
int i;
bool getmg = FALSE;
- SV *constsv = NULL;
/* number of args already concatted */
SSize_t n = (nargs - 1) - (toparg - SP);
/* current arg is either the first
@@ -1074,19 +1073,9 @@ PP(pp_multiconcat)
if ((SSize_t)len < 0)
continue;
- /* set constsv to the next constant string segment */
- if (constsv) {
- sv_setpvn(constsv, const_pv, len);
- if (dst_utf8)
- SvUTF8_on(constsv);
- else
- SvUTF8_off(constsv);
- }
- else
- constsv = newSVpvn_flags(const_pv, len,
+ /* set right to the next constant string segment */
+ right = newSVpvn_flags(const_pv, len,
(dst_utf8 | SVs_TEMP));
-
- right = constsv;
const_pv += len;
}
else {
diff --git a/t/op/concat2.t b/t/op/concat2.t
index cc2fa4f00b..8e962996eb 100644
--- a/t/op/concat2.t
+++ b/t/op/concat2.t
@@ -12,7 +12,7 @@ BEGIN {
set_up_inc('../lib');
}
-plan 2;
+plan 3;
# This test is in the file because overload.pm uses concatenation.
{ package o; use overload '""' => sub { $_[0][0] } }
@@ -23,6 +23,19 @@ $x.= chr 257;
$x.= chr 257;
is $x, "\xff\x{101}\x{101}", '.= is not confused by changing utf8ness';
+# RT #132385
+# in multiconcat, each const TEMP used for overloading should be distinct
+
+package RT132385 {
+ my @a;
+ use overload '.' => sub { push @a, \$_[1]; $_[0] };
+ my $o = bless [];
+ my $x = $o . "A" . $o . 'B';
+ ::is "${$a[0]}${$a[2]}", "AB", "RT #132385";
+}
+
+
+
# Ops should not share the same TARG between recursion levels. This may
# affect other ops, too, but concat seems more susceptible to this than
# others, since it can call itself recursively. (Where else would I put