Skip to content

BigInt literals wider than 64 bits are truncated in split (multi-unit) modules: 2n ** 70n === 1180591620717411303424n is false #10545

Description

@proggeramlug

Found by the package audit (while fixing #10418) on Perry 7661bc0 (v0.5.1589), Linux x64. When a module is compiled
as more than one codegen unit, BigInt literals that don't fit in 64 bits lose their high bits: a 71-bit literal
becomes 0n, a 97-bit negative literal becomes a different 64-bit value. Single-unit builds are correct. Large real
modules are split automatically, so this silently changes the constants of big BigInt-heavy libraries (crypto curve
parameters, field moduli), not just forced splits.

Reproduction

main.ts:

function f() { const x = 2n ** 70n; return x === 1180591620717411303424n; }
function g() { return 1180591620717411303424n; }
console.log(f(), g() === 2n ** 70n, String(g()));
const small = 12345678901234567890n;
const neg = -98765432109876543210987654321n;
console.log(String(small), String(neg), 2n ** 64n === 18446744073709551616n);
node main.ts
PERRY_NO_AUTO_OPTIMIZE=1 perry compile main.ts -o one && ./one                        # 1 unit
PERRY_CODEGEN_UNITS=2 PERRY_NO_AUTO_OPTIMIZE=1 perry compile main.ts -o two && ./two  # forced split

Expected (Node 26.5.1, and Perry with 1 unit)

true true 1180591620717411303424
12345678901234567890 -98765432109876543210987654321 true

Actual (Perry, PERRY_CODEGEN_UNITS=2 or 4)

false false 0
12345678901234567890 -18444665141527514289 false

The 64-bit literal 12345678901234567890n survives; anything wider is truncated.

Impact

  • Every automatically split module containing a >64-bit BigInt literal computes with wrong constants — silently.
    Real candidates: @noble/curves (secp256k1/ed25519/BLS field primes and group orders are 255–381-bit literals),
    @noble/hashes constants, ethers, big-number libraries, and any large bundle that happens to include them.
  • The gap corpus is all single-unit, so no existing test covers this.

Notes

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    package-auditFound by the 2026 package audit: compiling real npm packages from source instead of native bindings

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions