Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions t/comp/parser_run.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ BEGIN {
set_up_inc( qw(. ../lib ) );
}

plan(70);
plan(82);

# [perl #130814] can reallocate lineptr while looking ahead for
# "Missing $ on loop variable" diagnostic.
Expand Down Expand Up @@ -38,7 +38,10 @@ for my $var ('$00','${00}','$001','${001}','$01','${01}','$09324', '${09324}') {
}
}

for my $var ('$0', '${0}', '$1', '${1}', '$10', '${10}', '$9324', '${9324}') {
for my $var (
'$0', '${0}', '$1', '${1}', '$10', '${10}', '$9324', '${9324}',
'${0x10}', '${0b10000}', '${0xA}',
) {
for my $utf8 ("","use utf8;") {
for my $strict ("","use strict;") {
fresh_perl_is(
Expand Down
1 change: 0 additions & 1 deletion t/re/pat.t
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ sub run_tests {
$ok= eval sprintf 'is ${0%d}, "%s", q(${0%d} = %s); 1', ($n, substr($string,$n-1,1))x2;
ok(!$ok, "eval failed as expected for \${0$n} test");

no strict 'refs';
$ok= eval sprintf 'is ${0b%b}, "%s", q(${0b%b} = %s); 1', ($n, substr($string,$n-1,1))x2;
ok($ok, sprintf "eval for \${0b%b} test", $n);
$ok= eval sprintf 'is ${0x%x}, "%s", q(${0x%x} = %s); 1', ($n, substr($string,$n-1,1))x2;
Expand Down
54 changes: 44 additions & 10 deletions toke.c
Original file line number Diff line number Diff line change
Expand Up @@ -10195,18 +10195,52 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN destlen, I32 ck_uni)
}
}

/* special case to handle ${10}, ${11} the same way we handle ${1} etc */
if (isDIGIT(*d)) {
bool is_zero= *d == '0' ? TRUE : FALSE;
/* special case to handle ${10}, ${11} the same way we handle $1 and ${1} etc,
* also special case ${0x10} and ${0b10000} to do the right thing and refer to
* $16 at compile time without triggering use strict violations */
if (isDIGIT(*d) && s < PL_bufend) {
char *digit_start= d;
while (s < PL_bufend && isDIGIT(*s)) {
d++;
if (d >= e)
Perl_croak(aTHX_ "%s", ident_too_long);
*d= *s++;
bool has_leading_zero= *d == '0' ? TRUE : FALSE;
if (isDIGIT(*s)) {
do {
d++;
if (d >= e)
Perl_croak(aTHX_ "%s", ident_too_long);
*d = *s++;
} while (s < PL_bufend && isDIGIT(*s));
if (has_leading_zero && d - digit_start >= 1) /* d points at the last digit */
Perl_croak(aTHX_ ident_var_zero_multi_digit);
}
if (is_zero && d - digit_start >= 1) /* d points at the last digit */
Perl_croak(aTHX_ ident_var_zero_multi_digit);
else
if ( has_leading_zero ) {
int shift = 0;
U8 class_bit = 0;
if (*s == 'x') {
shift = 4;
class_bit = CC_XDIGIT_;
} else if (*s == 'b') {
shift = 1;
class_bit = CC_BINDIGIT_;
} else if (*s == 'o') {
shift = 3;
class_bit = CC_OCTDIGIT_;
}
if (shift) {
STRLEN len = PL_bufend - s;
I32 flags = PERL_SCAN_SILENT_ILLDIGIT | PERL_SCAN_DISALLOW_PREFIX;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider setting the PERL_SCAN_ALLOW_UJNDERSCORES flag? (to allow things like 0b11_00_1_1)

UV uv = Perl_grok_bin_oct_hex(aTHX_ s+1, &len, &flags, NULL, shift, class_bit, *s);
if (len) {
s += len + 1; /* move past the prefix digit and tail */
if (flags & PERL_SCAN_GREATER_THAN_UV_MAX || d+len >= e)
Perl_croak(aTHX_ "%s", ident_too_long);
Comment on lines +10234 to +10235

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test for the flags & PERL_SCAN_GREATER_THAN_UV_MAX condition(?)
The error in that case might also be a bit misleading:

$ ./perl -wle 'use strict; print ${0x1ffffffffffffffff};'
Integer overflow in hexadecimal number at -e line 1.
Hexadecimal number > 0xffffffff non-portable at -e line 1.
Identifier too long at -e line 1.

len = snprintf(dest,destlen, "%" UVuf, uv);
d = dest + len - 1;
/* note we dont need to worry about trailing garbage, that will be
* handled later. */
}
}
}

d[1] = '\0';
}

Expand Down