summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-09-06 00:17:05 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-09-06 06:18:08 -0700
commitdd2a7f9048da2c440a4dfed5122c0bfd98f079d3 (patch)
treec901bb9cb11796df795d97b5cf5c1914a2781aec /pp_hot.c
parent956f23f034b0a3aa7c521134b47f388252b9f843 (diff)
downloadperl-dd2a7f9048da2c440a4dfed5122c0bfd98f079d3.tar.gz
Use defelems for (goto) &xsub calls
Before ce0d59f: $ perl -e '++$#_; &utf8::encode' Modification of a read-only value attempted at -e line 1. As of ce0d59f: $ ./perl -Ilib -e '++$#_; &utf8::encode' Assertion failed: (sv), function Perl_sv_utf8_encode, file sv.c, line 3581. Abort trap: 6 Calling sub { utf8::encode($_[0]) } should be more or less equivalent to calling utf8::encode, but it is not in this case: $ ./perl -Ilib -we '++$#_; &{sub { utf8::encode($_[0]) }}' Use of uninitialized value in subroutine entry at -e line 1. In the first two examples above, an implementation detail is leaking through. What you are seeing is not the array element, but a place- holder that indicates an element that has not been assigned to yet. We should use defelem magic so that what the XSUB assigns to will cre- ate an array element (as happens with utf8::encode($_[0])). All of the above applies to goto &xsub as well.
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/pp_hot.c b/pp_hot.c
index be16eae5ba..3b96643b00 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2728,9 +2728,20 @@ try_autoload:
const I32 items = AvFILLp(av) + 1; /* @_ is not tieable */
if (items) {
+ SSize_t i = 0;
/* Mark is at the end of the stack. */
EXTEND(SP, items);
- Copy(AvARRAY(av), SP + 1, items, SV*);
+ for (; i < items; ++i)
+ if (AvARRAY(av)[i]) SP[i+1] = AvARRAY(av)[i];
+ else {
+ SV * const lv = sv_2mortal(newSV_type(SVt_PVLV));
+ SP[i+1] = lv;
+ LvTYPE(lv) = 'y';
+ sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0);
+ LvTARG(lv) = SvREFCNT_inc_simple_NN(av);
+ LvSTARGOFF(lv) = i;
+ LvTARGLEN(lv) = 1;
+ }
SP += items;
PUTBACK ;
}