summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2018-02-13 13:36:22 -0800
committerFather Chrysostomos <sprout@cpan.org>2018-02-18 16:25:42 -0800
commit7406cffe8ec122fcc2500115f8ed1742385893e1 (patch)
tree85cd52b856bf70d6a188cf3d1c166c38f15b5138
parentc46431c409d5cdb3c1c17c039a19e0e03356c7a6 (diff)
downloadperl-7406cffe8ec122fcc2500115f8ed1742385893e1.tar.gz
Fix two bugs when calling &xsub when @_ has holes
This fixes #132729 in the particular instance where an XSUB is called via ampersand syntax when @_ has ‘holes’, or nonexistent ele- ments, as in: @_ = (); $_[1] = 1; &xsub; This means that if the XSUB or something it calls unshifts @_, the first argument passed to the XSUB will now refer to $_[1], not $_[0]; i.e., as of this commit it is correctly shifted over. Previously, a ‘defelem’ was used, which is a magical scalar that remembers its index in the array, independent of whether the array was shifted. In addition, the old code failed to mortalize the defelem, so this commit fixes a memory leak with the new ‘non-elem’ mechanism (a spe- cially-marked element stored in the array itself).
-rw-r--r--ext/XS-APItest/APItest.xs7
-rw-r--r--pp_hot.c2
-rw-r--r--t/op/sub.t12
-rw-r--r--t/op/svleak.t6
4 files changed, 24 insertions, 3 deletions
diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs
index 4e5bf3cf1a..1fead70ee9 100644
--- a/ext/XS-APItest/APItest.xs
+++ b/ext/XS-APItest/APItest.xs
@@ -4398,6 +4398,13 @@ get_cv_flags(SV *sv, UV flags)
OUTPUT:
RETVAL
+void
+unshift_and_set_defav(SV *sv,...)
+ CODE:
+ av_unshift(GvAVn(PL_defgv), 1);
+ av_store(GvAV(PL_defgv), 0, newSVuv(42));
+ sv_setuv(sv, 43);
+
PerlIO *
PerlIO_stderr()
diff --git a/pp_hot.c b/pp_hot.c
index 9135e5d2d3..24c86e46fe 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -5215,7 +5215,7 @@ PP(pp_entersub)
else sv = AvARRAY(av)[i];
if (sv) SP[i+1] = sv;
else {
- SP[i+1] = newSVavdefelem(av, i, 1);
+ SP[i+1] = av_nonelem(av, i);
}
}
SP += items;
diff --git a/t/op/sub.t b/t/op/sub.t
index c8bf72d680..2b8ebcc463 100644
--- a/t/op/sub.t
+++ b/t/op/sub.t
@@ -6,7 +6,7 @@ BEGIN {
set_up_inc('../lib');
}
-plan(tests => 61);
+plan(tests => 62);
sub empty_sub {}
@@ -403,6 +403,16 @@ is ref($main::{rt_129916}), 'CODE', 'simple sub stored as CV in stash (main::)';
is ref($RT129916::{foo}), 'CODE', 'simple sub stored as CV in stash (non-main::)';
}
+# Calling xsub via ampersand syntax when @_ has holes
+SKIP: {
+ skip "no XS::APItest on miniperl" if is_miniperl;
+ require XS::APItest;
+ local *_;
+ $_[1] = 1;
+ &XS::APItest::unshift_and_set_defav;
+ is "@_", "42 43 1"
+}
+
# [perl #129090] Crashes and hangs
watchdog 10;
{ no warnings;
diff --git a/t/op/svleak.t b/t/op/svleak.t
index 59bd7d9d7f..05ae01f792 100644
--- a/t/op/svleak.t
+++ b/t/op/svleak.t
@@ -15,7 +15,7 @@ BEGIN {
use Config;
-plan tests => 147;
+plan tests => 148;
# 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
@@ -326,6 +326,10 @@ leak(2, 0, sub {
bless \&recredef, "Recursive::Redefinition"; eval "sub recredef{}"
}, 'recursive sub redefinition');
+# Sub calls
+leak(2, 0, sub { local *_; $_[1]=1; &re::regname },
+ 'passing sparse array to xsub via ampersand call');
+
# Syntax errors
eleak(2, 0, '"${<<END}"
', 'unterminated here-doc in quotes in multiline eval');