Skip to content

Fix BigInt shift_right/shift_left for large shift amounts#4710

Merged
jedel1043 merged 2 commits intoboa-dev:mainfrom
Ansh-699:fix/bigint-shift-right-large-amount
Feb 28, 2026
Merged

Fix BigInt shift_right/shift_left for large shift amounts#4710
jedel1043 merged 2 commits intoboa-dev:mainfrom
Ansh-699:fix/bigint-shift-right-large-amount

Conversation

@Ansh-699
Copy link
Contributor

1000n >> 1000000000000000n incorrectly throws RangeError: Maximum BigInt size exceeded instead of returning 0n. The shift amount does not fit in i32, so to_i32() returns None and the code falls through to the error branch unconditionally.

Per the ECMAScript spec (and confirmed against V8/SpiderMonkey), arithmetic right-shifting by a very large positive amount should return:

  • 0n for non-negative values
  • -1n for negative values

The same fix is applied symmetrically to shift_left when the shift amount is a large negative number (equivalent to a large right-shift).

Changes:

  • JsBigInt::shift_right: check sign of y in the None arm — large positive y returns 0n/-1n, large negative y keeps the RangeError
  • JsBigInt::shift_left: mirror logic — large negative y returns 0n/-1n, large positive y keeps the RangeError
  • Updated tests: replaced assert_native_error with assert_eq for the right-shift case, added coverage for negative BigInt and zero

@jedel1043
Copy link
Member

Per the ECMAScript spec (and confirmed against V8/SpiderMonkey), arithmetic right-shifting by a very large positive amount should return:
0n for non-negative values
-1n for negative values

I would suggest adding a comment to the specific section of the spec that mentions this, just for future reference.

@github-actions
Copy link

github-actions bot commented Feb 25, 2026

Test262 conformance changes

Test result main count PR count difference
Total 52,862 52,862 0
Passed 49,505 49,497 -8
Ignored 2,261 2,261 0
Failed 1,096 1,104 +8
Panics 0 0 0
Conformance 93.65% 93.63% -0.02%
Fixed tests (1):
test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js (previously Ignored)
Broken tests (8):
test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js (previously Passed)
test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js (previously Passed)
test/staging/sm/RegExp/unicode-raw.js (previously Passed)
test/staging/sm/RegExp/unicode-class-raw.js (previously Passed)

@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

❌ Patch coverage is 75.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.12%. Comparing base (6ddc2b4) to head (470cd2b).
⚠️ Report is 703 commits behind head on main.

Files with missing lines Patch % Lines
core/engine/src/bigint.rs 75.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4710      +/-   ##
==========================================
+ Coverage   47.24%   57.12%   +9.87%     
==========================================
  Files         476      552      +76     
  Lines       46892    60500   +13608     
==========================================
+ Hits        22154    34559   +12405     
- Misses      24738    25941    +1203     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Ansh-699
Copy link
Contributor Author

Per the ECMAScript specification, the Signed Right Shift Operator (>>) is defined here:
https://tc39.es/ecma262/#sec-signed-right-shift-operator
For BigInt operands, it is defined mathematically as:

ℤ(floor(x / 2^y))

For sufficiently large positive y:

  • If x ≥ 0, then x / 2^y → 0floor(...) = 00n
  • If x < 0, then x / 2^y → 0⁻floor(...) = -1-1n

Therefore, shifting by a very large positive amount must return 0n or -1n, not throw a RangeError. This matches V8 and SpiderMonkey behavior.

@jedel1043
Copy link
Member

@Ansh-699 That sound more like it's not part of the spec.

I guess we can still apply this safeguard, but let's be very clear with a comment that this is just a best-effort safeguard, not a spec-related result.

@jedel1043 jedel1043 added the Internal Category for changelog label Feb 25, 2026
@Ansh-699
Copy link
Contributor Author

ok no worries

Right-shifting a BigInt by a value that doesn't fit in i32 (e.g.
1000n >> 1000000000000000n) incorrectly threw RangeError. Per spec,
arithmetic right shift by a large positive amount should return 0n
for non-negative values and -1n for negative values.

The same logic is applied symmetrically to shift_left when the shift
amount is a large negative number.
@Ansh-699 Ansh-699 force-pushed the fix/bigint-shift-right-large-amount branch from 7eda4e5 to f237dd4 Compare February 25, 2026 07:17
@Ansh-699 Ansh-699 requested a review from a team as a code owner February 25, 2026 07:17
@Ansh-699
Copy link
Contributor Author

Ansh-699 commented Feb 25, 2026

Updated — thanks for the feedback!

Changes in this push:

  • Reworded comments to make it clear this is a best-effort safeguard, not a direct spec requirement. Added links to the relevant spec sections (sec-numeric-types-bigint-signedRightShift and sec-numeric-types-bigint-leftShift).
  • Added tests for shift_left with large negative amounts (the mirror case), which should improve the patch coverage.

Copy link
Member

@jedel1043 jedel1043 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just some small nitpicks about the style, but the implementation looks good

Comment on lines 232 to 245
if y.inner.sign() == Sign::Minus {
// x >> (large negative) is equivalent to x << (large positive), which overflows.
Err(JsNativeError::range()
.with_message("Maximum BigInt size exceeded")
.into())
} else {
// x >> (large positive): all bits are shifted out.
if x.inner.sign() == Sign::Minus {
Ok(Self::new(RawBigInt::from(-1)))
} else {
Ok(Self::zero())
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: maybe this would look a bit nicer with a match

match (x.inner.sign(), y.inner.sign()) {
    (Sign::Minus, Sign::Plus) => -1,
    (Sign::Plus, Sign::Plus) => 0,
    (_, Sing::Minus) => Err,
}

Comment on lines 259 to 272
None => {
if y.inner.sign() == Sign::Minus {
// x << (large negative) is equivalent to x >> (large positive): all bits shifted out.
if x.inner.sign() == Sign::Minus {
Ok(Self::new(RawBigInt::from(-1)))
} else {
Ok(Self::zero())
}
} else {
// x << (large positive) overflows.
Err(JsNativeError::range()
.with_message("Maximum BigInt size exceeded")
.into())
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same suggestion as above; a match could be easier to read overall.

@jedel1043 jedel1043 added bug Something isn't working waiting-on-author Waiting on PR changes from the author labels Feb 27, 2026
Copy link
Member

@jedel1043 jedel1043 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@jedel1043 jedel1043 added this pull request to the merge queue Feb 28, 2026
Merged via the queue into boa-dev:main with commit f950c21 Feb 28, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Internal Category for changelog waiting-on-author Waiting on PR changes from the author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants