This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Avoid accessing free()d memory when calling reset in one thread, after
[perl5.git] / op.c
diff --git a/op.c b/op.c
index b00164c..e0be444 100644 (file)
--- 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)
 {