summaryrefslogtreecommitdiff
path: root/pad.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-07-02 13:07:45 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-08-20 21:38:07 -0700
commitce0d59fdd1c7d145efdf6bf8da56a259fed483e4 (patch)
tree6d7ed09aaf3e1540bf3b408b343713dfe3da8b19 /pad.c
parent1a33a0598e4c684205d292afcb97de6d79d17e7d (diff)
downloadperl-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.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/pad.c b/pad.c
index d8d9322c60..92765f0f79 100644
--- a/pad.c
+++ b/pad.c
@@ -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 {