summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2010-07-05 20:40:33 +0100
committerDavid Mitchell <davem@iabyn.com>2010-07-14 23:06:17 +0100
commit4c74a7df3242aa95d62dcfbcc231b8a55cc03c59 (patch)
tree40e1d5a912f0d7cfb9868075dda2ee1c5dcfcb7a /op.c
parente3d2b9e76ba8553f994404cc1438760e83dd8b76 (diff)
downloadperl-4c74a7df3242aa95d62dcfbcc231b8a55cc03c59.tar.gz
protect CvSTASH weakref with backrefs
Each CV usually has a pointer, CvSTASH, back to the stash that it was complied in. This pointer isn't reference counted, to avoid loops. Which can leave it dangling if the stash is deleted. There is already protection for the similar GvSTASH field in GVs: the stash has an array of backrefs, xhv_backreferences, pointing to the GVs whose GvSTASHes point to it, and which is used to zero all the GvSTASH fields should the stash be deleted. All this patch does is also add the CVs with CvSTASH to that stash's backref list too.
Diffstat (limited to 'op.c')
-rw-r--r--op.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/op.c b/op.c
index d832c997de..bd7b84bd36 100644
--- a/op.c
+++ b/op.c
@@ -5844,6 +5844,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
pad_fixup_inner_anons(CvPADLIST(cv), PL_compcv, cv);
if (PERLDB_INTER)/* Advice debugger on the new sub. */
++PL_sub_generation;
+ if (CvSTASH(cv))
+ sv_del_backref(MUTABLE_SV(CvSTASH(cv)), MUTABLE_SV(cv));
}
else {
/* Might have had built-in attributes applied -- propagate them. */
@@ -5872,6 +5874,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
CvGV(cv) = gv;
CvFILE_set_from_cop(cv, PL_curcop);
CvSTASH(cv) = PL_curstash;
+ if (PL_curstash)
+ Perl_sv_add_backref(aTHX_ MUTABLE_SV(PL_curstash), MUTABLE_SV(cv));
}
if (attrs) {
/* Need to do a C<use attributes $stash_of_cv,\&cv,@attrs>. */