From: Dave Mitchell Date: Mon, 19 Dec 2005 22:07:49 +0000 (+0000) Subject: [perl #8262] //g loops infinitely on tainted data X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e26a497577f3ce7b9a4d9e1e62062839554dfd8f;p=p5sagit%2Fp5-mst-13.2.git [perl #8262] //g loops infinitely on tainted data make the LHS of expr =~ /foo/g an lvalue, so that any pos magic attached to it stays attached. p4raw-id: //depot/perl@26410 --- diff --git a/op.c b/op.c index 3dd0cdb..f757505 100644 --- 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); diff --git a/t/op/taint.t b/t/op/taint.t index 7f9d06e..4aab737 100755 --- a/t/op/taint.t +++ b/t/op/taint.t @@ -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"; + +} +