ReviewOS

zig-utils/zig-js

Interpreter: securely seed AST and RegExp identity caches

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

Parent: #493 Related: #473, #760, #770, #855, #856

Problem

Four interpreter-local tables remain default-seeded pointer maps whose populations are controlled by JavaScript source/runtime activity:

  • invocation-local Annex B eligible declaration-node identity;
  • tree-walker string-literal AST-site cache;
  • cross-tier tagged-template AST-site cache;
  • compiled-RegExp to mutable matcher-state cache.

A realm can create many distinct sites/RegExp instances in attacker-chosen order. Arena placement and ASLR are not an explicit collision defense. Linear scans, cache bypass, or forced VM/tree-walker fallback would either recover superlinear work or change observable identity/state semantics.

Implementation

  • Add one lazy interpreter-owned exact-identity hash context sourced through the existing per-interpreter secure seed stream.
  • Convert the four maps to keyed usize identity indexes while preserving exact pointer equality and values.
  • Share the context across nested calls and all four tables; do not request entropy per table or site.
  • Publish the context only after the first successful identity insertion; empty lookups remain allocation- and entropy-free.
  • Preserve scratch/arena ownership, RegExp matcher mutability, tagged-template cross-tier identity, literal GC rooting/relocation, and Annex B eligibility lifetime.
  • Keep the Context-owned debugger registry out of scope because it has a distinct shared-lock/publication contract.

Acceptance

  • All four interpreter-local maps use the keyed context; their default pointer maps are gone.
  • A deterministic legacy-collision family disperses under an installed seed with exact get/contains semantics.
  • Failed first insertion leaves the identity context and table unpublished; retry succeeds.
  • String literal, tagged template (tree-walker and VM), RegExp matcher reuse, and Annex B node eligibility remain exact.
  • Precise-GC tracing and moving relocation preserve cached values and map membership.
  • Focused interpreter/VM/GC Debug and TSan, full units, exact-parent Test262, threadfuzz, and ABI gates pass.

No-workaround rules

No source blacklist, site count cap, linear scan, cache disablement, forced tier fallback, address-secrecy assumption, predictable seed, per-table entropy request, third-party map, or weakened identity semantics.

9 days ago

Implemented and pushed to main in fix(interpreter): seed AST identity caches (#857).

The four interpreter-owned pointer maps now share one lazy, securely seeded exact-identity context. First-insert OOM leaves both context and table unpublished; no default pointer map, fallback seed, scan, cap, or semantic bypass remains.

Evidence:

  • focused Debug + TSan: 7/7 identity/string/template/VM/RegExp/Annex B/relocation probes pass, 0 leaks;
  • full units: 2270 passed, 1 skipped, 0 failed, 0 leaked across 10 shards;
  • exact-parent Test262: 1560/1560 across Annex B, RegExp literal/exec, string literal, template literal, and tagged-template inventories; all six diagnostics byte-identical, 0 flips;
  • threadfuzz: 400 programs, 0 failures;
  • public C API: 117/117; Home private ABI: 447/447 plus 392/392 runtime shims.
9 days ago

Follow-up #860 has landed: fix(debugger): seed statement location registry (#860). It covers the Context-owned shared debugger AST registry that was intentionally outside #857’s mutator-local identity-cache scope, deriving one lazy context from the realm Shape secret and preserving the existing no-GIL lock lifecycle.

Sign in to comment on this issue.