Fix overflow issue in Number.prototype.toString for large numbers#2471
Conversation
|
Please add test coverage. |
(-12345e+30).toString(2) and similar calls used to cast x to long directly, which overflowed for values beyond ~9.22e18 (long.MaxValue) and silently returned wrong digits (or threw). Use BigInteger for the integer part once the truncated value no longer fits in long. This produces the mathematically exact base-r representation of the stored double for every radix in 2..36, while keeping the fast (long) path for small values. Add ShouldWriteLargeNumbersUsingBasesWithoutOverflow covering power-of-2 radices (bit-exact, matches V8), non-power-of-2 radices, the long.MaxValue boundary, and small-value regression cases. Co-Authored-By: Marko Lahma <marko.lahma@gmail.com>
|
Hi @asheigithub — I rebased this onto current Why the original fix was incompleteThe "divide by radix in floating-point until it fits in
For non-power-of-2 radices (3, 5, 6, 7, 9, 11–15, 17–31, 33–36) neither property holds:
Concrete example with the old fix: (1e+20).toString(3)
// old fix: 220200020122120112010222022122002000000000 (wrong)
// new fix: 220200020122120112010222022122002000100201 (exact)What the new commit does
Test coverageAdded
All 2997 |
|
thank you ! my English is not very good, Your BigInteger solution looks great. I will keep learning and hope I can make better contributions in the future. |
Fixes a crash when calling Number.prototype.toString(radix) on very large numbers such as:
(-12345e+30).toString(2)
Summary
Use Math.Truncate(x) to avoid overflow when converting extremely large Numbers to string in non‑decimal radices.
Details
The previous implementation cast the Number directly to
long:This overflows for values larger than
long.MaxValue(≈9e18), which is common for Numbers with large exponents such as-12345e+30.(long)xwithMath.Truncate(x)to safely obtain the integer part without overflow.long.MaxValue, repeatedly divide by the radix until the value fits intolong.Linked issue
Fixes # (no existing issue; this PR includes the fix)
Test plan
Jint.Testsdotnet test --configuration ReleaselocallyJint.Tests.Test262and confirmed no regressionsJint.Tests/Runtime/InteropJint.BenchmarkBreaking change?
No.