summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2017-07-25 14:36:28 +1000
committerTony Cook <tony@develop-help.com>2017-09-19 10:55:23 +1000
commit08ccc81012771c7ca6dc701881d86876ceb40e54 (patch)
tree2da35c0b4acc211651d1ae31c75dfc87a0ec5f05 /toke.c
parent570a6dbb8c57e331a0496105a6acdc1f06e03496 (diff)
downloadperl-08ccc81012771c7ca6dc701881d86876ceb40e54.tar.gz
(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.
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c37
1 files changed, 34 insertions, 3 deletions
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 ')':