summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2005-12-31 13:16:06 +0000
committerNicholas Clark <nick@ccl4.org>2005-12-31 13:16:06 +0000
commit1b8791d118104352beb2148b6b5cd8c57952ebb2 (patch)
tree7a53d257e2ec56659fa4108f89bb8f0f2d0aeb9b /hv.c
parent67eb4d3079ea11b2f1cbc84fe9afb351bc67715a (diff)
downloadperl-1b8791d118104352beb2148b6b5cd8c57952ebb2.tar.gz
Stop 'sub a { // }; %::=()' panicing because the backreference array
became lost. p4raw-id: //depot/perl@26546
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/hv.c b/hv.c
index 27c4becc3a..c90fbb20c7 100644
--- a/hv.c
+++ b/hv.c
@@ -1652,6 +1652,7 @@ S_hfreeentries(pTHX_ HV *hv)
I32 riter;
I32 max;
struct xpvhv_aux *iter;
+ AV *new_backrefs = NULL;
if (!HvARRAY(hv))
return;
@@ -1670,6 +1671,7 @@ S_hfreeentries(pTHX_ HV *hv)
if (AvFILLp(iter->xhv_backreferences) == -1) {
/* Turns out that the array is empty. Just free it. */
SvREFCNT_dec(iter->xhv_backreferences);
+
} else {
sv_magic((SV*)hv, (SV*)iter->xhv_backreferences,
PERL_MAGIC_backref, NULL, 0);
@@ -1708,8 +1710,21 @@ S_hfreeentries(pTHX_ HV *hv)
the array set to 0. */
assert(HvARRAY(hv));
- if (HvAUX(hv)->xhv_name)
+ if(HvAUX(hv)->xhv_backreferences) {
+ if (iter) {
+ /* Erk. They caused the backreference AV to be put back
+ into the hash aux structure */
+ assert (!iter->xhv_backreferences);
+ iter->xhv_backreferences = HvAUX(hv)->xhv_backreferences;
+ } else {
+ /* Erk. They created a backreference array when there was none
+ before. */
+ new_backrefs = HvAUX(hv)->xhv_backreferences;
+ }
+ }
+ if (HvAUX(hv)->xhv_name) {
unshare_hek_or_pvn(HvAUX(hv)->xhv_name, 0, 0, 0);
+ }
/* SvOOK_off calls sv_backoff, which isn't correct. */
Safefree(HvARRAY(hv));
@@ -1731,6 +1746,11 @@ S_hfreeentries(pTHX_ HV *hv)
}
HvARRAY(hv) = array;
+
+ if (new_backrefs) {
+ /* Don't lose the backreferences array */
+ *Perl_hv_backreferences_p(aTHX_ hv) = new_backrefs;
+ }
}
/*