@@ -3405,6 +3405,13 @@ rb_f_integer(rb_execution_context_t *ec, VALUE obj, VALUE arg, VALUE base, VALUE
3405
3405
return rb_convert_to_integer (arg , NUM2INT (base ), exc );
3406
3406
}
3407
3407
3408
+ static bool
3409
+ is_digit_char (unsigned char c , int base )
3410
+ {
3411
+ int i = ruby_digit36_to_number_table [c ];
3412
+ return (i >= 0 && i < base );
3413
+ }
3414
+
3408
3415
static double
3409
3416
rb_cstr_to_dbl_raise (const char * p , rb_encoding * enc , int badcheck , int raise , int * error )
3410
3417
{
@@ -3446,30 +3453,48 @@ rb_cstr_to_dbl_raise(const char *p, rb_encoding *enc, int badcheck, int raise, i
3446
3453
char * e = init_e ;
3447
3454
char prev = 0 ;
3448
3455
int dot_seen = FALSE;
3456
+ int base = 10 ;
3457
+ char exp_letter = 'e' ;
3449
3458
3450
3459
switch (* p ) {case '+' : case '-' : prev = * n ++ = * p ++ ;}
3451
3460
if (* p == '0' ) {
3452
3461
prev = * n ++ = '0' ;
3453
- while (* ++ p == '0' );
3462
+ switch (* ++ p ) {
3463
+ case 'x' : case 'X' :
3464
+ prev = * n ++ = 'x' ;
3465
+ base = 16 ;
3466
+ exp_letter = 'p' ;
3467
+ if (* ++ p != '0' ) break ;
3468
+ /* fallthrough */
3469
+ case '0' : /* squeeze successive zeros */
3470
+ while (* ++ p == '0' );
3471
+ break ;
3472
+ }
3454
3473
}
3455
3474
while (p < end && n < e ) prev = * n ++ = * p ++ ;
3456
3475
while (* p ) {
3457
3476
if (* p == '_' ) {
3458
3477
/* remove an underscore between digits */
3459
- if (n == buf || !ISDIGIT (prev ) || (++ p , !ISDIGIT (* p ))) {
3478
+ if (n == buf ||
3479
+ !is_digit_char (prev , base ) ||
3480
+ !is_digit_char (* ++ p , base )) {
3460
3481
if (badcheck ) goto bad ;
3461
3482
break ;
3462
3483
}
3463
3484
}
3464
3485
prev = * p ++ ;
3465
- if (e == init_e && (prev == 'e' || prev == 'E' || prev == 'p' || prev == 'P' )) {
3486
+ if (e == init_e && (rb_tolower ( prev ) == exp_letter )) {
3466
3487
e = buf + sizeof (buf ) - 1 ;
3467
3488
* n ++ = prev ;
3468
3489
switch (* p ) {case '+' : case '-' : prev = * n ++ = * p ++ ;}
3469
3490
if (* p == '0' ) {
3470
3491
prev = * n ++ = '0' ;
3471
3492
while (* ++ p == '0' );
3472
3493
}
3494
+
3495
+ /* reset base to decimal for underscore check of
3496
+ * binary exponent part */
3497
+ base = 10 ;
3473
3498
continue ;
3474
3499
}
3475
3500
else if (ISSPACE (prev )) {
@@ -3479,7 +3504,7 @@ rb_cstr_to_dbl_raise(const char *p, rb_encoding *enc, int badcheck, int raise, i
3479
3504
break ;
3480
3505
}
3481
3506
}
3482
- else if (prev == '.' ? dot_seen ++ : !ISDIGIT (prev )) {
3507
+ else if (prev == '.' ? dot_seen ++ : !is_digit_char (prev , base )) {
3483
3508
if (badcheck ) goto bad ;
3484
3509
break ;
3485
3510
}
0 commit comments