Retain trace-proxy callback (fix Hermes use-after-free) - #149
Open
beaucollins wants to merge 3 commits into
Open
Retain trace-proxy callback (fix Hermes use-after-free)#149beaucollins wants to merge 3 commits into
beaucollins wants to merge 3 commits into
Conversation
JavaScriptRuntimeTraceProxyCallable held the wrapped callback as a bare, non-owning JSValue. Under Hermes the callback's pooled ManagedHermesValue could be released to zero and its slot recycled while the proxy still referenced it, so a later invocation hit a dangling handle and threw "Value is not a function". Hold it as an owning JSValueRef instead, retained for the proxy's lifetime. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📊 PR Size: size/XSTotal changes: 6 lines (1 files) Top files changed:
Size calculated as additions + deletions. Labels: XS (<10), S (<50), M (<250), L (<1000), XL (1000+) |
Wraps an inline closure in runtime.makeTraceProxy, forces GC, then invokes the proxy. Pre-fix under Hermes the unrooted closure was collected and its slot recycled, so the call threw 'Value is not a function'. Runs across engines via the parametrized RuntimeFixture. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
| Test Suite | Result |
|---|---|
| valdi_web Integration Test | ✅ success |
| Snapshot Tests | ✅ success |
| macOS: C++ & Platform Tests | ✅ success |
| Linux: Registry Validation | ❌ cancelled |
| Valdi Smoke Tests | ✅ success |
| Linux: C++ Tests | ❌ cancelled |
| Linux: Build Compiler | ✅ success |
| Linux: Build & Export | ❌ cancelled |
| API Surface Check | ✅ success |
| Linux: Module Tests | ✅ success |
| Linux: Hotreload Smoke | ✅ success |
Some tests failed. Please check the workflow logs for details.
🚀 Bazel remote cache is now enabled - future builds will be faster!
Workflow: Valdi CI
runtime.makeTraceProxy is only bound under kTracingEnabled, so the test can only exercise the bug in a tracing build. Probe for the binding and GTEST_SKIP when it's absent instead of failing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
JavaScriptRuntimeTraceProxyCallablestored the wrapped callback as a bare, non-owningJSValue. Under the Hermes engine the callback's pooledManagedHermesValuecould be released to zero and its slot recycled while the proxy still referenced it, so a later invocation hit a dangling handle and threw"Value is not a function".Fix
Hold the callback as an owning
JSValueRefviaJSValueRef::makeRetained, retained for the proxy's lifetime and released in the destructor. This matches how the rest ofJavaScriptRuntime.cppretains values kept across native calls (e.g.JSValueRef::makeRetained,JSValueRefHolder::makeRetainedCallback).Notes
Only reproduces under Hermes (QuickJS's value model doesn't dangle a bare handle) and only when the tracing layer wraps a callback in a trace proxy. Verified with a Hermes build: crash gone across repeated launches.