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

dgram: socket.send() crash when input array is modified #6616

Closed
bnoordhuis opened this issue May 6, 2016 · 6 comments
Closed

dgram: socket.send() crash when input array is modified #6616

bnoordhuis opened this issue May 6, 2016 · 6 comments
Labels
confirmed-bug Issues with confirmed bugs. dgram Issues and PRs related to the dgram subsystem / UDP.

Comments

@bnoordhuis
Copy link
Member

bnoordhuis commented May 6, 2016

#4374 introduces a bug: it makes socket.send() accept an array but it's not resilient against that array getting modified afterwards:

$ node -e '
  var a = ["boom!"], s = dgram.createSocket("udp4");
  s.send(a, 1234);
  a.splice(0);
'
node: ../deps/uv/src/unix/udp.c:390: uv__udp_send: Assertion `nbufs > 0' failed.
Aborted (core dumped)

A secondary issue with #4374 is that it penalizes the common case of passing in a buffer by always wrapping it in an array.

/cc @mcollina @jasnell

@bnoordhuis bnoordhuis added the dgram Issues and PRs related to the dgram subsystem / UDP. label May 6, 2016
@mcollina
Copy link
Member

mcollina commented May 6, 2016

I tried hard to benchmark the array allocation penalty, and I failed to produce a statistical difference, at least when I did the PR.

Regarding the array change you are right, we need to clone. I hope it will not cause a perfomance penalty.

BTW, did this come from a user issue? Is there some urgency in fixing it? I will not have bandwidth till mid-may to work on it.

@bnoordhuis
Copy link
Member Author

bnoordhuis commented May 6, 2016

BTW, did this come from a user issue? Is there some urgency in fixing it?

I don't think it's critical. I was checking something in lib/dgram.js and this stood out.

@Fishrock123 Fishrock123 added the confirmed-bug Issues with confirmed bugs. label May 6, 2016
@mcollina
Copy link
Member

mcollina commented May 6, 2016

@bnoordhuis let me know if you find any other area worth improving (there is actually http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_try_send to implement)

@ghost
Copy link

ghost commented May 13, 2016

This doesn't look like an array modification problem because the following works:

$ node -e '
  var a = ["boom!", "bang"], s = dgram.createSocket("udp4");
  s.send(a, 1234);
  a.splice(1);
'

It just looks like send doesn't accept an empty set of buffers:

$ node -e '
  var a = [], s = dgram.createSocket("udp4");
  s.send(a, 1234);
'
node: ../deps/uv/src/unix/udp.c:390: uv__udp_send: Assertion `nbufs > 0' failed.
Abort trap: 6

@ghost
Copy link

ghost commented May 15, 2016

I'm new to this codebase so let me know if I'm off base here but after looking at the uv code for unix and win, it looks like the unix version shouldn't have a problem because it copies the buffer pointers:

int uv__udp_send(uv_udp_send_t* req,
                 uv_udp_t* handle,
                 const uv_buf_t bufs[],
...
  memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
...

The windows version, however, passes them in directly to WSASendTo whose documentation says the buffers should not be modified for the duration of the call:

pBuffers [in]
A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer, in bytes. For a Winsock application, once the WSASendTo function is called, the system owns these buffers and the application may not access them. This array must remain valid for the duration of the send operation.

Is it an option to only wrap the win call (or to fix it so that it also copies the buffer pointers in the C code?)

@mcollina
Copy link
Member

@brown-dragon there is a slight chance for a GC run to deallocate those buffers in the meanwhile, as the buffers are not copied. A new array needs to be allocated and all values copied over.

mcollina added a commit to mcollina/node that referenced this issue May 25, 2016
This commit fix a possible crash situation in dgram send().
A crash is possible if an array is passed, and then altered after the
send call, as the call to libuv is wrapped in process.nextTick().

Fixes: nodejs#6616
Fishrock123 pushed a commit to Fishrock123/node that referenced this issue May 30, 2016
This commit fix a possible crash situation in dgram send().
A crash is possible if an array is passed, and then altered after the
send call, as the call to libuv is wrapped in process.nextTick().
It also avoid sending an empty array to libuv by allocating an empty
buffer. It also does some cleanup inside send() to increase readability.

It removes test flakyness by use common.mustCall and
common.platformTimeout. Fixes situations were some events were not
asserted to be emitted.

Fixes: nodejs#6616
PR-URL: nodejs#6804
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
rvagg pushed a commit that referenced this issue Jun 2, 2016
This commit fix a possible crash situation in dgram send().
A crash is possible if an array is passed, and then altered after the
send call, as the call to libuv is wrapped in process.nextTick().
It also avoid sending an empty array to libuv by allocating an empty
buffer. It also does some cleanup inside send() to increase readability.

It removes test flakyness by use common.mustCall and
common.platformTimeout. Fixes situations were some events were not
asserted to be emitted.

Fixes: #6616
PR-URL: #6804
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. dgram Issues and PRs related to the dgram subsystem / UDP.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants