This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix /a++(?{})+$code_block/
authorFather Chrysostomos <sprout@cpan.org>
Thu, 1 Nov 2012 21:49:35 +0000 (14:49 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 2 Nov 2012 01:10:00 +0000 (18:10 -0700)
This I would expect:

$ perl5.16.0 -wMre=eval -e '$x = "(?{})"; /a++(?{})+$x/x'
(?{})+ matches null string many times in regex; marked by <-- HERE in m/a++(?{})+ <-- HERE (?{})/ at -e line 1.
Use of uninitialized value $_ in pattern match (m//) at -e line 1.

It warns, but it still runs.

This I would not,

$ perl5.17.5 -wMre=eval -e '$x = "(?{})"; /a++(?{})+$x/x'
Nested quantifiers in regex; marked by <-- HERE in m/a++     + <-- HERE (?{})/ at (eval 1) line 1.

were it not for the fact that I know how it works. :-)

To compile the blocks in $x without recompiling the blocks directly
inside /.../, the regexp compiler blanks out the ‘outer’ blocks with
spaces, and compiles qr'a++     +(?{})'x.  But /x can see through
those spaces, resulting in a change in behaviour.  So use under-
scores instead.

regcomp.c
t/re/rxcode.t

index 3bd8475..4979b6a 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -5005,7 +5005,7 @@ S_has_runtime_code(pTHX_ RExC_state_t * const pRExC_state, OP *expr,
  *
  * becomes
  *
- *    qr'a\\bc                       def\'ghi\\\\jkl(?{"this is runtime"})mno'
+ *    qr'a\\bc_______________________def\'ghi\\\\jkl(?{"this is runtime"})mno'
  *
  * After eval_sv()-ing that, grab any new code blocks from the returned qr
  * and merge them with any code blocks of the original regexp.
@@ -5058,7 +5058,7 @@ S_compile_runtime_code(pTHX_ RExC_state_t * const pRExC_state,
                /* blank out literal code block */
                assert(pat[s] == '(');
                while (s <= pRExC_state->code_blocks[n].end) {
-                   *p++ = ' ';
+                   *p++ = '_';
                    s++;
                }
                s--;
index eb144f9..16bc4b7 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan tests => 38;
+plan tests => 39;
 
 $^R = undef;
 like( 'a',  qr/^a(?{1})(?:b(?{2}))?/, 'a =~ ab?' );
@@ -84,3 +84,10 @@ cmp_ok( scalar(@var), '==', 0, '..still nothing pushed (package)' );
     ok( 'abbb' =~ /^a(?{36})(?:b(?{37})|c(?{38}))+/, 'abbbb =~ a(?:b|c)+' );
     ok( $^R == 37, '$^R == 37' ) or print "# \$^R=$^R\n";
 }
+
+# Broken temporarily by the jumbo re-eval rewrite in 5.17.1; fixed in .6
+{
+    use re 'eval';
+    $x = "(?{})";
+    is eval { "a" =~ /a++(?{})+$x/x } || $@, '1', '/a++(?{})+$code_block/'
+}