node-api: External type tag check fails if the original tag struct changes or disappears (regression in Node 20.12 and Node 21.6) #52387
Labels
node-api
Issues and PRs related to the Node-API.
Version
v20.12.1
Platform
Subsystem
node-api
What steps will reproduce the bug?
A change introduced in Node 20.12 and Node 21.6 changes the semantics of tagging External values, and introduces a possible memory bug.
This pull request is responsible for the change: #51149
The code in this commit stores the type tag pointer and not the 128-bit value inside. This breaks some pre-existing code that were using temporary tags (made on the stack). It also means that unloading the module will cause existing External objects to have a tag pointer that points... "nowhere" (use-after-free).
This violates what is stated in the N-API documentation:
For objects, nothing has changed since type tags are still stored by value in a private property (in a BigInt). So the pointer does not get stale.
I've made a small reproduction available here: https://git.sr.ht/~koromix/napi_tag_bug
To reproduce, execute these commands:
What is the expected behavior? Why is that the expected behavior?
Expected result with Node v20.11.1:
This works because the type tag is embedded by value instead of just the pointer to the tag passed to
napi_type_tag_object()
.What do you see instead?
Wrong result with Node v20.12.1:
Here it fails because the reproduction code explicitly clears out the tag value (which lives on the stack by the way) and the External value refers to it (instead of copying it).
Proposed fix and test
The following patch fixes the bug: store_tag_value.patch
I propose the following change to the test suite to prevent future regressions: prevent_tag_pointers.patch
I can make a pull request if you prefer.
The text was updated successfully, but these errors were encountered: