Skip to content

[4.x] Give BigInt shifts and asIntN/asUintN their spec results for any count (backport of #4443) - #4467

Open
michaelthyregod wants to merge 1 commit into
sebastienros:4.xfrom
michaelthyregod:backport/4.x-bigint-shift-and-asintn
Open

michaelthyregod wants to merge 1 commit into
sebastienros:4.xfrom
michaelthyregod:backport/4.x-bigint-shift-and-asintn

Conversation

@michaelthyregod

Copy link
Copy Markdown
Contributor

Backport of #4443. Fixes #4432 on 4.x.

On 4.17.0, a script can make the host receive a CLR exception from BigInt arithmetic (the first two also re-checked on 4.x at dfccb4d): 1n >> (2n ** 32n) throws OverflowException ("Value was either too large or too small for an Int32"), BigInt.asUintN(2 ** 31 - 1, 5n) throws OverflowException, and BigInt.asUintN(2 ** 31 - 2, 5n) throws OutOfMemoryException, where the spec has a result (0n, 5n, 5n). The change is #4443's: BigIntLeftShift implements BigInt::leftShift/signedRightShift with the same JsBigInt.MaxBitLength cap ** uses, asIntN/asUintN return a value that already fits and otherwise mask instead of BigInteger.Pow, and EvaluateBitwiseOperation takes the Engine and reads .Realm only to throw.

The library files applied cleanly. Left out: Jint.Tests/SpecAnchors.txt, which 4.x does not have. The tests in BigIntTests are converted from NUnit to xUnit; as on main, FixedWidthBigIntOperationsRejectUnsupportedBitCounts becomes FixedWidthBigIntOperationsReturnAValueThatFitsUnchanged, since asIntN(2 ** 31, 1n) now returns 1n instead of RangeError: Invalid bit count. The GetBitLength polyfill covers net462 and both netstandard targets.

Observable changes on 4.x, the same as on main: those cases return the spec result instead of throwing; a negative asUintN wider than 1,000,000 bits and a left shift whose result would exceed 1,000,000 bits throw RangeError: Maximum BigInt size exceeded (V8 allows 2^30 bits), consistent with **.

Verified locally: Jint.Tests 8054 passed / 4 skipped (net10.0) and 7969 / 4 (net472); Jint.Tests.PublicInterface 1967 passed / 9 skipped (net10.0) and 1959 / 9 (net472); Jint.Tests.Test262 102513 passed / 171 skipped; 0 failures.

🤖 Generated with Claude Code

@michaelthyregod

Copy link
Copy Markdown
Contributor Author

The linux - ARM failure here is StackOverflowGuardTests.TheEngineIsUnchangedAfterTheGuardFires (depths 631/631/611), not this change: the recursion it measures (depth++; return f()) never reaches a BigInt or bitwise path, and x64, macOS and Windows passed, as did the same ARM job on #4468. On 4.x that test still requires three identical depths, so one JIT recompilation that changes a frame size turns it red; main replaced that with the leak-march check in #3140, which was never backported. Could you re-run the job?

If it's useful, I can send #3140 as a 4.x backport too (test-only), so this stops turning 4.x PRs red.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant