Commit 2ff325e
Node-API (Chakra): fix heap corruption when an ObjectWrap constructor throws (#199)
## What
Fixes a heap corruption in the ChakraCore Node-API implementation when
an `ObjectWrap`-based constructor throws.
Split out of #198 as an
independent fix, per review.
## Problem
When a wrapped (`napi_wrap`) constructor throws, the C++ `ObjectWrap`
instance is destroyed by stack unwinding inside the callback, but the
wrap finalizer registered by `napi_wrap()` stays attached to `this`.
`~ObjectWrap()` cannot detach it, because `napi_get_reference_value()`
returns null for the wrap's weak (refcount 0) reference. A later GC then
runs the finalizer on the freed native instance — a use-after-free that
surfaces as non-deterministic `STATUS_HEAP_CORRUPTION` (`0xC0000374`).
## Fix
`Core/Node-API/Source/js_native_api_chakra.cc`:
- In `ExternalCallback`, after a construct call that left a pending JS
exception, detach the wrap (`napi_remove_wrap`) before returning, then
re-set the exception so it is preserved across the cleanup.
- Guard `napi_remove_wrap` against a `nullptr` `result` out-param (the
finalizer-cleanup call above passes `nullptr`), so it no longer
dereferences a null pointer.
## Test
Adds a regression test (`Tests/UnitTests/Scripts/tests.ts`) that throws
from a wrapped constructor 100× to create many dangling wraps, then
allocates/decodes to exercise the heap and surface any corruption within
the run. It uses `TextDecoder` as a convenient throwing wrapped
constructor; the test passes on `main`'s existing `TextDecoder` behavior
and is independent of the TextDecoder label change in #198.
## Verification
Reliably reproduced as `STATUS_HEAP_CORRUPTION` on Chakra (Win32
x64/x86) before the fix; passes after.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 272f6a9 commit 2ff325e
2 files changed
Lines changed: 39 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
172 | 172 | | |
173 | 173 | | |
174 | 174 | | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
175 | 196 | | |
176 | 197 | | |
177 | 198 | | |
| |||
1748 | 1769 | | |
1749 | 1770 | | |
1750 | 1771 | | |
1751 | | - | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
1752 | 1775 | | |
1753 | | - | |
| 1776 | + | |
1754 | 1777 | | |
1755 | 1778 | | |
1756 | 1779 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1490 | 1490 | | |
1491 | 1491 | | |
1492 | 1492 | | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
1493 | 1507 | | |
1494 | 1508 | | |
1495 | 1509 | | |
| |||
0 commit comments