You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix: resolve memory leaks, use-after-free, and correctness issues in … (#1408)
Comprehensive audit and fix of all C++ source files under `src/` that implement
N-API bindings for the ROS2 rcl library. Five categories of issues were
identified and resolved.
### 1. Use-after-free in context deleter lambda
**File:** `src/rcl_context_bindings.cpp`
Changed `[&env]` capture to `[env]` in the lambda deleter passed to
`RclHandle`. Since `Napi::Env` is a lightweight pointer wrapper, capturing by
value copies the `napi_env` pointer safely. Capturing by reference created a
dangling reference because the lambda outlives the stack frame where `env` was
declared — the deleter runs during garbage collection, long after
`CreateContext` returns.
### 2. Memory leaks on early-return error paths
**Files:** 9 binding files
When `rcl_*_init()` fails, the previously `malloc`'d handle was not freed
before throwing and returning. Added `free()` calls before the error throw in:
- `src/rcl_node_bindings.cpp` — `CreateNode`
- `src/rcl_publisher_bindings.cpp` — `CreatePublisher`
- `src/rcl_timer_bindings.cpp` — `CreateTimer` (both `ROS_VERSION > 2305` branches)
- `src/rcl_guard_condition_bindings.cpp` — `CreateGuardCondition`
- `src/rcl_client_bindings.cpp` — `CreateClient`
- `src/rcl_service_bindings.cpp` — `CreateService`
- `src/rcl_action_client_bindings.cpp` — `ActionCreateClient`
- `src/rcl_action_server_bindings.cpp` — `ActionCreateServer`
- `src/rcl_lifecycle_bindings.cpp` — `CreateLifecycleStateMachine` (all 3 version branches)
### 3. Missing return after throw
**File:** `src/rcl_type_description_service_bindings.cpp`
Added `free(service)` and `return env.Undefined()` after
`ThrowAsJavaScriptException()` on init failure. Without the return, execution
continued and wrapped the uninitialized handle into an `RclHandle`, which would
later attempt to finalize invalid memory.
### 4. Static variable not reset between calls
**File:** `src/executor.cpp`
Added `handle_closed = false;` immediately after the `static bool handle_closed`
declaration in `Executor::Stop()`. Static local variables are initialized only
once; on a second call to `Stop()`, `handle_closed` would still be `true` from
the previous invocation, causing the `while (!handle_closed)` loop to be
skipped entirely — the `uv_close` callback would never run and the async handle
would leak.
Fix: #1407
0 commit comments