Fatalize some uses of unescaped '{' in patterns
authorKarl Williamson <khw@cpan.org>
Sat, 14 Jul 2018 19:50:41 +0000 (13:50 -0600)
committerKarl Williamson <khw@cpan.org>
Sun, 15 Jul 2018 00:15:06 +0000 (18:15 -0600)
This commit follows through with our schedule of making some unescaped
literal left brace usages fatal in 5.30.  Some contexts won't be made
fatal until 5.32, and, in a partial change of plan,  others won't be
made fatal at all.

The goal since before 5.20 is to allow things like \w{foo} to be added
to the language, where the 'w' could be any suitable alphabetic.
This has already been accomplished with \b, \B (for example \b{wb}).
But various impediments have prevented generalizing this.

Another goal is to make the general quantifier, X{a,b}, syntax not so
restrictive, so that spaces can be used within the braces, and the lower
bound could be omitted.

This commit is another step towards allowing this.

Uses of some contexts have been scheduled to be made fatal in 5.30.  But
a discussion I had with Peter Rabbitson at TPC persuaded me to narrow
those contexts to the ones that we actually really need.  This commit
changes those to fatal, and the others where we had previously raised a
deprecation message are changed into a non-deprecation warning.  Keeping
this as a warning prevents a construct, where the user had intended a
quantifier but made a typo, from silently being compiled into a literal
string.

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

index a41f2c6..5efcbe9 100644 (file)
@@ -106,7 +106,7 @@ Literal uses of C<{> were deprecated in Perl 5.20, and some uses of it
 started to give deprecation warnings since. These cases were made fatal
 in Perl 5.26. Due to an oversight, not all cases of a use of a literal
 C<{> got a deprecation warning.  Some cases started warning in Perl 5.26,
-and they will be fatal by Perl 5.30.  Other case started in Perl 5.28,
+and were made fatal in Perl 5.30.  Other case started in Perl 5.28,
 and will be made fatal in 5.32.
 
 =head2 Perl 5.30
index a200626..2c1fe74 100644 (file)
@@ -6419,7 +6419,65 @@ C<undef *foo>.
 (A) You've accidentally run your script through B<csh> instead of Perl.
 Check the #! line, or manually feed your script into Perl yourself.
 
-=item Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through in regex; marked by S<<-- HERE> in m/%s/
+=item Unescaped left brace in regex is passed through in regex; marked by S<<-- HERE> in m/%s/
+
+(W regexp)  The simple rule to remember, if you want to
+match a literal C<"{"> character (U+007B C<LEFT CURLY BRACKET>) in a
+regular expression pattern, is to escape each literal instance of it in
+some way.  Generally easiest is to precede it with a backslash, like
+C<"\{"> or enclose it in square brackets (C<"[{]">).  If the pattern
+delimiters are also braces, any matching right brace (C<"}">) should
+also be escaped to avoid confusing the parser, for example,
+
+ qr{abc\{def\}ghi}
+
+Forcing literal C<"{"> characters to be escaped will enable the Perl
+language to be extended in various ways in future releases.  To avoid
+needlessly breaking existing code, the restriction is is not enforced in
+contexts where there are unlikely to ever be extensions that could
+conflict with the use there of C<"{"> as a literal.  Those that are
+not potentially ambiguous do not warn; those that are do raise a
+non-deprecation warning.
+
+In this release of Perl, some literal uses of C<"{"> are fatal, and some
+still just deprecated.  This is because of an oversight:  some uses of a
+literal C<"{"> that should have raised a deprecation warning starting in
+v5.20 did not warn until v5.26.  By making the already-warned uses fatal
+now, some of the planned extensions can be made to the language sooner.
+The cases which are still allowed will be fatal in Perl 5.32.
+
+The contexts where no warnings or errors are raised are:
+
+=over 4
+
+=item *
+
+as the first character in a pattern, or following C<"^"> indicating to
+anchor the match to the beginning of a line.
+
+=item *
+
+as the first character following a C<"|"> indicating alternation.
+
+=item *
+
+as the first character in a parenthesized grouping like
+
+ /foo({bar)/
+ /foo(?:{bar)/
+
+=item *
+
+as the first character following a quantifier
+
+ /\s*{/
+
+=back
+
+=for comment
+The text of the message above is duplicated below to allow splain (and
+'use diagnostics') to work.  Since one is deprecated, and one not, khw
+thinks they can't be combined as one message.
 
 =item Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.32), passed through in regex; marked by S<<-- HERE> in m/%s/
 
@@ -6437,14 +6495,16 @@ Forcing literal C<"{"> characters to be escaped will enable the Perl
 language to be extended in various ways in future releases.  To avoid
 needlessly breaking existing code, the restriction is is not enforced in
 contexts where there are unlikely to ever be extensions that could
-conflict with the use there of C<"{"> as a literal.
+conflict with the use there of C<"{"> as a literal.  Those that are
+not potentially ambiguous do not warn; those that are do raise a
+non-deprecation warning.
 
 In this release of Perl, some literal uses of C<"{"> are fatal, and some
 still just deprecated.  This is because of an oversight:  some uses of a
 literal C<"{"> that should have raised a deprecation warning starting in
 v5.20 did not warn until v5.26.  By making the already-warned uses fatal
 now, some of the planned extensions can be made to the language sooner.
-The cases which are still allowed will be fatal in Perl 5.30 or 5.32.
+The cases which are still allowed will be fatal in Perl 5.32.
 
 The contexts where no warnings or errors are raised are:
 
@@ -6477,8 +6537,8 @@ as the first character following a quantifier
 =for comment
 The text of the message above is duplicated below to allow splain (and
 'use diagnostics') to work.  Since one is fatal, and one not, they can't
-be combined as one message.  And since the non-fatal one is temporary,
-there's no real need to enhance perldiag to handle this transient case.
+be combined as one message.  Perhaps perldiag could be enhanced to
+handle this case.
 
 =item Unescaped left brace in regex is illegal here in regex;
 marked by S<<-- HERE> in m/%s/
@@ -6497,13 +6557,16 @@ Forcing literal C<"{"> characters to be escaped will enable the Perl
 language to be extended in various ways in future releases.  To avoid
 needlessly breaking existing code, the restriction is is not enforced in
 contexts where there are unlikely to ever be extensions that could
-conflict with the use there of C<"{"> as a literal.
+conflict with the use there of C<"{"> as a literal.  Those that are
+not potentially ambiguous do not warn; those that are do raise a
+non-deprecation warning.
 
 In this release of Perl, some literal uses of C<"{"> are fatal, and some
 still just deprecated.  This is because of an oversight:  some uses of a
 literal C<"{"> that should have raised a deprecation warning starting in
 v5.20 did not warn until v5.26.  By making the already-warned uses fatal
 now, some of the planned extensions can be made to the language sooner.
+The cases which are still allowed will be fatal in Perl 5.32.
 
 The contexts where no warnings or errors are raised are:
 
index d416d23..17feb37 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -13787,20 +13787,22 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
                    } /* End of switch on '\' */
                    break;
                case '{':
-                    /* Currently we allow an lbrace at the start of a construct
-                     * without raising a warning.  This is because we think we
-                     * will never want such a brace to be meant to be other
-                     * than taken literally. */
+                    /* Trying to gain new uses for '{' without breaking too
+                     * much existing code is hard.  The solution currently
+                     * adopted is:
+                     *  1)  If there is no ambiguity that a '{' should always
+                     *      be taken literally, at the start of a construct, we
+                     *      just do so.
+                     *  2)  If the literal '{' conflicts with our desired use
+                     *      of it as a metacharacter, we die.  The deprecation
+                     *      cycles for this have come and gone.
+                     *  3)  If there is ambiguity, we raise a simple warning.
+                     *      This could happen, for example, if the user
+                     *      intended it to introduce a quantifier, but slightly
+                     *      misspelled the quantifier.  Without this warning,
+                     *      the quantifier would silently be taken as a literal
+                     *      string of characters instead of a meta construct */
                    if (len || (p > RExC_start && isALPHA_A(*(p - 1)))) {
-
-                        /* But, we raise a fatal warning otherwise, as the
-                         * deprecation cycle has come and gone.  Except that it
-                         * turns out that some heavily-relied on upstream
-                         * software, notably GNU Autoconf, have failed to fix
-                         * their uses.  For these, don't make it fatal unless
-                         * we anticipate using the '{' for something else.
-                         * This happens after any alpha, and for a looser {m,n}
-                         * quantifier specification */
                         if (      RExC_strict
                             || (  p > parse_start + 1
                                 && isALPHA_A(*(p - 1))
@@ -13812,10 +13814,8 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
                                   "illegal here");
                         }
                         if (PASS2) {
-                            ckWARNregdep(p + 1,
-                                        "Unescaped left brace in regex is "
-                                        "deprecated here (and will be fatal "
-                                        "in Perl 5.30), passed through");
+                            ckWARNreg(p + 1, "Unescaped left brace in regex is"
+                                             " passed through");
                         }
                    }
                    goto normal_default;
@@ -14324,8 +14324,15 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
     /* Position parse to next real character */
     skip_to_be_ignored_text(pRExC_state, &RExC_parse,
                                             FALSE /* Don't force to /x */ );
-    if (PASS2 && *RExC_parse == '{' && OP(ret) != SBOL && ! regcurly(RExC_parse)) {
-        ckWARNregdep(RExC_parse + 1, "Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through");
+    if (   PASS2 && *RExC_parse == '{'
+        && OP(ret) != SBOL && ! regcurly(RExC_parse))
+    {
+        if (RExC_strict || new_regcurly(RExC_parse, RExC_end)) {
+            RExC_parse++;
+            vFAIL("Unescaped left brace in regex is illegal here");
+        }
+        ckWARNreg(RExC_parse + 1, "Unescaped left brace in regex is"
+                                  " passed through");
     }
 
     return(ret);
index 5fb1f1a..3ab9a69 100644 (file)
@@ -305,6 +305,9 @@ my @death =
  '/\w{/' => 'Unescaped left brace in regex is illegal here {#} m/\w{{#}/',
  '/\q{/' => 'Unescaped left brace in regex is illegal here {#} m/\q{{#}/',
  '/\A{/' => 'Unescaped left brace in regex is illegal here {#} m/\A{{#}/',
+ '/.{, 4 }/' => 'Unescaped left brace in regex is illegal here {#} m/.{{#}, 4 }/',
+ '/[x]{, 4}/'       => 'Unescaped left brace in regex is illegal here {#} m/[x]{{#}, 4}/',
+ '/\p{Latin}{,4 }/' => 'Unescaped left brace in regex is illegal here {#} m/\p{Latin}{{#},4 }/',
  '/(?<=/' => 'Sequence (?... not terminated {#} m/(?<={#}/',                        # [perl #128170]
  '/\p{vertical \v tab}/' => 'Can\'t find Unicode property definition "vertical \v tab" {#} m/\\p{vertical \v tab}{#}/', # [perl #132055]
 
@@ -389,14 +392,20 @@ my @death_only_under_strict = (
                                      => 'False [] range "[:digit:]-" {#} m/[[:digit:]-{#}[:alpha:]]\x{100}/',
     '/[a\zb]\x{100}/' => 'Unrecognized escape \z in character class passed through {#} m/[a\z{#}b]\x{100}/',
                       => 'Unrecognized escape \z in character class {#} m/[a\z{#}b]\x{100}/',
-    'default_on/:{4,a}/'     => 'Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through {#} m/:{{#}4,a}/',
-                             => 'Unescaped left brace in regex is illegal here {#} m/:{{#}4,a}/',
-    'default_on/xa{3\,4}y/'  => 'Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through {#} m/xa{{#}3\,4}y/',
-                             => 'Unescaped left brace in regex is illegal here {#} m/xa{{#}3\,4}y/',
-  'default_on/\\${[^\\}]*}/' => 'Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through {#} m/\\${{#}[^\\}]*}/',
-                             => 'Unescaped left brace in regex is illegal here {#} m/\\${{#}[^\\}]*}/',
     '/[a\fb]/'          => "",
                         => 'Literal vertical space in [] is illegal except under /x {#} m/[a\f{#}b]/',
+    '/:{4,a}/'     => 'Unescaped left brace in regex is passed through {#} m/:{{#}4,a}/',
+                   => 'Unescaped left brace in regex is illegal here {#} m/:{{#}4,a}/',
+    '/xa{3\,4}y/'  => 'Unescaped left brace in regex is passed through {#} m/xa{{#}3\,4}y/',
+                   => 'Unescaped left brace in regex is illegal here {#} m/xa{{#}3\,4}y/',
+    '/\\${[^\\}]*}/' => 'Unescaped left brace in regex is passed through {#} m/\\${{#}[^\\}]*}/',
+                     => 'Unescaped left brace in regex is illegal here {#} m/\\${{#}[^\\}]*}/',
+    '/.{/'         => 'Unescaped left brace in regex is passed through {#} m/.{{#}/',
+                   => 'Unescaped left brace in regex is illegal here {#} m/.{{#}/',
+    '/[x]{/'       => 'Unescaped left brace in regex is passed through {#} m/[x]{{#}/',
+                   => 'Unescaped left brace in regex is illegal here {#} m/[x]{{#}/',
+    '/\p{Latin}{/' => 'Unescaped left brace in regex is passed through {#} m/\p{Latin}{{#}/',
+                   => 'Unescaped left brace in regex is illegal here {#} m/\p{Latin}{{#}/',
 );
 
 # These need the character 'ネ' as a marker for mark_as_utf8()
@@ -690,9 +699,6 @@ my @deprecated = (
  '/foo(:?{bar)/' => "",
  '/\s*{/'        => "",
  '/a{3,4}{/'     => "",
- '/.{/'         => 'Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through {#} m/.{{#}/',
- '/[x]{/'       => 'Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through {#} m/[x]{{#}/',
- '/\p{Latin}{/' => 'Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through {#} m/\p{Latin}{{#}/',
 );
 
 for my $strict ("", "use re 'strict';") {