Skip to content

Commit a2c2074

Browse files
committed
grok_bin_oct_hex: Improve overflow detection
The new scheme is is what toke.c already uses for the same purpose, and I think is cleaner
1 parent c202865 commit a2c2074

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

numeric.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,6 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
497497
bool overflowed = FALSE;
498498
NV value_nv = 0;
499499
const PERL_UINT_FAST8_T base = 1 << shift; /* 2, 8, or 16 */
500-
const UV max_div= UV_MAX / base; /* Value above which, the next digit
501-
processed would overflow */
502500

503501
for (; s < e; s++) {
504502
if (generic_isCC_(*s, class_bit)) {
@@ -508,8 +506,15 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
508506
(khw suspects that adding a LIKELY() just above would do the
509507
same thing) */
510508
redo:
511-
if (LIKELY(value <= max_div)) {
512-
value = (value << shift) | XDIGIT_VALUE(*s);
509+
510+
/* Make room for the next digit */
511+
UV tentative_value = value << shift;
512+
513+
/* If shiftng back doesn't yield the previous value, it was
514+
* because a bit got shifted off the left end, so overflowed.
515+
* But if not, just add the new digit. */
516+
if (LIKELY((tentative_value >> shift) == value)) {
517+
value = tentative_value | XDIGIT_VALUE(*s);
513518
/* Note XDIGIT_VALUE() is branchless, works on binary
514519
* and octal as well, so can be used here, without
515520
* slowing those down */

0 commit comments

Comments
 (0)