test: property-based fuzz testing for js->zig->js roundtrip#41
Open
nazarhussain wants to merge 21 commits into
Open
test: property-based fuzz testing for js->zig->js roundtrip#41nazarhussain wants to merge 21 commits into
nazarhussain wants to merge 21 commits into
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NAPI sets word_count to the required size even when the buffer is smaller than needed; the previous code returned words[0..word_count], which is UB when word_count > words.len. Clamping via @min makes the function safe and gives callers the semantics of truncate-to-low-N-bits.
Previous toI128 panicked on three input classes: zero (result[0] on empty slice), minInt(i128) (@intcast overflow during negation), and out-of-range magnitudes. Reworks the function to use a pre-zeroed local buffer and wrapping arithmetic, returning BigInt.asIntN(128, b) semantics for out-of-domain inputs. Documents the in-domain (exact) and out-of-domain (truncation) contract in the doc comment, and adds an explicit comment on the magnitude == 0 guard for out-of-range negatives whose low 128 bits are all zero (e.g. -2^128n), where asIntN(128, b) === 0n.
Thin DSL wrapper over napi_create_bigint_words. Required for round-tripping i128 and larger values through the DSL without going through the i64/u64 path. Accepts a sign bit and a little-endian u64-word slice; the resulting BigInt equals (sign == 1 ? -1 : 1) * sum(words[i] << (64 * i)).
Round-trips JS BigInt → i128 → JS BigInt via toI128 and fromWords. Property test covers the i128 boundary plus out-of-range truncation via BigInt.asIntN(128, ·). Oracle test adds deterministic boundary cases for zero, I128_MIN/MAX (exact), just-out-of-range ±1, and oversized values whose low 128 bits are all zero (expected result: 0n).
Zig 0.16's `zig fmt` reorders `@alignCast(@ptrCast(x))` to `@ptrCast(@aligncast(x))`. The pre-existing form was triggering format churn in working trees across every `zig build` invocation; applying the canonical order once stops the noise.
The seeds-workflow doc claimed NaN/Infinity could be persisted via a
{"__special": ...} encoding, but no corresponding reviver exists in
fuzz.test.ts — following the README literally would silently corrupt
test input. NaN/Infinity are already in edgeNumbers and exercised every
run, so persisting them adds nothing. Trim the README to match reality.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a property-based fuzz harness for zapi
Number,BigIntandUint8Arrayconverters and (vitest + fast-check, driven through a dedicatedtest_fuzz_numeric.nodeaddon). The harness immediately surfaced multiple latent bugs and an API sharp edge, all addressed in this branch.API changes
toI64/toU64/toI128: these now returnerror.InvalidArgon out-of-range BigInts instead of silently truncating. Callers who explicitly want low-bits semantics use the newtoI64LowBits/toU64LowBits/toI128LowBitsvariants. NAPI's lossless flag is exposed as thelosslessout-pointer on the*LowBitscalls.BigInt.fromWords(sign_bit, words)— DSL surface for constructing BigInts whose magnitude exceeds u64 (e.g., i128). Closes the gap the existingBigInt.fromdoc comment noted but couldn't fill.Number.toI32/U32/F64/I64updated to accurately describe N-API conversion semantics (NaN/Inf → 0, range clamping, etc.).