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

Buffer.allocUnsafe causes "Conditional jump..." on valgrind #26464

Closed
kotsss opened this issue Mar 6, 2019 · 5 comments
Closed

Buffer.allocUnsafe causes "Conditional jump..." on valgrind #26464

kotsss opened this issue Mar 6, 2019 · 5 comments
Labels
buffer Issues and PRs related to the buffer subsystem.

Comments

@kotsss
Copy link

kotsss commented Mar 6, 2019

Working with valgrind to clean a giant networking application I was getting "Conditional jump or move depends on uninitialised value(s)" with js stacks (see below), took a long time but managed to zero in on reason.

==28440== Conditional jump or move depends on uninitialised value(s)
==28440==    at 0xA7EBB08780A: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???
==28440==    by 0xA7EBB0118D4: ???

Running the following code through valgrind will trigger the error

const alloc = process.env.SAFE ? Buffer.alloc : Buffer.allocUnsafe;
var buf = alloc(20);
buf.writeInt32BE(123, 2);

>valgrind --gen-suppressions=yes --leak-check=full /var/lib/nave/global/10.13.0/bin/node a.js

I've managed to trace the cause to lib/internal/buffer.js:checkBounds accessing the buffer that isn't initialized.
Buffer.allocUnsafe used by ws npm module

Shachar

@ChALkeR ChALkeR added the buffer Issues and PRs related to the buffer subsystem. label Mar 6, 2019
@bnoordhuis
Copy link
Member

Thanks for the report. I'd say that's expected given that checkBounds() checks that buf[offset] === undefined, which has been observed to be a little faster than checking that offset < buf.length.

V8's runtime loads the byte at buf[offset]. That's a random value if you use Buffer.allocUnsafe() because it doesn't zero the memory.

I'm not sure if this is something we actually want to fix because there's no real bug.

I suppose the strongest argument for addressing it is that it can't be suppressed because the comparison takes place in runtime-generated code - the address and even the exact layout of the code can change between invocations.

@kotsss
Copy link
Author

kotsss commented Mar 7, 2019

buf[offset] === undefined, which has been observed to be a little faster than checking that offset < buf.length.

Is that really true? (I'm amazed that it amounts to something noticeable - I'm curious to test it myself)

I'm not sure if this is something we actually want to fix because there's no real bug.

I'm trying to understand why it's not a real bug, my best guess is that no matter what random memory value is read it won't cause Buffer [] operator to return undefined value as long as it's inside the array bounds. Am I getting this right?

I suppose the strongest argument for addressing it is that it can't be suppressed because the comparison takes place in runtime-generated code - the address and even the exact layout of the code can change between invocations.

IMHO, almost any fix to this will have, at least, the 'penalty' of changing to checking offset<buf.length.
So if someone is already using allocUnsafe I can deduce 2 things about them: performance sensitive and know what they are doing (because working with uninitialized memory/buffer intentionally can lead to much worse bugs).
So I would suggest not checking bounds if using allocUnsafe because as the name states it's 'unsafe' - you're on your own.

@kotsss kotsss closed this as completed Mar 7, 2019
@kotsss kotsss reopened this Mar 7, 2019
@BridgeAR
Copy link
Member

BridgeAR commented Mar 7, 2019

Is that really true? (I'm amazed that it amounts to something noticeable - I'm curious to test it myself)

I was able to replace multiple error checks with buf[offset] === undefined and newer V8 versions have a nice OOB protection that works relatively fast. If buf[offset] is indeed undefined the original checks are executed to detect what exactly is wrong (e.g., wrong input value, out of bounds, float instead of integer...).

@bnoordhuis
Copy link
Member

my best guess is that no matter what random memory value is read it won't cause Buffer [] operator to return undefined value as long as it's inside the array bounds. Am I getting this right?

Yes, that's right.

@BridgeAR
Copy link
Member

I am going to close this since it does not really seem to be a bug.

Please feel free to comment in case this should be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
buffer Issues and PRs related to the buffer subsystem.
Projects
None yet
Development

No branches or pull requests

4 participants