Skip to content

v0.2.2 — a BigInt division could panic

Latest

Choose a tag to compare

@MerlijnW70 MerlijnW70 released this 06 Aug 05:37

A security release. Every published version up to and including 0.2.1 is affected, and
upgrading is a version bump with no code changes for almost every embedder.

The problem — GHSA-6976-qm5m-7mcj

1n / ((1n << 33554399n) * 2n) ended the host process with an index out of bounds. ViperJS
exists to run untrusted JavaScript inside somebody else's program, so a script-triggered panic
is not one bug among many — it is the engine's central promise failing. Reported privately by
@Zniece, who gets the credit for finding it and for a report that
was reproducible on the first run.

What it was

One comparison against the wrong number. A left shift reserved a limb for the bits it might push
off the top, measured that width against the size ceiling, and trimmed it away again — so a
magnitude landing exactly on the ceiling was refused for room it does not keep. The refusal was
then read as impossible by the division and discarded with a default, leaving an empty divisor
to be indexed at usize::MAX.

Two silent wrong answers came from the same line and are fixed with it. On 0.2.1,
d % 7n answered 0n where the true remainder is 1n, and String(d) answered "0"
neither of which raised anything. Those are the ones worth noticing: a panic announces itself,
and a wrong answer does not.

Also in this release

  • BigInt::to_digits returns a Result, and String(x) on a magnitude beyond the engine's
    limit raises a RangeError rather than spelling "0". ECMA-262 §6.1.4 requires an
    implementation that imposes a limit to throw rather than to answer something else. Breaking,
    which pre-1.0 allows.
  • A shift landing exactly on the ceiling now succeeds, where it used to be refused.

Upgrade: viperjs = "0.2.2".