Fix use-after-free when a second JS scope registers on an operation

XMLWordPrintableJSON

    • Type: Task
    • Resolution: Fixed
    • Priority: Major - P3
    • 9.1.0-rc0, 9.0.0-rc2
    • Affects Version/s: None
    • Component/s: Build
    • None
    • Query Integration
    • Fully Compatible
    • v9.0
    • QO 2025-02-17
    • 200
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      A `WasmtimeImplScope` registers itself on its `OperationContext` through a single `WasmtimeScopeRef` decoration slot so interrupts can find it. When a second scope registered on the same opCtx (e.g. `$where` parsing acquiring a pooled scope while another scope was still registered), `WasmtimeScriptEngine::registerOperation()` silently overwrote the slot. The displaced scope kept its raw `_opCtx` back-pointer but lost the teardown that clears it when the opCtx is destroyed, so the scope's destructor dereferenced freed memory (ASan heap-use-after-free in `OperationContext::getClient()`).

      Changes:

      • `wasmtime_engine.cpp/.h`: `registerOperation()` severs a displaced scope's back-pointer (invokes its `onTeardown`) before overwriting the slot; `unregisterOperation()` now takes the scope and only clears the slot if that scope still owns it, so a stale unregister cannot wipe a newer registration.
      • `engine.cpp`: `getPooledScope()` checks for interrupt before registering the operation on a scope, so an already-killed operation fails before partially setting up JS state; `ScopeCache::release()` unregisters scopes before pooling as defense-in-depth (covers the early-return paths that destroy a scope without resetting it).
      • `scope_test_concurrency.cpp`: three regression tests. `SecondRegistrationSeversPreviousScopeBackPointer` deterministically reproduces the use-after-free before the fix under ASan; `GetPooledScopeThrowsOnInterruptedOpCtx` fails before the fix on any build.

            Assignee:
            Lee Maguire
            Reporter:
            Lee Maguire
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: