diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-07-02 13:07:45 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-08-20 21:38:07 -0700 |
commit | ce0d59fdd1c7d145efdf6bf8da56a259fed483e4 (patch) | |
tree | 6d7ed09aaf3e1540bf3b408b343713dfe3da8b19 /pad.c | |
parent | 1a33a0598e4c684205d292afcb97de6d79d17e7d (diff) | |
download | perl-ce0d59fdd1c7d145efdf6bf8da56a259fed483e4.tar.gz |
[perl #7508] Use NULL for nonexistent array elems
This commit fixes bug #7508 and provides the groundwork for fixing
several other bugs.
Elements of @_ are aliased to the arguments, so that \$_[0] within
sub foo will reference the same scalar as \$x if the sub is called
as foo($x).
&PL_sv_undef (the global read-only undef scalar returned by the
‘undef’ operator itself) was being used to represent nonexistent
array elements. So the pattern would be broken for foo(undef), where
\$_[0] would vivify a new $_[0] element, treating it as having been
nonexistent.
This also causes other problems with constants under ithreads
(#105906) and causes a pending fix for another bug (#118691) to trig-
ger this bug.
This commit changes the internals to use a null pointer to represent a
nonexistent element.
This requires that Storable be changed to account for it. Also,
IPC::Open3 was relying on the bug. So this commit patches
both modules.
Diffstat (limited to 'pad.c')
-rw-r--r-- | pad.c | 30 |
1 files changed, 20 insertions, 10 deletions
@@ -285,6 +285,7 @@ Perl_pad_new(pTHX_ int flags) av_store(pad, 0, NULL); padname = newAV(); AvPAD_NAMELIST_on(padname); + av_store(padname, 0, &PL_sv_undef); } /* Most subroutines never recurse, hence only need 2 entries in the padlist @@ -1651,11 +1652,13 @@ Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust) PL_curpad[po] = newSV(0); SvPADTMP_on(PL_curpad[po]); #else - PL_curpad[po] = &PL_sv_undef; + PL_curpad[po] = NULL; #endif if (PadnamelistMAX(PL_comppad_name) != -1 && (PADOFFSET)PadnamelistMAX(PL_comppad_name) >= po) { - assert(!PadnameLEN(PadnamelistARRAY(PL_comppad_name)[po])); + if (PadnamelistARRAY(PL_comppad_name)[po]) { + assert(!PadnameLEN(PadnamelistARRAY(PL_comppad_name)[po])); + } PadnamelistARRAY(PL_comppad_name)[po] = &PL_sv_undef; } if ((I32)po < PL_padix) @@ -1767,21 +1770,23 @@ Perl_pad_tidy(pTHX_ padtidy_type type) av_store(PL_comppad_name, AvFILLp(PL_comppad), NULL); if (type == padtidy_SUBCLONE) { - SV * const * const namep = AvARRAY(PL_comppad_name); + SV ** const namep = AvARRAY(PL_comppad_name); PADOFFSET ix; for (ix = AvFILLp(PL_comppad); ix > 0; ix--) { SV *namesv; + if (!namep[ix]) namep[ix] = &PL_sv_undef; /* * The only things that a clonable function needs in its * pad are anonymous subs, constants and GVs. * The rest are created anew during cloning. */ - if (SvIMMORTAL(PL_curpad[ix]) || IS_PADGV(PL_curpad[ix])) + if (!PL_curpad[ix] || SvIMMORTAL(PL_curpad[ix]) + || IS_PADGV(PL_curpad[ix])) continue; - if (!((namesv = namep[ix]) != NULL && - PadnamePV(namesv) && + namesv = namep[ix]; + if (!(PadnamePV(namesv) && (!PadnameLEN(namesv) || *SvPVX_const(namesv) == '&'))) { SvREFCNT_dec(PL_curpad[ix]); @@ -1797,10 +1802,12 @@ Perl_pad_tidy(pTHX_ padtidy_type type) } if (type == padtidy_SUB || type == padtidy_FORMAT) { - SV * const * const namep = AvARRAY(PL_comppad_name); + SV ** const namep = AvARRAY(PL_comppad_name); PADOFFSET ix; for (ix = AvFILLp(PL_comppad); ix > 0; ix--) { - if (SvIMMORTAL(PL_curpad[ix]) || IS_PADGV(PL_curpad[ix]) || IS_PADCONST(PL_curpad[ix])) + if (!namep[ix]) namep[ix] = &PL_sv_undef; + if (!PL_curpad[ix] || SvIMMORTAL(PL_curpad[ix]) + || IS_PADGV(PL_curpad[ix]) || IS_PADCONST(PL_curpad[ix])) continue; if (!SvPADMY(PL_curpad[ix])) { SvPADTMP_on(PL_curpad[ix]); @@ -2417,7 +2424,8 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) for ( ;ix > 0; ix--) { if (!oldpad[ix]) { pad1a[ix] = NULL; - } else if (names_fill >= ix && PadnameLEN(names[ix])) { + } else if (names_fill >= ix && names[ix] && + PadnameLEN(names[ix])) { const char sigil = SvPVX_const(names[ix])[0]; if ((SvFLAGS(names[ix]) & SVf_FAKE) || (SvFLAGS(names[ix]) & SVpad_STATE) @@ -2446,7 +2454,9 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) } } } - else if (IS_PADGV(oldpad[ix]) || PadnamePV(names[ix])) { + else if (IS_PADGV(oldpad[ix]) + || ( names_fill >= ix && names[ix] + && PadnamePV(names[ix]) )) { pad1a[ix] = sv_dup_inc(oldpad[ix], param); } else { |