Skip to content

embedder/resources: no host-side lend tracking — GC backstop can run a dtor under a live guest borrow; backstop swallows dtor traps #86

Description

@lann

Severity: high — use-after-free of the rep where the reference traps.

There is no host-side analogue of num_lends: lowering a host-held own
wrapper as borrow<R> records nothing (takeRep(w, false, ...),
embedder/resources.ts:113+), and the FinalizationRegistry backstop
(:54-63) checks only s.valid && s.owns.

The reference models host-held owns as table entries whose num_lends is
bumped on borrow-lift (definitions.py:890-892, 1516-1521), making drop trap
while lent (definitions.py:2325). wasmtime mirrors this (host_table +
lend tracking, runtime/vm/component/resources.rs).

Repro: host passes an own wrapper as borrow<R> into a guest call; the
wrapper is unreferenced after lowering; GC finalizes during the in-flight
call (trivially possible under a JSPI park) -> guest dtor runs while the
guest holds a live borrow of the same rep.

Independent second defect: the backstop's catch {} (:59-61) swallows a
trapping dtor with no instance poisoning — the reference propagates the
trap and leaves the impl instance unenterable. A half-destroyed guest
instance stays re-enterable.

Fix shape: WrapperState gains a lend counter — increment at borrow
lowering, decrement at the same points guest-side lender release happens
(subtask resolve / call return); dropWrapper and the backstop defer
while lent (mark pending-drop; execute on last release through the gated
dtor path of the dtor-gating issue); backstop dtor traps route into
instance poisoning + the host-failure channel instead of catch {}.

Found in the 2026-08-10 adversarial conformance review (runtime + translator vs component-model @ 73b7ad5 definitions.py; wasmtime-environ 47.0.3 treated as trusted).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions