fix(parse): reject non-finite numbers + pin fast-check repro - #51
Merged
Conversation
A raw Infinity in the legacy flat-map shape (value is a bare number) was assigned to amount without finite filtering. Infinity > 0 is true, so the row survived and poisoned totalPrimary, producing a non-finite snapshot total. Route the value through num(), which clamps non-finite values to 0 so the existing !(amount > 0) guard discards the row. Surfaced by the fast-check property parseSnapshot: output always has required keys with correct types (seed -1679627146, counterexample [Infinity]) flaking the Web-static verify gate on PRs #49/#50.
Explicit deterministic cases for Infinity / -Infinity / NaN across all three input shapes (legacy bare-number array, legacy object amount, new miner amount). Locks the fast-check counterexample [Infinity] (seed -1679627146) regardless of the random seed, so the Web-static verify gate no longer flakes on this class of input.
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.
Summary
parseSnapshotcould emit a non-finitetotalPrimary. In the legacyflat-map shape, a bare-number value (
{ addr: <number> }, or an arrayelement via
Object.entries) was assigned toamountwithoutfinite filtering.
Infinity > 0is true, so the row survived the!(amount > 0)guard and poisoned thetotalPrimarysum, producing asnapshot whose
totalPrimarywasInfinity. (-InfinityandNaNwere already dropped by the guard; only
+Infinityleaked.)Fix: route the legacy bare-number branch through the existing
num()helper, which clamps non-finite values to
0so the existing guarddiscards the row — consistent with the parser's "drop malformed rows,
never throw" contract (no spec allows non-finite payout amounts).
Bug provenance
Surfaced by the fast-check property
parseSnapshot: output always has required keys with correct typesflaking the Web-static verify gate onPRs #49/#50.
-1679627146[Infinity](the[[…]]printed by fast-checkis the argument-tuple wrapper)
Number.isFinite(snap.totalPrimary)Changes
src/pplns/parse.ts—parseLegacyShape:amount = v→amount = num(v).tests/unit/pplns-parse-properties.test.ts— 3 deterministicregression tests pinning
Infinity/-Infinity/NaNacross thelegacy-array, legacy-object, and new-miner shapes.
Verification
npm test— 257 tests, 245 pass / 12 skipped / 0 fail. New regressiontests green.
Note
The fast-check seed pin in CI (to make the gate deterministic) is
tracked separately and is ci-steward's domain — not included here.