Parents: #493, #495 Related: #156, #396, #870
Problem
ZJSInspectorSessionRelease and ZJSInspectorSessionDispatch cast an
arbitrary embedder-provided ZJSInspectorSessionRef and read
session.state before proving that the address names a live registered
session. The process registry is an ordered linear pointer list used by
broadcasts, and only the private reporter-agent lookup currently validates
membership before dereference.
The worker transport has the same boundary:
ZJSWorkerInspectorSessionDispatch, Pump, and Release cast and inspect
the supplied ZJSWorkerInspectorSessionRef without any process membership
registry. Null is inert, but a forged or retired non-null handle can therefore
be dereferenced before rejection. Returning allocator addresses also exposes
session allocation identity and permits stale-address aliasing if storage is
later reused.
Required design
- Return nonzero secure capability tokens rather than allocator addresses for both opaque session types; token entropy must be independent from bucket hashing and live-token collisions must retry without overwrite.
- Extend the existing mutex-protected process inspector registry with one lazy, securely seeded exact-token index whose tagged values distinguish context sessions from worker sessions.
- Preserve context-session creation order for broadcasts while making arbitrary handle validation exact and constant expected time.
- Publish a session only after token generation and every required ordered/index allocation succeeds; entropy or backing-allocation failure must roll back without exposing a partial handle or leaking registry state.
- Validate exact membership, transport kind, and owner-thread/liveness state under the registry lock before dereferencing anything obtained from a caller-provided handle.
- Retain context sessions across dispatch/reentrant callbacks so release remains deferred until the active operation has unwound.
- Remove exactly once on physical teardown; reset/free an empty index so a later lifecycle obtains fresh entropy.
- Preserve worker queue, pump, detach fallback, worker-first shutdown, context pause ownership, broadcast order, and ABI signatures/layouts.
No-workaround rules
- No raw-pointer handle or dereference before membership validation, predictable or address-derived token/seed, shared token/hash entropy, hash-only equality, linear validation scan, tombstone-only retirement, leaked empty allocation, arbitrary registry cap, disabled reentrancy, weakened thread affinity, serialized global inspector callback, or ABI change.
Acceptance
- Null, forged, wrong-transport, foreign-thread, duplicate-release, and retired context inspector capabilities are inert; dispatch returns false without dereference.
- The same guarantees hold for worker inspector dispatch/pump/release, with
invalid pump returning
closed. - Default-seed collision families disperse in the secure tagged index; exact live-token collision retries without overwrite or cross-transport confusion.
- Token/hash entropy and first allocation failures are empty, unseeded, leak-free, and retryable; final removal resets storage and later insertion obtains fresh entropy.
- Multi-session broadcast order, callback-driven release, detach/pause ownership, worker-first close, and concurrent/wrong-thread behavior remain exact.
- Focused tests pass in Debug, ReleaseSafe, and TSan; C inspector and worker inspector fixtures, ABI audits, threadfuzz, full units, and docs gates pass.