This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
(perl #134125) make no digits after 0x/0b fatal
authorTony Cook <tony@develop-help.com>
Thu, 20 Jun 2019 01:06:13 +0000 (11:06 +1000)
committerTony Cook <tony@develop-help.com>
Wed, 26 Jun 2019 23:53:57 +0000 (09:53 +1000)
My original change in 7259f4194 silently adjusted the parse
position to immediately after the 0 in an incomplete hex or binary
literal.  In most cases this leads to a syntax error, but in some
cases, especially with 0x, this can lead to a silent change in
behaviour.

So throw an error instead.

pod/perldiag.pod
t/lib/croak/toke
t/op/hexfp.t
toke.c

index 166d29b..325bfce 100644 (file)
@@ -4100,6 +4100,11 @@ for some reason the current debugger (e.g. F<perl5db.pl> or a C<Devel::>
 module) didn't define a C<DB::sub> routine to be called at the beginning
 of each ordinary subroutine call.
 
+=item No digits found for %s literal
+
+(F) No hexadecimal digits were found following C<0x> or no binary digits
+were found following C<0b>.
+
 =item No directory specified for -I
 
 (F) The B<-I> command-line switch requires a directory name as part of the
index e7bf609..4ef6f72 100644 (file)
@@ -507,16 +507,12 @@ Execution of - aborted due to compilation errors.
 0x x 2;
 0xx 2;
 0x_;
+0b;
 EXPECT
-Number found where operator expected at - line 1, near "x 2"
-       (Do you need to predeclare x?)
-Bareword found where operator expected at - line 2, near "0xx"
-       (Missing operator before xx?)
-Number found where operator expected at - line 2, near "xx 2"
-       (Do you need to predeclare xx?)
-Bareword found where operator expected at - line 3, near "0x_"
-       (Missing operator before x_?)
-syntax error at - line 1, near "x 2"
+No digits found for hexadecimal literal at - line 1, near "0x "
+No digits found for hexadecimal literal at - line 2, near "0xx"
+No digits found for hexadecimal literal at - line 3, near "0x_;"
+No digits found for binary literal at - line 4, near "0b;"
 Execution of - aborted due to compilation errors.
 ########
 # NAME [perl #130585] close paren in subparse
index 8904c48..eeb2c9d 100644 (file)
@@ -138,7 +138,7 @@ sub get_warn() {
 
 { # Test certain things that are not hexfloats and should stay that way.
     eval '0xp3';
-    like(get_warn(), qr/Missing operator before xp3/);
+    like(get_warn(), qr/Missing operator before p3/);
 
     eval '5p3';
     like(get_warn(), qr/Missing operator before p3/);
@@ -149,7 +149,7 @@ sub get_warn() {
 
     undef $a;
     eval '$a = eval "0x.3"';
-    is($a, ''); # 0 x .3
+    is($a, undef); # throws an error
 
     undef $a;
     eval '$a = eval "0xc.3"';
diff --git a/toke.c b/toke.c
index e21a95f..b09bd8d 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -11336,10 +11336,16 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
             }
 
             if (shift != 3 && !has_digs) {
-                /* 0x or 0b with no digits, treat it as if the x or b is part of the
-                   next token
+                /* 0x or 0b with no digits, treat it as an error.
+                   Originally this backed up the parse before the b or
+                   x, but that has the potential for silent changes in
+                   behaviour, like for: "0x.3" and "0x+$foo".
                 */
-                s = start + 1;
+                const char *d = s;
+                if (*d) ++d; /* so the user sees the bad non-digit */
+                PL_bufptr = (char *)d; /* so yyerror reports the context */
+                yyerror(Perl_form(aTHX_ "No digits found for %s literal",
+                                  shift == 4 ? "hexadecimal" : "binary"));
             }
 
            if (overflowed) {