In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/08ccc81012771c7ca6dc701881d86876ceb40e54?hp=570a6dbb8c57e331a0496105a6acdc1f06e03496>

- Log -----------------------------------------------------------------
commit 08ccc81012771c7ca6dc701881d86876ceb40e54
Author: Tony Cook <t...@develop-help.com>
Date:   Tue Jul 25 14:36:28 2017 +1000

    (perl #131777) prevent non-'=' assign ops tokens in sub signatures
    
    The yacc grammar introduced in d3d9da4a7 uses ASSIGNOP to
    represent the '=' used to introduce default values in subroutine
    signatures, unfortunately the parser returns ASSIGNOP for non-simple
    assignments, which allowed:
    
      sub foo ($x += 1) { ... }
    
    to default $x to 1.
    
    Modify yylex to accept only the simple assignment operator after a
    subroutine parameter.
    
    I'm not especially happy with the error recovery here.
-----------------------------------------------------------------------

Summary of changes:
 pod/perldiag.pod  | 11 +++++++++++
 t/lib/croak/toke  |  9 +++++++++
 t/op/signatures.t | 16 ++++++++++------
 toke.c            | 37 ++++++++++++++++++++++++++++++++++---
 4 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 689e9609bc..d417fb296e 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -2652,6 +2652,17 @@ this error when Perl was built using standard options.  
For some
 reason, your version of Perl appears to have been built without
 this support.  Talk to your Perl administrator.
 
+=item Illegal operator following parameter in a subroutine signature
+
+(F) A parameter in a subroutine signature, was followed by something
+other than C<=> introducing a default, C<,> or C<)>.
+
+    use feature 'signatures';
+    sub foo ($=1) {}           # legal
+    sub foo ($a = 1) {}        # legal
+    sub foo ($a += 1) {}       # illegal
+    sub foo ($a == 1) {}       # illegal
+
 =item Illegal character following sigil in a subroutine signature
 
 (F) A parameter in a subroutine signature contained an unexpected character
diff --git a/t/lib/croak/toke b/t/lib/croak/toke
index c477be0336..87d958020a 100644
--- a/t/lib/croak/toke
+++ b/t/lib/croak/toke
@@ -404,3 +404,12 @@ Number found where operator expected at - line 1, near 
"--5"
        (Missing operator before 5?)
 syntax error at - line 1, near "1e"
 Execution of - aborted due to compilation errors.
+########
+# NAME signature with non-"=" assignop #131777
+use feature 'signatures';
+no warnings 'experimental::signatures';
+sub foo ($a += 1)
+EXPECT
+Illegal operator following parameter in a subroutine signature at - line 3, 
near "($a += 1"
+syntax error at - line 3, near "($a += 1"
+Execution of - aborted due to compilation errors.
diff --git a/t/op/signatures.t b/t/op/signatures.t
index f0e1b93353..8ab8db3761 100644
--- a/t/op/signatures.t
+++ b/t/op/signatures.t
@@ -1095,17 +1095,21 @@ syntax error at foo line 8, near ", 123"
 EOF
 
 eval "#line 8 foo\nno warnings; sub t096 (\$a 123) { }";
-is $@, qq{syntax error at foo line 8, near "\$a 123"\n};
+is $@, <<'EOF';
+Illegal operator following parameter in a subroutine signature at foo line 8, 
near "($a 123"
+syntax error at foo line 8, near "($a 123"
+EOF
 
 eval "#line 8 foo\nsub t097 (\$a { }) { }";
-is $@, <<EOF;
-syntax error at foo line 8, near "\$a { "
+is $@, <<'EOF';
+Illegal operator following parameter in a subroutine signature at foo line 8, 
near "($a { }"
+syntax error at foo line 8, near "($a { }"
 EOF
 
 eval "#line 8 foo\nsub t098 (\$a; \$b) { }";
-is $@, <<EOF;
-syntax error at foo line 8, at EOF
-syntax error at foo line 8, near "\$b) "
+is $@, <<'EOF';
+Illegal operator following parameter in a subroutine signature at foo line 8, 
near "($a; "
+syntax error at foo line 8, near "($a; "
 EOF
 
 eval "#line 8 foo\nsub t099 (\$\$) { }";
diff --git a/toke.c b/toke.c
index 8b5f8628d5..a91a4fcfbe 100644
--- a/toke.c
+++ b/toke.c
@@ -5125,12 +5125,43 @@ Perl_yylex(pTHX)
                     0, cBOOL(UTF), FALSE);
                 *dest = '\0';
                 assert(PL_tokenbuf[1]); /* we have a variable name */
+            }
+            else {
+                *PL_tokenbuf = 0;
+                PL_in_my = 0;
+            }
+
+            s = skipspace(s);
+            /* parse the = for the default ourselves to avoid '+=' etc being 
accepted here
+             * as the ASSIGNOP, and exclude other tokens that start with =
+             */
+            if (*s == '=' && (!s[1] || strchr("=~>", s[1]) == 0)) {
+                /* save now to report with the same context as we did when
+                 * all ASSIGNOPS were accepted */
+                PL_oldbufptr = s;
+
+                ++s;
+                NEXTVAL_NEXTTOKE.ival = 0;
+                force_next(ASSIGNOP);
+                PL_expect = XTERM;
+            }
+            else if (*s == ',' || *s == ')') {
+                PL_expect = XOPERATOR;
+            }
+            else {
+                /* make sure the context shows the unexpected character and
+                 * hopefully a bit more */
+                if (*s) ++s;
+                while (*s && *s != '$' && *s != '@' && *s != '%' && *s != ')')
+                    s++;
+                PL_bufptr = s; /* for error reporting */
+                yyerror("Illegal operator following parameter in a subroutine 
signature");
+                PL_in_my = 0;
+            }
+            if (*PL_tokenbuf) {
                 NEXTVAL_NEXTTOKE.ival = sigil;
                 force_next('p'); /* force a signature pending identifier */
             }
-            else
-                PL_in_my = 0;
-            PL_expect = XOPERATOR;
             break;
 
         case ')':

--
Perl5 Master Repository

Reply via email to