This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Don't use PL_check[op_type] to check for filetets ops to stack
authorDagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Tue, 21 May 2019 16:34:49 +0000 (17:34 +0100)
committerDagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Mon, 27 May 2019 16:30:34 +0000 (17:30 +0100)
This breaks hooking the filetest ops' check function by modules like
bareword::filehandles.  Instead use the OP_IS_FILETEST() macro to decide
check for filetest ops.  Also add an OP_IS_STAT() macro for when we want
to check for (l)stat as well as the filetest ops.

c.f. https://rt.cpan.org/Ticket/Display.html?id=127073

op.c
op.h
regen/opcodes

diff --git a/op.c b/op.c
index 29181ba..dba7ac7 100644 (file)
--- a/op.c
+++ b/op.c
@@ -991,8 +991,7 @@ Perl_op_clear(pTHX_ OP *o)
        o->op_targ = 0;
        break;
     default:
-       if (!(o->op_flags & OPf_REF)
-           || (PL_check[o->op_type] != Perl_ck_ftst))
+       if (!(o->op_flags & OPf_REF) || !OP_IS_STAT(o->op_type))
            break;
        /* FALLTHROUGH */
     case OP_GVSV:
@@ -4413,8 +4412,7 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
     /* [20011101.069 (#7861)] File test operators interpret OPf_REF to mean that
        their argument is a filehandle; thus \stat(".") should not set
        it. AMS 20011102 */
-    if (type == OP_REFGEN &&
-        PL_check[o->op_type] == Perl_ck_ftst)
+    if (type == OP_REFGEN && OP_IS_STAT(o->op_type))
         return o;
 
     if (type != OP_LEAVESUBLV)
@@ -11696,9 +11694,8 @@ Perl_ck_ftst(pTHX_ OP *o)
        scalar((OP *) kid);
        if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o->op_type))
            o->op_private |= OPpFT_ACCESS;
-       if (type != OP_STAT && type != OP_LSTAT
-            && PL_check[kidtype] == Perl_ck_ftst
-            && kidtype != OP_STAT && kidtype != OP_LSTAT
+       if (OP_IS_FILETEST(type)
+            && OP_IS_FILETEST(kidtype)
         ) {
            o->op_private |= OPpFT_STACKED;
            kid->op_private |= OPpFT_STACKING;
diff --git a/op.h b/op.h
index c9f05b2..ad6cf7f 100644 (file)
--- a/op.h
+++ b/op.h
@@ -1021,6 +1021,8 @@ C<sib> is non-null. For a higher-level interface, see C<L</op_sibling_splice>>.
 #define OP_TYPE_ISNT_AND_WASNT(o, type) \
     ( (o) && OP_TYPE_ISNT_AND_WASNT_NN(o, type) )
 
+/* should match anything that uses ck_ftst in regen/opcodes */
+#define OP_IS_STAT(op) (OP_IS_FILETEST(op) || (op) == OP_LSTAT || (op) == OP_STAT)
 
 #  define OpHAS_SIBLING(o)     (cBOOL((o)->op_moresib))
 #  define OpSIBLING(o)         (0 + (o)->op_moresib ? (o)->op_sibparent : NULL)
index b4bf904..4e82369 100644 (file)
@@ -397,6 +397,7 @@ getsockname getsockname             ck_fun          is%     Fs
 getpeername    getpeername             ck_fun          is%     Fs
 
 # Stat calls.  OP_IS_FILETEST wants them consecutive.
+# Also needs to match OP_IS_STAT() in op.h
 
 lstat          lstat                   ck_ftst         u-      F?
 stat           stat                    ck_ftst         u-      F?