Differential behavior: BigInt division throws RangeError on max-size dividend due to over-allocation in absoluteLeftShiftAlwaysCopy
Categories
(Core :: JavaScript Engine, defect, P3)
Tracking
()
People
(Reporter: decoder, Unassigned)
References
(Blocks 1 open bug)
Details
(Keywords: ai-involved, testcase)
Attachments
(1 file)
|
233 bytes,
text/plain
|
Details |
Summary
BigInt::absoluteLeftShiftAlwaysCopy unconditionally allocates n + 1 digits when called with LeftShiftMode::AlwaysAddOneDigit. When the dividend is already at MaxDigitLength, the internal temporary exceeds the allocation limit and the engine throws RangeError: BigInt is too large to allocate, even though the final quotient is well within the limit. V8 computes the correct result.
Root Cause
In js/src/vm/BigIntType.cpp:805, resultLength is computed as n + 1 for AlwaysAddOneDigit mode. When this is called from absoluteDivWithBigIntDivisor (line 911) with a max-size dividend (n == MaxDigitLength), createUninitialized(cx, MaxDigitLength + 1, ...) at line 806 fails because it exceeds the allocation limit check at line 141.
The over-allocation is an internal implementation detail of the Knuth division normalization step — the final result (quotient) is much smaller than MaxDigitLength, so the operation should succeed.
Reproduction
Testcase: poc.js
const maxBitLength = 1024n * 1024n;
const x = 1n << (maxBitLength - 1n);
const y = 1n << 64n;
const q = x / y;
const expected = 1n << (maxBitLength - 65n);
if (q !== expected) {
throw new Error("wrong quotient");
}
print("ok");
SpiderMonkey (mozilla-central 20260521-b754e06486cf, fuzzing-asan-opt):
$ dist/bin/js --fuzzing-safe poc.js
poc.js:5:15 RangeError: BigInt is too large to allocate
V8:
$ d8 poc.js
ok
No special prefs or flags are required beyond --fuzzing-safe (used only for fuzzing stability, not required to reproduce).
Suggested Fix
Either:
- Increase the internal allocation limit for temporaries in division (allow
MaxDigitLength + 1for internal intermediate results), or - Handle the max-size dividend case in
absoluteDivWithBigIntDivisorby special-casing whenshift == 0to avoid the extra digit allocation, or - Use a separate internal limit for transient allocations that is slightly larger than the public
MaxDigitLength.
| Reporter | ||
Comment 1•2 months ago
|
||
Updated•2 months ago
|
Updated•2 months ago
|
Description
•