summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2007-04-06 20:57:34 +0000
committerNicholas Clark <nick@ccl4.org>2007-04-06 20:57:34 +0000
commitbfd0ff222f043bea86c0b0e7700eeab47f675d46 (patch)
tree3ea80924df433dc9e2243fea34d250ec8a2dbae1 /op.c
parent5a4a8c8bd3ab61d27d13dfb8fcc36ee12afee389 (diff)
downloadperl-bfd0ff222f043bea86c0b0e7700eeab47f675d46.tar.gz
Avoid accessing free()d memory when calling reset in one thread, after
deleting pattern match ops in another thread. p4raw-id: //depot/perl@30856
Diffstat (limited to 'op.c')
-rw-r--r--op.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/op.c b/op.c
index b00164cf18..e0be444912 100644
--- a/op.c
+++ b/op.c
@@ -428,9 +428,13 @@ Perl_op_free(pTHX_ OP *o)
OP_REFCNT_LOCK;
refcnt = OpREFCNT_dec(o);
OP_REFCNT_UNLOCK;
- if (refcnt)
+ if (refcnt) {
+ /* Need to find and remove any pattern match ops from the list
+ we maintain for reset(). */
+ find_and_forget_pmops(o);
return;
}
+ }
break;
default:
break;
@@ -652,6 +656,25 @@ S_forget_pmop(pTHX_ PMOP *const o, U32 flags)
PmopSTASH_free(o);
}
+STATIC void
+S_find_and_forget_pmops(pTHX_ OP *o)
+{
+ if (o->op_flags & OPf_KIDS) {
+ OP *kid = cUNOPo->op_first;
+ while (kid) {
+ switch (kid->op_type) {
+ case OP_SUBST:
+ case OP_PUSHRE:
+ case OP_MATCH:
+ case OP_QR:
+ forget_pmop((PMOP*)kid, 0);
+ }
+ find_and_forget_pmops(kid);
+ kid = kid->op_sibling;
+ }
+ }
+}
+
void
Perl_op_null(pTHX_ OP *o)
{