Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault in node 12 #16

Closed
mhofman opened this issue Apr 23, 2019 · 18 comments
Closed

Segfault in node 12 #16

mhofman opened this issue Apr 23, 2019 · 18 comments

Comments

@mhofman
Copy link

mhofman commented Apr 23, 2019

Not sure what's going on, but in Node 12, I'm getting some segfaults. I've traced it to ObjectInfo.target calls after the target has been collected, but it doesn't seem to always trigger.

To reproduce, just run the test suite of your package, or npm run test:node of https://github.com/mhofman/tc39-weakrefs-shim

@addaleax
Copy link
Contributor

Hi! Thanks, I’ve not forgotten your other issue either, but I’ll try to look into this sooner rather than later. The native addon part isn’t particularly complex, so this might well be a bug in Node.

@mhofman
Copy link
Author

mhofman commented Apr 23, 2019

Yeah I looked at the source of the native addon and I really don't see why it would segfault. My C++ development days are way in the past so I couldn't easily troubleshoot further.

@mhofman
Copy link
Author

mhofman commented Apr 23, 2019

Interestingly, the tests in this package also fail on node 11, but the tests in mine work fine on node 11. Maybe there are 2 different segfaults triggers.

@addaleax
Copy link
Contributor

addaleax commented Apr 29, 2019

Interesting! Sorry it took me a while to get to it, but this looks like it’s a bug in the N-API C++ convenience wrapper. I’ll post a fix shortly :)

Edit: nodejs/node-addon-api#475

addaleax added a commit to addaleax/node-api that referenced this issue Apr 29, 2019
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

Fixes: node-ffi-napi/weak-napi#16
@VoltanaDMG
Copy link

The provided solution by @addaleax works fine for Node 10.x and higher versions (tested it for Node v10.x, v11.x, v12.x). But the solution breaks the tests of the weak-napi module for Node v9.x and lower.
I got the following error for test case create():
*** Error in '/home/travis/.nvs/node/9.11.2/x64/bin/node': double free or corruption (fasttop): 0x000000000305edf0 ***

Here is a screenshot of test run for Node v9.x:
weak-napi_fix_solution_produces_error

@addaleax
Copy link
Contributor

addaleax commented May 3, 2019

@VoltanaDMG Fascinating … I’ll take a look.

@addaleax
Copy link
Contributor

addaleax commented May 3, 2019

I think this is happening because nodejs/node#24494 isn’t on v8.x. That’s not ideal, and I’ll have to think about whether/how to work around that.

@VoltanaDMG
Copy link

VoltanaDMG commented May 3, 2019

Hm, this isn't good, a lot of people and companies are still using v8.x.x.
I will look into it as well, because there must be solution for mainline versions.

Edit: Fixed some typos 🤣

@mhdawson
Copy link

mhdawson commented May 9, 2019

From what I remember nodejs/node#24494 was not backported to 8.x because the original issue seemed to occur in 10.x but not 8.x (I think the code might have been different too). We may want to consider backporting if it affects 8.x as well.

@addaleax
Copy link
Contributor

addaleax commented May 9, 2019

@mhdawson The code appeared to be the same to me when looking into this; so it should be affected too. In general, it seems like a bad idea to me to backport only some N-API changes.

That being said, backporting to v8.x wouldn’t affect already-released versions, so it doesn’t really solve the problem – from the looks of it, some versions of N-API want one thing, some versions of N-API want another thing and there’s no way to detect which ones want what. That’s just kind of fundamentally bad for a stable API like N-API.

It might make sense to try and figure out what caused this to fail in v12.x, and if possible try to undo that. That would still leave the C++ wrapper API broken until a new major release comes out, but would fix this particular bug and I guess that’s just something we may have to live with.

@mhdawson
Copy link

mhdawson commented May 9, 2019

If the code looks the same then I must have remembered wrong. In that case we should look at backporting.

A bug in the C++ wrapper which only affects some versions (or by bad luck on shows up in some versions even though it could affect any of them) is painful. It would be good to understand if there is something different in 12.x that caused this to surface or its simply different timing.

If it was that `some versions of N-API want one thing, some versions of N-API want another thing' then the N-API version might help (although that should not be the case anyway since versions should be adding, not changing behaviour). Instead, I think what you are saying is that different versions of Node.js with the same N-API version seem to want something different. The fundamental problem seems to be that the fix for what we see in one version makes the problem much more visible in another.

In terms of backporting it not fixing the problem in earlier versions that is sometimes going to be the case and I'm not sure how we can avoid needing an upgrade to the latest v8.x if an application hits that bug unless we can work around it in the wrapper or calling code.

@mhdawson
Copy link

mhdawson commented May 9, 2019

@addaleax if you want me to start putting together a backport for 8.x just let me know.

@addaleax
Copy link
Contributor

addaleax commented May 9, 2019

Actually, from bisecting it looks like nodejs/node#24494 also introduced the crash here in the first place… I guess I’ll have to dig a bit more

@splitice
Copy link

Running @addaleax's branch but it doesnt appear to resolve the issue 100% still seeing the odd segfault in node.

Unfortunately it's so uncommon I haven't had GDB attached during it (and core dumps arent working on this system).

@ronag
Copy link

ronag commented Jul 21, 2019

I assume this package is unsafe for use until nodejs/node-addon-api#475 has landed?

@michalburger1
Copy link

I'd like to use this exclusively in Node 12, is there any workaround or easy fix I could apply myself that would make it work, ignoring any incompatibilities with previous versions?

@rijnhard
Copy link

ping, any movement here?

@addaleax
Copy link
Contributor

ping, any movement here?

Not really, object lifetime management in N-API is just a huge clusterfuck at this point and while this is on my TODO list, it just takes a lot of focus and energy to try and understand what N-API is doing across the different versions.

If anybody is interested in working on this before I get back to it, please feel free to do so.

addaleax added a commit to addaleax/node-api that referenced this issue Jan 14, 2020
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

Fixes: node-ffi-napi/weak-napi#16
addaleax added a commit to addaleax/node-api that referenced this issue Jan 16, 2020
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
Co-authored-by: Gabriel Schulhof <[email protected]>
addaleax added a commit to addaleax/node-api that referenced this issue Jan 16, 2020
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
Co-authored-by: Gabriel Schulhof <[email protected]>
gabrielschulhof pushed a commit to nodejs/node-addon-api that referenced this issue Jan 17, 2020
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: #475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
JorgenEvens added a commit to ambassify/throttle that referenced this issue Feb 20, 2020
`weak-napi` potentially causes segfault on node >=12

node-ffi-napi/weak-napi#16
gabrielschulhof pushed a commit to gabrielschulhof/node-addon-api that referenced this issue May 11, 2020
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: nodejs#475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
gabrielschulhof pushed a commit to gabrielschulhof/node-addon-api that referenced this issue Jun 12, 2020
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: nodejs#475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
kevindavies8 added a commit to kevindavies8/node-addon-api-Develop that referenced this issue Aug 24, 2022
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: nodejs/node-addon-api#475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
Marlyfleitas added a commit to Marlyfleitas/node-api-addon-Development that referenced this issue Aug 26, 2022
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: nodejs/node-addon-api#475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
wroy7860 added a commit to wroy7860/addon-api-benchmark-node that referenced this issue Sep 19, 2022
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: nodejs/node-addon-api#475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
johnfrench3 pushed a commit to johnfrench3/node-addon-api-git that referenced this issue Aug 11, 2023
Currently, when the `ObjectWrap` constructor runs, it calls
`napi_wrap()`, adding a finalize callback to the freshly created
JS object.

However, if the `ObjectWrap` instance is prematurely deleted,
for example because a subclass constructor throws – which seems
like a reasonable scenario – that finalize callback was not removed,
possibly leading to a use-after-free crash.

This commit adds a call `napi_remove_wrap()` from the `ObjectWrap`
destructor,  and a test for that scenario.

This also changes the code to use the correct pointer type
in `FinalizeCallback`, which may not match the incorretct one
in cases of multiple inheritance.

Fixes: node-ffi-napi/weak-napi#16
PR-URL: nodejs/node-addon-api#475
Reviewed-By: Hitesh Kanwathirtha <[email protected]>
Reviewed-By: Gabriel Schulhof <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Co-authored-by: Gabriel Schulhof <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants