-
Notifications
You must be signed in to change notification settings - Fork 229
Description
Description
The exported nativeTexture() function in pls_binding.mm is the only renderer API that does not guard against a nullptr renderer argument. When called with a freed or null pointer, it crashes with EXC_BAD_ACCESS (SIGSEGV) / KERN_INVALID_ADDRESS.
Every other exported function in the same file includes a null check:
// ✅ Has null check
EXPORT bool clear(MetalTextureRenderer* renderer, bool clear, uint32_t color) {
if (renderer == nullptr) { return false; }
renderer->begin(clear, color);
return true;
}
// ✅ Has null check
EXPORT rive::Renderer* makeRenderer(MetalTextureRenderer* renderer) {
if (renderer == nullptr) { return nullptr; }
return renderer->renderer();
}
// ❌ Missing null check — crashes
EXPORT void* nativeTexture(MetalTextureRenderer* renderer) {
return (__bridge void*)renderer->currentTargetTexture();
}
Crash Report
Process: XXXX - [71482]
Code Type: ARM-64 (Native)
OS Version: macOS 15.7.3 (24G419)
Crashed Thread: 65 Dispatch queue: com.airplaystudio.mixer.render
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00006001e1d78e90
Thread 65 Crashed:
0 rive_native nativeTexture + 8
1 our_plugin [RiveTextureBridge registerRendererPointer:asSlot:]_block_invoke + 172
Reproduction Context
This crash occurs when nativeTexture() is called from a render loop on a background dispatch queue while destroyRiveRenderer() runs on the platform thread. The 1-second batched _disposeTexture() Timer in _NativeRenderTexture creates a window where the old MetalTextureRenderer* is freed but external callers may still hold the pointer.
Race window:
- performLayout() triggers makeRenderTexture() with new dimensions
- Old renderer is queued for destruction via 1-second Timer
- External render loop calls nativeTexture(oldRenderer) before onTextureChanged callback fires
- destroyRiveRenderer() frees the old renderer on the platform thread
- nativeTexture() dereferences the freed pointer → SIGSEGV
Suggested Fix
EXPORT void* nativeTexture(MetalTextureRenderer* renderer) {
+ if (renderer == nullptr) { return nullptr; }
return (__bridge void*)renderer->currentTargetTexture();
}
Environment
Package: rive_native 0.1.2
Platform: macOS 15.7.3 (ARM64)
Flutter: 3.x
File:
native/src/pls_binding.mm , line 246–249