[perl #8262] //g loops infinitely on tainted data
Dave Mitchell [Mon, 19 Dec 2005 22:07:49 +0000 (22:07 +0000)]
make the LHS of expr =~ /foo/g an lvalue, so that any pos magic
attached to it stays attached.

p4raw-id: //depot/perl@26410

op.c
t/op/taint.t

diff --git a/op.c b/op.c
index 3dd0cdb..f757505 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1142,8 +1142,9 @@ Perl_mod(pTHX_ OP *o, I32 type)
        /* FALL THROUGH */
     default:
       nomod:
-       /* grep, foreach, subcalls, refgen */
-       if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN)
+       /* grep, foreach, subcalls, refgen, m//g */
+       if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN
+           || type == OP_MATCH)
            break;
        yyerror(Perl_form(aTHX_ "Can't modify %s in %s",
                     (o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL)
@@ -1822,9 +1823,14 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
     }
     if (!(right->op_flags & OPf_STACKED) && ismatchop) {
        right->op_flags |= OPf_STACKED;
-       if (right->op_type != OP_MATCH &&
-            ! (right->op_type == OP_TRANS &&
-               right->op_private & OPpTRANS_IDENTICAL))
+       /* s/// and tr/// modify their arg.
+        * m//g also indirectly modifies the arg by setting pos magic on it */
+       if (   (right->op_type == OP_MATCH &&
+                   (cPMOPx(right)->op_pmflags & PMf_GLOBAL))
+           || (right->op_type == OP_SUBST)
+           || (right->op_type == OP_TRANS &&
+               ! (right->op_private & OPpTRANS_IDENTICAL))
+       )
            left = mod(left, right->op_type);
        if (right->op_type == OP_TRANS)
            o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right);
index 7f9d06e..4aab737 100755 (executable)
@@ -17,7 +17,7 @@ use Config;
 use File::Spec::Functions;
 
 BEGIN { require './test.pl'; }
-plan tests => 244;
+plan tests => 245;
 
 
 $| = 1;
@@ -1135,3 +1135,17 @@ TERNARY_CONDITIONALS: {
     eval { local $0, eval '1' };
     test $@ eq '';
 }
+
+# [perl #8262] //g loops infinitely on tainted data
+
+{
+    my @a;
+    $a[0] = $^X;
+    my $i = 0;
+    while($a[0]=~ m/(.)/g ) {
+       last if $i++ > 10000;
+    }
+    test $i < 10000, "infinite m//g";
+    
+}
+