@@ -465,6 +465,9 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
465465 NV value_nv = 0 ;
466466 const PERL_UINT_FAST8_T base = 1 << shift ; /* 2, 8, or 16 */
467467
468+ /* Value above which, the next digit processed would overflow */
469+ UV max_div = UV_MAX >> shift ;
470+
468471 for (; s < e ; s ++ ) {
469472 if (generic_isCC_ (* s , class_bit )) {
470473 /* Write it in this wonky order with a goto to attempt to get the
@@ -473,19 +476,12 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
473476 (khw suspects that adding a LIKELY() just above would do the
474477 same thing) */
475478 redo : ;
476-
477- /* Make room for the next digit */
478- UV tentative_value = value << shift ;
479-
480- /* If shiftng back doesn't yield the previous value, it was
481- * because a bit got shifted off the left end, so overflowed.
482- * But if it worked, add the new digit. */
483- if (LIKELY ((tentative_value >> shift ) == value )) {
479+ if (LIKELY (value <= max_div )) {
484480 /* Note XDIGIT_VALUE() is branchless, works on binary and
485481 * octal as well, so can be used here, without noticeably
486482 * slowing those down (it does have unnecessary shifts, ANDSs,
487483 * and additions for those) */
488- value = tentative_value | XDIGIT_VALUE (* s );
484+ value = ( value << shift ) | XDIGIT_VALUE (* s );
489485 factor *= base ;
490486 continue ;
491487 }
0 commit comments