This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #123737] Fix assertion failure with 0${
authorFather Chrysostomos <sprout@cpan.org>
Fri, 6 Feb 2015 16:25:14 +0000 (08:25 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 6 Feb 2015 17:14:21 +0000 (09:14 -0800)
S_no_op, which displays ‘Foo found where operator expected’, assumes
that PL_bufptr points to the beginning of the token, but that was not
the case for ${ at the end of a line.  The attempt to read more into
the buffer would make PL_bufptr point to the end of the line.  This
meant it would use a negative string length when generating the
‘(Missing operator before foo?)’ text, only accidentally escaping a
crash.  On debugging builds, it failed an assertion.

t/lib/croak/toke
toke.c

index 57f3790..a5e02af 100644 (file)
@@ -19,6 +19,15 @@ Number found where operator expected at - line 4, near "myfunc 1"
 syntax error at - line 4, near "myfunc 1"
 Execution of - aborted due to compilation errors.
 ########
+# NAME (Missing operator before ${?) [perl #123737]
+0${
+EXPECT
+Scalar found where operator expected at - line 1, near "0${"
+       (Missing operator before ${?)
+syntax error at - line 1, near "0$"
+Missing right curly or square bracket at - line 1, at end of line
+Execution of - aborted due to compilation errors.
+########
 # NAME Unterminated here-doc in string eval
 eval "<<foo"; die $@
 EXPECT
diff --git a/toke.c b/toke.c
index 5373510..cb411d4 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -503,6 +503,9 @@ S_ao(pTHX_ int toketype)
  * It prints "Missing operator before end of line" if there's nothing
  * after the missing operator, or "... before <...>" if there is something
  * after the missing operator.
+ *
+ * PL_bufptr is expected to point to the start of the thing that was found,
+ * and s after the next token or partial token.
  */
 
 STATIC void
@@ -5994,8 +5997,14 @@ Perl_yylex(pTHX)
        PL_tokenbuf[0] = '$';
        s = scan_ident(s, PL_tokenbuf + 1,
                       sizeof PL_tokenbuf - 1, FALSE);
-       if (PL_expect == XOPERATOR)
-           no_op("Scalar", s);
+       if (PL_expect == XOPERATOR) {
+           d = s;
+           if (PL_bufptr > s) {
+               d = PL_bufptr-1;
+               PL_bufptr = PL_oldbufptr;
+           }
+           no_op("Scalar", d);
+       }
        if (!PL_tokenbuf[1]) {
            if (s == PL_bufend)
                yyerror("Final $ should be \\$ or $name");