@@ -495,6 +495,9 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
495495 NV value_nv = 0 ;
496496 const PERL_UINT_FAST8_T base = 1 << shift ; /* 2, 8, or 16 */
497497
498+ /* Value above which, the next digit processed would overflow */
499+ UV max_div = UV_MAX >> shift ;
500+
498501 for (; s < e ; s ++ ) {
499502 if (generic_isCC_ (* s , class_bit )) {
500503 /* Write it in this wonky order with a goto to attempt to get the
@@ -503,19 +506,12 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
503506 (khw suspects that adding a LIKELY() just above would do the
504507 same thing) */
505508 redo : ;
506-
507- /* Make room for the next digit */
508- UV tentative_value = value << shift ;
509-
510- /* If shiftng back doesn't yield the previous value, it was
511- * because a bit got shifted off the left end, so overflowed.
512- * But if it worked, add the new digit. */
513- if (LIKELY ((tentative_value >> shift ) == value )) {
509+ if (LIKELY (value <= max_div )) {
514510 /* Note XDIGIT_VALUE() is branchless, works on binary and
515511 * octal as well, so can be used here, without noticeably
516512 * slowing those down (it does have unnecessary shifts, ANDSs,
517513 * and additions for those) */
518- value = tentative_value | XDIGIT_VALUE (* s );
514+ value = ( value << shift ) | XDIGIT_VALUE (* s );
519515 factor *= base ;
520516 continue ;
521517 }
0 commit comments