ReviewOS

zig-utils/zig-js

Private ABI: seed script-execution context registry

#867
Closed chris opened this 9 days ago ·
9 days ago

Parents: #493, #495 Related: #866 Follow-up: #868

Problem

The process-global ScriptExecutionContextIdentifier registry stores live 32-bit context IDs in std.AutoHashMapUnmanaged(u32, ...). Home may supply those IDs through Zig__GlobalObject__create, so native boundary input controls the key set while bucket placement remains process-default and predictable.

This is an algorithmic-complexity surface in a long-lived process registry. The IDs are stable identities, not authority tokens: callers depend on exact explicit assignment and same-VM isolation transfer, so randomizing or replacing their externally visible values would be the wrong fix.

Required design

  • Preserve the exact nonzero 32-bit identifier ABI, sequential lazy allocation, explicit Home assignment, and same-VM test-isolation transfer semantics.
  • Store live mappings in a separately and securely seeded exact-integer map under the existing process lock.
  • Initialize the map lazily and publish its hash context only after the first backing allocation succeeds.
  • Make first registration, explicit assignment, and transfer failure-atomic: entropy/allocation failure must not publish an ID, owner, or partial map state.
  • Preserve natural teardown and explicit remove behavior; zero, unknown, duplicate, retired, and forged IDs remain inert.
  • Keep lookup exact under collisions and concurrent creation/removal.

No-workaround rules

  • No randomized externally visible IDs, address-derived IDs/seeds, predictable entropy fallback, hash-only equality, ID cap/reduced range, linear fallback, leaked tombstones, disabled explicit assignment, weakened teardown, signature or pinned-layout change, or lock removal.

Acceptance

  • Default-seed integer collision families disperse under independently keyed exact hashing; lookup/removal remain exact.
  • Context-entropy and first-allocation failures leave the registry empty, unseeded, leak-free, and retryable.
  • Stable lazy IDs, exact explicit assignment, and isolation transfer preserve the current observable ABI and publish only complete mappings.
  • Duplicate/zero/unknown/retired/forged IDs and concurrent lifecycle races remain inert and cannot resolve a different live context.
  • Focused script-execution-context tests pass in Debug, ReleaseSafe, and TSan; full units and public C plus pinned Home/Bun ABI/runtime gates pass.
9 days ago

Implemented and shipped in 58697c0e.

The process registry now preserves exact public 32-bit IDs while using a lazy independent secure hash context. First insertion publishes its table and context together, duplicate assignment cannot replace the live owner, and isolation transfer performs its only possible allocation before changing the inherited mapping.

Validation:

  • shared exact-identity collision/OOM witness: 1/1 in Debug, ReleaseSafe, and TSan
  • script-context registry/stability tests: 2/2 in Debug, ReleaseSafe, and TSan
  • full internal global lifecycle/isolation test: 1/1 in Debug, ReleaseSafe, and TSan
  • pinned Home script-context fixture: Debug, ReleaseSafe, and TSan
  • pinned Home+Bun global lifecycle fixtures: Debug, ReleaseSafe, and TSan
  • deterministic threadfuzz: 400/400 from seed 1
  • exact clean full suite at the committed tree: 2,288 passed, 1 skipped, 0 failed, 0 leaked across 10 shards
  • public C audit: 117/117 declarations and symbols; Home public ABI: 50/50 plus runtime smoke
  • Home private ABI: 447/447; Bun private ABI: 437/437; Home private runtime/value shims: 392/392
  • private JSType audit: Home 97, Bun 98, shared 97, Bun-only 1, renumbered 70; Home and Bun runtime shims passed
  • docs build: 50 pages; link check: 328/328

The distinct pinned INT32_MAX macro-sentinel mismatch discovered during review is tracked in #868 rather than changing its semantics inside this hash-hardening fix.

9 days ago

Follow-up #868 is complete in 67cf1750: the keyed registry now also preserves pinned INT32_MAX macro-sentinel generation and one monotonic non-reusing namespace across worker, macro, lazy, and isolation IDs.

9 days ago

Follow-up #869 is complete in fix(private-abi): harden VM identity registries (#869). The remaining VM-owned canonical-object and contiguous-vector identity registries now use independent lazy secure exact-identity maps with failure-atomic first publication and allocation-free moving-GC rekeying. Full validation evidence is recorded in #869.

9 days ago

Follow-up #870 is complete in 17dea421 — fix(private-abi): harden lifecycle registry (#870). The process-global private lifecycle table now uses independent lazy secure exact-pointer hashing, failure-atomic publication, centralized exact retirement, and empty-table reset/reseed, with Debug/ReleaseSafe/TSan, external fixtures, fuzz, full units, ABI audits, and docs gates passing.

Sign in to comment on this issue.