fix(sbmd): harden mquickjs GC safety#244
Conversation
mquickjs uses a moving, compacting GC. Raw JSValue handles can go stale when allocations occur between property reads, stack growth, or argument construction. This change roots transient and retained values to prevent stale-handle and use-after-move behavior. Changes: - Root intermediate exception/property/array/result values with SafeJSValue in runtime, loader, util, invoker, and parser paths. - Root handler and handlerContext before allocation-heavy operations. - Split create-and-attach patterns in SafeJSValue helpers where argument evaluation order could pass stale parents under moving GC. - Refine SbmdDriver teardown: detach held roots only when shared context is absent during runtime shutdown. - Add a Date constructor compatibility shim for generated stdlib tables that reference js_date_constructor. - Update SBMD tests to use rooted function accessors and root intermediate JS values in assertions. - Enabled DEBUG_GC in mquickjs Docker build to help expose problematic JSValue usage. - Bump mquickjs Docker pin and container version for reproducible builds aligned with these fixes.
There was a problem hiding this comment.
Pull request overview
This PR hardens the SBMD mquickjs integration against stale-handle/use-after-move issues caused by mquickjs’s moving/compacting GC, by systematically rooting transient and retained JSValues (via SafeJSValue) across allocation-heavy operations. It also updates the SBMD test suite to follow the new rooting rules and tweaks the mquickjs Docker build to help surface GC-safety problems.
Changes:
- Root intermediate/property/exception/handler values across loader, runtime, invoker, executor, and test paths to prevent stale
JSValuehandles under moving GC. - Refine handler/root lifetime behavior in
SbmdDriverteardown and during handler holding to avoid dangling GC-root nodes during runtime shutdown. - Update container tooling (mquickjs pin, DEBUG_GC) and add a Date constructor shim for generated stdlib compatibility.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| docker/version | Bumps Docker container/version tag used by repo tooling. |
| docker/patches/mquickjs/CMakeLists.txt | Enables DEBUG_GC in the patched mquickjs build to expose unsafe JSValue usage. |
| docker/Dockerfile | Updates the pinned mquickjs commit for reproducible builds aligned with GC-safety fixes. |
| core/test/src/SbmdHandlerInvokerTest.cpp | Converts raw JSValue intermediates to SafeJSValue to keep tests GC-safe. |
| core/test/src/SbmdDriverTest.cpp | Roots handler/args in helper invocation path; switches to rooted handler accessors (Fn()). |
| core/test/src/SbmdDispatchTest.cpp | Roots handler/args for invocations and uses rooted handler accessor (Fn()). |
| core/deviceDrivers/matter/sbmd/SbmdDriver.cpp | Adjusts destructor/root teardown behavior and avoids re-holding already-rooted handlers. |
| core/deviceDrivers/matter/sbmd/SafeJSValue.h | Splits create-and-attach patterns to avoid argument-evaluation hazards under moving GC. |
| core/deviceDrivers/matter/sbmd/mquickjs/SbmdResultExecutor.cpp | Roots result/ops/terminal and intermediates during result parsing. |
| core/deviceDrivers/matter/sbmd/mquickjs/SbmdLoader.cpp | Roots extracted registration/handlers/supplements and intermediates during driver extraction. |
| core/deviceDrivers/matter/sbmd/mquickjs/SbmdJsUtil.cpp | Roots property reads/exception values and array/object traversal intermediates. |
| core/deviceDrivers/matter/sbmd/mquickjs/SbmdHandlerInvoker.cpp | Roots handler function and handlerContext across stack checks and arg building. |
| core/deviceDrivers/matter/sbmd/mquickjs/MQuickJsStdlib.c | Adds js_date_constructor shim for generated stdlib table compatibility. |
| core/deviceDrivers/matter/sbmd/mquickjs/MQuickJsRuntime.cpp | Roots pending exception object and intermediates while constructing diagnostic strings. |
Comments suppressed due to low confidence (1)
core/deviceDrivers/matter/sbmd/mquickjs/SbmdJsUtil.cpp:165
- Same GC-safety issue as GetUint16Array(): each element should be rooted across JS_ToUint32() to avoid stale handles if a conversion allocates and triggers GC.
for (uint32_t i = 0; i < len; i++)
{
JSValue elem = JS_GetPropertyUint32(ctx, rootedArray.Get(), i);
uint32_t val = 0;
JS_ToUint32(ctx, &val, elem);
result.push_back(val);
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
core/deviceDrivers/matter/sbmd/mquickjs/SbmdJsUtil.cpp:165
- GetUint32Array() still holds a raw JSValue element and then calls JS_ToUint32 on it. Under mquickjs's moving/compacting GC, JS_ToUint32 may allocate/GC and relocate the element, making
elemstale and causing a use-after-move. Root the element the same way GetUint16Array/GetStringArray already do.
for (uint32_t i = 0; i < len; i++)
{
JSValue elem = JS_GetPropertyUint32(ctx, rootedArray.Get(), i);
uint32_t val = 0;
JS_ToUint32(ctx, &val, elem);
result.push_back(val);
}
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
cleithner-comcast
left a comment
There was a problem hiding this comment.
The comments are in excess, I think.
mquickjs uses a moving, compacting GC. Raw JSValue handles can go stale when allocations occur between property reads, stack growth, or argument construction. This change roots transient and retained values to prevent stale-handle and use-after-move behavior.
Changes: