diff --git a/TODO.md b/TODO.md index 31af3a8763..0592e157c8 100644 --- a/TODO.md +++ b/TODO.md @@ -509,15 +509,3 @@ Fix direction: in `applyArg`, when `VALUE_FLAGS[arg]` exists but `next` is `undefined`, raise a clear "missing value for " usage error rather than pushing the flag to `positional`; keep consuming/returning true when a value is present. - -### 5. Seeded PRNG `rand()` can return exactly 1 - -`test/lib/checkout-pricing-consistency.test.ts` — `makeRng`'s `rand` returns -`seed / 0x7fffffff`, which is `1` when `seed === 0x7fffffff`. That lets `pick` -index one past the array and `randInt` return `hi + 1`. Astronomically unlikely -for the fixed seeds in use (and identical to `main`), but incorrect. - -Fix direction: normalize with `seed / 0x80000000` (or clamp below 1). Note this -changes the seeded sequence, so re-baseline any hardcoded expectations and -confirm the property test still passes; best landed on its own so the corpus -shift is reviewed deliberately. diff --git a/test/lib/checkout-pricing-consistency.test.ts b/test/lib/checkout-pricing-consistency.test.ts index 4f94e0bfc1..b088186405 100644 --- a/test/lib/checkout-pricing-consistency.test.ts +++ b/test/lib/checkout-pricing-consistency.test.ts @@ -118,7 +118,10 @@ const makeRng = (initialSeed: number): Rng => { let seed = initialSeed; const rand = () => { seed = (seed * 1103515245 + 12345) & 0x7fffffff; - return seed / 0x7fffffff; + // Divide by 2^31 (not 2^31-1) so the result is always in [0, 1): at + // seed === 0x7fffffff the old divisor returned exactly 1, letting `pick` + // index past the array and `randInt` return hi + 1. + return seed / 0x80000000; }; const pick = (xs: readonly T[]): T => xs[Math.floor(rand() * xs.length)]!; const randInt = (lo: number, hi: number) => diff --git a/test/shared/payment-signature.test.ts b/test/shared/payment-signature.test.ts index 75536b0d43..1fc69db78e 100644 --- a/test/shared/payment-signature.test.ts +++ b/test/shared/payment-signature.test.ts @@ -58,7 +58,8 @@ const excludedKeys: [string, Record][] = [ /** Tiny deterministic PRNG so the fuzz loop is repeatable. */ const lcg = (seed: number) => () => { seed = (seed * 1103515245 + 12345) & 0x7fffffff; - return seed / 0x7fffffff; + // Divide by 2^31 (not 2^31-1) so the result stays in [0, 1). + return seed / 0x80000000; }; describeWithEnv("payment price signature", { encryptionKey: true }, () => {