This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
op.c: S_lvref(): handle all kids on OP_NULL
authorDavid Mitchell <davem@iabyn.com>
Tue, 4 Jun 2019 12:33:22 +0000 (13:33 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 24 Jun 2019 10:40:07 +0000 (11:40 +0100)
For an OP_NULL, his function formerly recursed into *all* its kids
if was an ex-list, otherwise only the first one.

To simplify making this function non-recursive, make it so that it
unconditionally recurses into all the kids.

However for now, also add an assertion that a non ex-list OP_NULL
will only have one child at most. If we find some code which violates
this, then we can nmake a more informed decision as to whether
non ex-list OP_NULL's should have all, or only their first child
examined.

op.c

diff --git a/op.c b/op.c
index ded96dd..ee0cf81 100644 (file)
--- a/op.c
+++ b/op.c
@@ -4092,10 +4092,13 @@ S_lvref(pTHX_ OP *o, I32 type)
            goto badref;
        else if (!(o->op_flags & OPf_KIDS))
            return;
-       if (o->op_targ != OP_LIST) {
-           S_lvref(aTHX_ cBINOPo->op_first, type);
-           return;
-       }
+
+        /* the code formerly only recursed into the first child of
+         * a non ex-list OP_NULL. if we ever encounter such a null op with
+         * more than one child, need to decide whether its ok to process
+         * *all* its kids or not */
+        assert(o->op_targ == OP_LIST
+                || !(OpHAS_SIBLING(cBINOPo->op_first)));
        /* FALLTHROUGH */
     case OP_LIST:
        for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid)) {