develooper Front page | perl.perl5.porters | Postings from May 2001

Re: [ID 20010311.001] Regexp replaces using large replacement variables fail some of the time

Thread Previous | Thread Next
From:
Hugo
Date:
May 20, 2001 10:19
Subject:
Re: [ID 20010311.001] Regexp replaces using large replacement variables fail some of the time
Message ID:
200105201621.RAA26581@crypt.compulink.co.uk
In <E14c68i-0003Sq-00@majestica.igloo>, ian@lynagh.demon.co.uk writes:
:This is a bug report for perl from igloo@earth.li,
:generated with the help of perlbug 1.28 running under perl v5.6.0.
:
:-----------------------------------------------------------------
:
:If I execute
:
:($foo = "abcdefghijklmn") =~ s/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)/${13
:}/;
:print $foo;
:($foo = "abcdefghijklmn") =~ s/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)/${3}
:/;
:print $foo;
:($foo = "abcdefghijklmn") =~ s/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)/${13
:}/;
:print $foo;
:
:then I see "cm" rather than "mcm".

Testing this using:
  perl -wle '($_="aj")=~s/(((((((((a)))))))))(j)/${10}/ and print'
the problem seems to be in op.c:Perl_pmruntime(), which fails to spot that
there are variable references in a repl looking like this:
        {
7           TYPE = rv2sv  ===> 8
            FLAGS = (SCALAR,KIDS)
            {
                TYPE = scope  ===> (7)
                FLAGS = (SCALAR,KIDS)
                {
                    TYPE = null  ===> (6)
                      (was nextstate)
                    FLAGS = (VOID)
                }
                {
6                   TYPE = const  ===> 7
                    FLAGS = (SCALAR)
                    SV = IV(10)
                }
            }
        }
.. primarily, I think, because the optree walker:
            for (curop = LINKLIST(repl); curop!=repl; curop = LINKLIST(curop)) {
.. never sees the OP_RV2SV in this case.

As a result of this, the replacement is marked 'constant', and evaluated
before the regexp matching begins. I don't have enough understanding of
the optree walking done here to see what should happen, but the attached
patch does fix the problem without breaking any tests. I'm particularly
concerned about the second fragment of the op.c patch.

Hugo
--- op.c.old	Sat May 12 05:39:08 2001
+++ op.c	Sun May 20 17:17:24 2001
@@ -3060,13 +3060,16 @@
 			; /* Okay here, dangerous in newASSIGNOP */
 		    else
 			break;
+		} else if (curop->op_type == OP_SCOPE) {
+		    /* may be anything here, such as ${1} */
+		    repl_has_vars = 1;
 		}
 		lastop = curop;
 	    }
 	}
 	if (curop == repl
 	    && !(repl_has_vars
-		 && (!pm->op_pmregexp
+		 || (!pm->op_pmregexp
 		     || pm->op_pmregexp->reganch & ROPT_EVAL_SEEN))) {
 	    pm->op_pmflags |= PMf_CONST;	/* const for long enough */
 	    pm->op_pmpermflags |= PMf_CONST;	/* const for long enough */
--- t/op/subst.t.old	Mon Apr 30 13:24:34 2001
+++ t/op/subst.t	Sun May 20 17:15:03 2001
@@ -6,7 +6,7 @@
     require Config; import Config;
 }
 
-print "1..85\n";
+print "1..86\n";
 
 $x = 'foo';
 $_ = "x";
@@ -383,3 +383,7 @@
 s/\B\w//g;
 print $_ eq "C B" ? "ok 85\n" : "not ok 85\n# \$_ eq '$_'\n";
 
+$_ = "xy";
+ /(((((((((x)))))))))(z)/;	# clear $10
+s/(((((((((x)))))))))(y)/${10}/;
+print $_ eq "y" ? "ok 86\n" : "not ok 86\n# \$_ eq '$_'\n";

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About