diff options
author | Nicholas Clark <nick@ccl4.org> | 2007-04-06 20:57:34 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2007-04-06 20:57:34 +0000 |
commit | bfd0ff222f043bea86c0b0e7700eeab47f675d46 (patch) | |
tree | 3ea80924df433dc9e2243fea34d250ec8a2dbae1 /op.c | |
parent | 5a4a8c8bd3ab61d27d13dfb8fcc36ee12afee389 (diff) | |
download | perl-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.c | 25 |
1 files changed, 24 insertions, 1 deletions
@@ -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) { |