This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regcomp.c: fix fencepost error in vFAIL at end of pattern
authorYves Orton <demerphq@gmail.com>
Mon, 22 Sep 2014 23:36:34 +0000 (01:36 +0200)
committerYves Orton <demerphq@gmail.com>
Thu, 25 Sep 2014 07:38:03 +0000 (09:38 +0200)
If RExC_parse was after RExC_end we passed a negative length
into the UTF8f macro/format, which then triggered asserts.

As part of this we add a new diagnostic to show when a
(?(condition)...) construct has gone unterminated, and tests for
the unterminated case, thus testing that vFAIL works properly
at the end of the string at the same time.

pod/perldiag.pod
regcomp.c
t/re/reg_mesg.t

index b29fff9..a49d23a 100644 (file)
@@ -5332,6 +5332,13 @@ it in clustering parentheses:
 The S<<-- HERE> shows whereabouts in the regular expression the problem
 was discovered.  See L<perlre>.
 
+=item Switch (?(condition)... not terminated in regex; marked by
+S<<-- HERE> in m/%s/
+
+(F) You ommitted to close a (?(condition)...) block somewhere in the
+pattern. Add a closing parenthesis in the appropriate position. See
+L<perlre>.
+
 =item Switch condition not recognized in regex; marked by S<<-- HERE> in
 m/%s/
 
index 3e8c42e..555cca1 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -495,7 +495,8 @@ static const scan_data_t zero_scan_data =
  * Simple_vFAIL -- like FAIL, but marks the current location in the scan
  */
 #define        Simple_vFAIL(m) STMT_START {                                    \
-    const IV offset = RExC_parse - RExC_precomp;                       \
+    const IV offset =                                                   \
+        (RExC_parse > RExC_end ? RExC_end : RExC_parse) - RExC_precomp; \
     Perl_croak(aTHX_ "%s" REPORT_LOCATION,                             \
            m, REPORT_LOCATION_ARGS(offset));   \
 } STMT_END
@@ -10145,8 +10146,12 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
                    }
                    else
                        lastbr = NULL;
-                   if (c != ')')
-                       vFAIL("Switch (?(condition)... contains too many branches");
+                    if (c != ')') {
+                        if (RExC_parse>RExC_end)
+                            vFAIL("Switch (?(condition)... not terminated");
+                        else
+                            vFAIL("Switch (?(condition)... contains too many branches");
+                    }
                    ender = reg_node(pRExC_state, TAIL);
                     REGTAIL(pRExC_state, br, ender);
                    if (lastbr) {
index 78be9ee..347234f 100644 (file)
@@ -94,6 +94,9 @@ my @death =
  '/(?(1x))/' => 'Switch condition not recognized {#} m/(?(1x{#}))/',
  '/(?(1x(?#)))/'=> 'Switch condition not recognized {#} m/(?(1x{#}(?#)))/',
 
+ '/(?(1)/'    => 'Switch (?(condition)... not terminated {#} m/(?(1){#}/',
+ '/(?(1)x/'    => 'Switch (?(condition)... not terminated {#} m/(?(1)x{#}/',
+ '/(?(1)x|y/'    => 'Switch (?(condition)... not terminated {#} m/(?(1)x|y{#}/',
  '/(?(1)x|y|z)/' => 'Switch (?(condition)... contains too many branches {#} m/(?(1)x|y|{#}z)/',
 
  '/(?(x)y|x)/' => 'Unknown switch condition (?(...)) {#} m/(?(x{#})y|x)/',