diff options
author | Marty Pauley <marty@martian.org> | 2010-10-24 18:02:40 +0900 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-11-04 00:33:47 -0700 |
commit | 91e34d82e7dd2f0ba610299faa1af2efc8b404dc (patch) | |
tree | 6a53af64d2795a2a4ac46420bcc80b85fa1bdc39 /pp_hot.c | |
parent | 8897dcaad14089c32e969309beb16112ec768eaf (diff) | |
download | perl-91e34d82e7dd2f0ba610299faa1af2efc8b404dc.tar.gz |
fix for #23790.
padav is leaving an arrayref on the stack when producing the return value for an
lvalue sub. But when this is in an argument list it really should be a array,
not a ref. So, in leavesublv I check for this case and expand the arrayref to
an array.
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 23 |
1 files changed, 23 insertions, 0 deletions
@@ -2595,6 +2595,29 @@ PP(pp_leavesublv) if (gimme == G_SCALAR) goto temporise; if (gimme == G_ARRAY) { + mark = newsp + 1; + /* We want an array here, but padav will have left us an arrayref for an lvalue, + * so we need to expand it */ + if(SvTYPE(*mark) == SVt_PVAV) { + AV *const av = MUTABLE_AV(*mark); + const I32 maxarg = AvFILL(av) + 1; + (void)POPs; /* get rid of the array ref */ + EXTEND(SP, maxarg); + if (SvRMAGICAL(av)) { + U32 i; + for (i=0; i < (U32)maxarg; i++) { + SV ** const svp = av_fetch(av, i, FALSE); + SP[i+1] = svp + ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp + : &PL_sv_undef; + } + } + else { + Copy(AvARRAY(av), SP+1, maxarg, SV*); + } + SP += maxarg; + PUTBACK; + } if (!CvLVALUE(cx->blk_sub.cv)) goto temporise_array; EXTEND_MORTAL(SP - newsp); |