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

dns: fix crash while using dns.setServers after dns.resolve4 #13050

Closed
wants to merge 6 commits into
base: master
from

Conversation

Projects
None yet
10 participants
@XadillaX
Member

XadillaX commented May 16, 2017

The callback function in cares_query is synchronous and called before closed. So dns.setServers in the synchronous callback before closed will occur crashing.

This PR makes the real callback of dns.resolve4 or some other functions in dns asynchronous to resolve this problem.

Solution

I use uv_async_t to send the callback task to next loop. And the task data is created from CaresAsyncData.

Because Callback has two functions with parameters hostent* or unsigned char*, int, CaresAsyncData has a flag is_host to distinguish them.

In the Callback function, whether hostent* or unsigned char* will be destroyed after this function is done. So I make a copy for those buffers for asynchronous use. In the asynchronous function and asynchronous done callback, I delete some related pointers.

Related Issue: #894 #1071

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

dns

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 16, 2017

Member

The related cares code is under ares_process.c.

query->callback(query->arg, status, query->timeouts, abuf, alen);
ares__free_query(query);

If real callback is synchronous and we do dns.setServers in the callback, the program will crash because ares_set_servers will destroy current servers first.

Member

XadillaX commented May 16, 2017

The related cares code is under ares_process.c.

query->callback(query->arg, status, query->timeouts, abuf, alen);
ares__free_query(query);

If real callback is synchronous and we do dns.setServers in the callback, the program will crash because ares_set_servers will destroy current servers first.

@XadillaX XadillaX changed the title from dns: fix crash while using dns.setServers after dns.resolve4 to [WIP] dns: fix crash while using dns.setServers after dns.resolve4 May 16, 2017

@XadillaX XadillaX changed the title from [WIP] dns: fix crash while using dns.setServers after dns.resolve4 to dns: fix crash while using dns.setServers after dns.resolve4 May 16, 2017

@Trott

This comment has been minimized.

Show comment
Hide comment
@Trott

Trott May 16, 2017

Member

Awesome!

Someone else will have to comment on the C++ code. /cc @trevnorris @indutny @addaleax @danbev

But I can comment on the test. The test itself looks good. Some small comments:

  • I'm pretty sure the test file needs to go in test/internet because it attempts to do a DNS resolution.
  • In the comment, it's probably a good idea to use the full URL for the GitHub issues rather than the #1234 shortcut. We have a lot of old tests where it is ambiguous if #1234 means issue 1234 in this repo or if it is referring to github.com/nodejs/node-v0.x-archive/. Using the full URL will (hopefully) eliminate that ambiguity.

/cc @nodejs/testing

Member

Trott commented May 16, 2017

Awesome!

Someone else will have to comment on the C++ code. /cc @trevnorris @indutny @addaleax @danbev

But I can comment on the test. The test itself looks good. Some small comments:

  • I'm pretty sure the test file needs to go in test/internet because it attempts to do a DNS resolution.
  • In the comment, it's probably a good idea to use the full URL for the GitHub issues rather than the #1234 shortcut. We have a lot of old tests where it is ambiguous if #1234 means issue 1234 in this repo or if it is referring to github.com/nodejs/node-v0.x-archive/. Using the full URL will (hopefully) eliminate that ambiguity.

/cc @nodejs/testing

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

@Trott

  • I wrote test refer to test-dns-regress-6244, it resolve4 with 127.0.0.1 and actually has no internet request. And then I setServers with 127.0.0.1 too. And I think we can discuss more about it.
  • I've updated the comment.

Thanks for your suggestions.

Member

XadillaX commented May 17, 2017

@Trott

  • I wrote test refer to test-dns-regress-6244, it resolve4 with 127.0.0.1 and actually has no internet request. And then I setServers with 127.0.0.1 too. And I think we can discuss more about it.
  • I've updated the comment.

Thanks for your suggestions.

@Trott

This comment has been minimized.

Show comment
Hide comment
@Trott

Trott May 17, 2017

Member

I wrote test refer to test-dns-regress-6244, it resolve4 with 127.0.0.1 and actually has no internet request.

Are you sure about that? If I change your test code to this:

'use strict';

const common = require('../common');
const dns = require('dns');

dns.resolve4('nodejs.org', common.mustCall(function(err, nameServers) {
  if (err)
    throw err;
}));

...running it with a network connection results in no error. If I run it without a network connection enabled, I get ECONNREFUSED. I haven't fired up Wireshark or anything, but that sure seems to suggest it's sending a DNS request...

Member

Trott commented May 17, 2017

I wrote test refer to test-dns-regress-6244, it resolve4 with 127.0.0.1 and actually has no internet request.

Are you sure about that? If I change your test code to this:

'use strict';

const common = require('../common');
const dns = require('dns');

dns.resolve4('nodejs.org', common.mustCall(function(err, nameServers) {
  if (err)
    throw err;
}));

...running it with a network connection results in no error. If I run it without a network connection enabled, I get ECONNREFUSED. I haven't fired up Wireshark or anything, but that sure seems to suggest it's sending a DNS request...

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

I see. Actually I don't care about whether it will throw an error or not. My test destination is to test whether the case will crash or not.

Anyway, I moved the test case under internet now.

Before this fixture PR, that test case will fail because of crash.

Member

XadillaX commented May 17, 2017

I see. Actually I don't care about whether it will throw an error or not. My test destination is to test whether the case will crash or not.

Anyway, I moved the test case under internet now.

Before this fixture PR, that test case will fail because of crash.

@silverwind

This comment has been minimized.

Show comment
Hide comment
@silverwind

silverwind May 17, 2017

Contributor

Shouldn't this target master instead of v6.x? Because as far as I know, the bug is still present there.

Contributor

silverwind commented May 17, 2017

Shouldn't this target master instead of v6.x? Because as far as I know, the bug is still present there.

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

@silverwind hmmmm, I think if this PR is merged, we can port it to master.

But if reviewers consider that this PR must target to master, then I will change the target.

Member

XadillaX commented May 17, 2017

@silverwind hmmmm, I think if this PR is merged, we can port it to master.

But if reviewers consider that this PR must target to master, then I will change the target.

@silverwind

This comment has been minimized.

Show comment
Hide comment
@silverwind

silverwind May 17, 2017

Contributor

We generally land on master first and then backport it after a few weeks/months, so I'd appreciate if you target master now.

Contributor

silverwind commented May 17, 2017

We generally land on master first and then backport it after a few weeks/months, so I'd appreciate if you target master now.

@XadillaX XadillaX changed the base branch from v6.x to master May 17, 2017

@XadillaX XadillaX changed the base branch from master to v6.x May 17, 2017

dns: fix crash while using dns.setServers after dns.resolve4
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c

@XadillaX XadillaX changed the base branch from v6.x to master May 17, 2017

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

@silverwind I've updated the PR to make master as base. And who help to update the label 6.x?

Member

XadillaX commented May 17, 2017

@silverwind I've updated the PR to make master as base. And who help to update the label 6.x?

@silverwind

This comment has been minimized.

Show comment
Hide comment
@silverwind

silverwind May 17, 2017

Contributor

I can confirm it fixes the test case in #894.

Contributor

silverwind commented May 17, 2017

I can confirm it fixes the test case in #894.

@pmq20

This comment has been minimized.

Show comment
Hide comment
@pmq20

pmq20 May 17, 2017

Contributor

Excellent work! Thanks for the patch. To my understanding this PR simply postponed the execution of the callback of dns.resolve4 to the next tick, yet achieved this in a lot of code. I would prefer a simpler approach (or even only patch the JS level if possible), e.g. wrapping the callback function into a process.nextTick(). It would be easier to land if the diff was smaller. Do you think it's possible? @XadillaX

Contributor

pmq20 commented May 17, 2017

Excellent work! Thanks for the patch. To my understanding this PR simply postponed the execution of the callback of dns.resolve4 to the next tick, yet achieved this in a lot of code. I would prefer a simpler approach (or even only patch the JS level if possible), e.g. wrapping the callback function into a process.nextTick(). It would be easier to land if the diff was smaller. Do you think it's possible? @XadillaX

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

My consideration is that:

If we solve this bug in JavaScript level, the bug will still exist if developers use DNS binding directly. @pmq20

Or if someone add some new features for dns in dns.js, he / she may forget this bug and then uses sync code.

Member

XadillaX commented May 17, 2017

My consideration is that:

If we solve this bug in JavaScript level, the bug will still exist if developers use DNS binding directly. @pmq20

Or if someone add some new features for dns in dns.js, he / she may forget this bug and then uses sync code.

Show outdated Hide outdated src/cares_wrap.cc
@@ -296,6 +300,121 @@ Local<Array> HostentToNames(Environment* env, struct hostent* host) {
return scope.Escape(names);
}
/* copies a hostent structure*, returns 0 on success, -1 on error */
/* this function refers to OpenSIPS */

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

This is code that was licensed under the GPL, we can’t use it – sorry.

@addaleax

addaleax May 17, 2017

Member

This is code that was licensed under the GPL, we can’t use it – sorry.

This comment has been minimized.

@XadillaX

XadillaX May 17, 2017

Member

Okay, I'll rewrite this function then.

@XadillaX

XadillaX May 17, 2017

Member

Okay, I'll rewrite this function then.

This comment has been minimized.

@XadillaX

XadillaX May 17, 2017

Member

Thx. I've rewritten those two functions by myself now.

@XadillaX

XadillaX May 17, 2017

Member

Thx. I've rewritten those two functions by myself now.

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax

addaleax May 17, 2017

Member

If we solve this bug in JavaScript level, the bug will still exist if developers use DNS binding directly.

We generally consider the bindings layer private Node internals, so anybody who uses it directly is on shaky ground anyway.

Member

addaleax commented May 17, 2017

If we solve this bug in JavaScript level, the bug will still exist if developers use DNS binding directly.

We generally consider the bindings layer private Node internals, so anybody who uses it directly is on shaky ground anyway.

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

We generally consider the bindings layer private Node internals, so anybody who uses it directly is on shaky ground anyway.

But if someone add some new features for dns in dns.js, he / she may forget this bug and then uses sync code.

Member

XadillaX commented May 17, 2017

We generally consider the bindings layer private Node internals, so anybody who uses it directly is on shaky ground anyway.

But if someone add some new features for dns in dns.js, he / she may forget this bug and then uses sync code.

Show outdated Hide outdated src/cares_wrap.cc
dest->h_name = nullptr;
/* copy `h_name` */
unsigned int name_size = (strlen(src->h_name) + 1) * sizeof(char);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

sizeof(char) is guaranteed to be 1, you can drop it :)

@addaleax

addaleax May 17, 2017

Member

sizeof(char) is guaranteed to be 1, you can drop it :)

Show outdated Hide outdated src/cares_wrap.cc
/* copy `h_name` */
unsigned int name_size = (strlen(src->h_name) + 1) * sizeof(char);
dest->h_name = reinterpret_cast<char*>(node::Malloc(name_size));

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

There should be no need to cast here

@addaleax

addaleax May 17, 2017

Member

There should be no need to cast here

Show outdated Hide outdated src/cares_wrap.cc
}
alias_size = sizeof(char*) * (alias_count + 1);
dest->h_aliases = reinterpret_cast<char**>(node::Malloc(alias_size));

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

h_aliases = node::Malloc<char*>(alias_count+1) should work fine

@addaleax

addaleax May 17, 2017

Member

h_aliases = node::Malloc<char*>(alias_count+1) should work fine

Show outdated Hide outdated src/cares_wrap.cc
/* copy `h_aliases` */
unsigned int alias_count;
unsigned int alias_size;
unsigned int cur_alias_length;

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

I think size_t would be the right for all of these (and other vars probably, too?)

@addaleax

addaleax May 17, 2017

Member

I think size_t would be the right for all of these (and other vars probably, too?)

Show outdated Hide outdated src/cares_wrap.cc
memcpy(dest->h_aliases[i],
src->h_aliases[i],
sizeof(char) * (cur_alias_length + 1));

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

We do like to align our arguments vertically :) (i.e. make src-> come directly below dest->)

@addaleax

addaleax May 17, 2017

Member

We do like to align our arguments vertically :) (i.e. make src-> come directly below dest->)

Show outdated Hide outdated src/cares_wrap.cc
static void CaresAsyncClose(uv_handle_t* handle) {
uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
struct CaresAsyncData* data =
static_cast<struct CaresAsyncData*>(async->data);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

I think in this case it should be fine to just use auto data =, the type is obvious from the static_cast

@addaleax

addaleax May 17, 2017

Member

I think in this case it should be fine to just use auto data =, the type is obvious from the static_cast

Show outdated Hide outdated src/cares_wrap.cc
unsigned char* buf_copy = nullptr;
if (status == ARES_SUCCESS) {
buf_copy = (unsigned char*)node::Malloc(
sizeof(unsigned char) * answer_len);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

node::Malloc<unsigned char>(answer_len) should be fine – we generally avoid C-style casts

@addaleax

addaleax May 17, 2017

Member

node::Malloc<unsigned char>(answer_len) should be fine – we generally avoid C-style casts

Show outdated Hide outdated src/cares_wrap.cc
bool copy_ret = false;
if (status == ARES_SUCCESS) {
host_copy = (struct hostent*)node::Malloc(sizeof(hostent));

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

node::Malloc<hostent>() (okay, I’m going to stop commenting, you get the idea. :))

@addaleax

addaleax May 17, 2017

Member

node::Malloc<hostent>() (okay, I’m going to stop commenting, you get the idea. :))

Show outdated Hide outdated src/cares_wrap.cc
dest->h_aliases[i] = reinterpret_cast<char*>(
node::Malloc(sizeof(char) * (cur_alias_length + 1)));
if (dest->h_aliases[i] == nullptr) {

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

node::Malloc() aborts if it sees an OOM – I personally like code that does checking, but you’ll want node::UncheckedMalloc() for the variant that can return a nullptr.

@addaleax

addaleax May 17, 2017

Member

node::Malloc() aborts if it sees an OOM – I personally like code that does checking, but you’ll want node::UncheckedMalloc() for the variant that can return a nullptr.

This comment has been minimized.

@XadillaX

XadillaX May 17, 2017

Member

hmmmm, so what's your suggestion here?

Use node::UncheckedMalloc or use malloc directly? Or leave node::Malloc here and delete the nullptr checking?

@XadillaX

XadillaX May 17, 2017

Member

hmmmm, so what's your suggestion here?

Use node::UncheckedMalloc or use malloc directly? Or leave node::Malloc here and delete the nullptr checking?

Show outdated Hide outdated src/cares_wrap.cc
return false;
}
memset(reinterpret_cast<void*>(dest->h_aliases), 0, alias_size);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

reinterpret_cast → static_cast?

@addaleax

addaleax May 17, 2017

Member

reinterpret_cast → static_cast?

Show outdated Hide outdated test/internet/test-dns-setserver-in-callback-of-resolve4.js
dns.setServers([ '8.8.8.8' ]);
// the test case shouldn't crash here

This comment has been minimized.

@cjihrig

cjihrig May 17, 2017

Contributor

These comments can probably be dropped, but if you want to keep them, could you move them to the top like this. Note the Refs: notation.

@cjihrig

cjihrig May 17, 2017

Contributor

These comments can probably be dropped, but if you want to keep them, could you move them to the top like this. Note the Refs: notation.

This comment has been minimized.

@XadillaX

XadillaX May 17, 2017

Member

Got it. √

@XadillaX

XadillaX May 17, 2017

Member

Got it. √

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 17, 2017

Member

I've updated the code with your suggestions. @addaleax @cjihrig

Member

XadillaX commented May 17, 2017

I've updated the code with your suggestions. @addaleax @cjihrig

Show outdated Hide outdated test/internet/test-dns-setserver-in-callback-of-resolve4.js
'use strict';
// Refs: https://github.com/nodejs/node/pull/13050
// We don't care about `err` in the callback function of `dns.resolve4` here.

This comment has been minimized.

@refack

refack May 17, 2017

Member

Very good comment 🥇 I wish all tests had this...
Nit about the wording:

We don't care about `err` in the callback function of `dns.resolve4`. We just want to test whether `dns.setServers` that is run after `resolve4` will cause a crash or not. If it doesn't crash, the test succeeded.
@refack

refack May 17, 2017

Member

Very good comment 🥇 I wish all tests had this...
Nit about the wording:

We don't care about `err` in the callback function of `dns.resolve4`. We just want to test whether `dns.setServers` that is run after `resolve4` will cause a crash or not. If it doesn't crash, the test succeeded.

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

I don’t think it’s necessary to block this PR over this

@addaleax

addaleax May 17, 2017

Member

I don’t think it’s necessary to block this PR over this

This comment has been minimized.

@refack

refack May 17, 2017

Member

Agree.

@refack

refack May 17, 2017

Member

Agree.

@addaleax

I’d like to give this another look once the comments have been addressed, but basically this looks good to me 👍

Show outdated Hide outdated src/cares_wrap.cc
void safe_free_hostent(struct hostent* host) {
int idx;
if (host->h_addr_list) {

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

Just a style nit, but we do prefer explicit != nullptr or == nullptr for these checks

@addaleax

addaleax May 17, 2017

Member

Just a style nit, but we do prefer explicit != nullptr or == nullptr for these checks

Show outdated Hide outdated src/cares_wrap.cc
}
dest->h_aliases = node::Malloc<char*>(alias_count + 1);
memset(dest->h_aliases, 0, sizeof(char*) * (alias_count + 1));

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

You can drop this line, I think

@addaleax

addaleax May 17, 2017

Member

You can drop this line, I think

Show outdated Hide outdated src/cares_wrap.cc
}
/* copy `h_addr_list` */
unsigned int list_count;

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

size_t?

@addaleax

addaleax May 17, 2017

Member

size_t?

Show outdated Hide outdated src/cares_wrap.cc
}
dest->h_addr_list = node::Malloc<char*>(list_count + 1);
memset(dest->h_addr_list, 0, sizeof(char*) * (list_count + 1));

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

ditto, you can drop this

@addaleax

addaleax May 17, 2017

Member

ditto, you can drop this

Show outdated Hide outdated src/cares_wrap.cc
dest->h_addr_list = node::Malloc<char*>(list_count + 1);
memset(dest->h_addr_list, 0, sizeof(char*) * (list_count + 1));
for (unsigned int i = 0; i < list_count; i++) {
dest->h_addr_list[i] = node::Malloc<char>(src->h_length);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

If you prefer to be explicit about it, this works, but node::Malloc(src->h_length) should also work

@addaleax

addaleax May 17, 2017

Member

If you prefer to be explicit about it, this works, but node::Malloc(src->h_length) should also work

Show outdated Hide outdated src/cares_wrap.cc
if (status == ARES_SUCCESS) {
host_copy = node::Malloc<hostent>(1);
copy_ret = cares_wrap_hostent_cpy(host_copy, host);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

copy_ret can’t be false anymore, right? That should make everything a bit simpler.

@addaleax

addaleax May 17, 2017

Member

copy_ret can’t be false anymore, right? That should make everything a bit simpler.

Show outdated Hide outdated src/cares_wrap.cc
copy_ret = cares_wrap_hostent_cpy(host_copy, host);
}
struct CaresAsyncData* data = new struct CaresAsyncData();

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

style nit: drop the struct (either just the one after new or both), it’s not necessary in C++ and we don’t do that elsewhere

@addaleax

addaleax May 17, 2017

Member

style nit: drop the struct (either just the one after new or both), it’s not necessary in C++ and we don’t do that elsewhere

Show outdated Hide outdated test/internet/test-dns-setserver-in-callback-of-resolve4.js
'use strict';
// Refs: https://github.com/nodejs/node/pull/13050
// We don't care about `err` in the callback function of `dns.resolve4` here.

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

I don’t think it’s necessary to block this PR over this

@addaleax

addaleax May 17, 2017

Member

I don’t think it’s necessary to block this PR over this

Show outdated Hide outdated src/cares_wrap.cc
QueryWrap* wrap;
int status;
bool is_host;
void* buf;

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

It might be worth turning this into a union { hostent* h; unsigned char* buf }, what do you think?

@addaleax

addaleax May 17, 2017

Member

It might be worth turning this into a union { hostent* h; unsigned char* buf }, what do you think?

Show outdated Hide outdated src/cares_wrap.cc
if (status != ARES_SUCCESS) {
wrap->ParseError(status);
} else if (!data->is_host) {
unsigned char* buf = reinterpret_cast<unsigned char*>(data->buf);

This comment has been minimized.

@addaleax

addaleax May 17, 2017

Member

static_cast should do fine here

@addaleax

addaleax May 17, 2017

Member

static_cast should do fine here

this particular point has been addressed

@refack refack dismissed their stale review May 17, 2017

Just a nit

@pmq20 pmq20 self-requested a review May 18, 2017

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 18, 2017

Member

I think I finished your suggestions that mentioned in your review. @addaleax

Member

XadillaX commented May 18, 2017

I think I finished your suggestions that mentioned in your review. @addaleax

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 18, 2017

Member

@addaleax What shall I do now? Check the CI and modify my code or just wait for another reviewer to review my code?

Member

XadillaX commented May 18, 2017

@addaleax What shall I do now? Check the CI and modify my code or just wait for another reviewer to review my code?

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax

addaleax May 18, 2017

Member

@XadillaX The CI says the program segfaults – I think the problem is just that h_aliases and h_addr_list need their null terminators, which currently aren’t being copied/added

edit: i.e. this patch:

diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc
index c561dd8d1108..f0b81c8c97e4 100644
--- a/src/cares_wrap.cc
+++ b/src/cares_wrap.cc
@@ -351,6 +351,7 @@ void cares_wrap_hostent_cpy(struct hostent* dest, struct hostent* src) {
     dest->h_aliases[i] = node::Malloc(cur_alias_length + 1);
     memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_length + 1);
   }
+  dest->h_aliases[alias_count] = nullptr;
 
   /* copy `h_addr_list` */
   size_t list_count;
@@ -364,6 +365,7 @@ void cares_wrap_hostent_cpy(struct hostent* dest, struct hostent* src) {
     dest->h_addr_list[i] = node::Malloc(src->h_length);
     memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
   }
+  dest->h_addr_list[list_count] = nullptr;
 
   /* work after work */
   dest->h_length = src->h_length;
Member

addaleax commented May 18, 2017

@XadillaX The CI says the program segfaults – I think the problem is just that h_aliases and h_addr_list need their null terminators, which currently aren’t being copied/added

edit: i.e. this patch:

diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc
index c561dd8d1108..f0b81c8c97e4 100644
--- a/src/cares_wrap.cc
+++ b/src/cares_wrap.cc
@@ -351,6 +351,7 @@ void cares_wrap_hostent_cpy(struct hostent* dest, struct hostent* src) {
     dest->h_aliases[i] = node::Malloc(cur_alias_length + 1);
     memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_length + 1);
   }
+  dest->h_aliases[alias_count] = nullptr;
 
   /* copy `h_addr_list` */
   size_t list_count;
@@ -364,6 +365,7 @@ void cares_wrap_hostent_cpy(struct hostent* dest, struct hostent* src) {
     dest->h_addr_list[i] = node::Malloc(src->h_length);
     memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
   }
+  dest->h_addr_list[list_count] = nullptr;
 
   /* work after work */
   dest->h_length = src->h_length;
@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 18, 2017

Member

@addaleax ah, i forgot to add nullptr after deleting memset. sorry

Member

XadillaX commented May 18, 2017

@addaleax ah, i forgot to add nullptr after deleting memset. sorry

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax

addaleax May 18, 2017

Member

@XadillaX No problem, I didn’t notice that either. :) I’ll kick off a new CI run once this PR is updated (unless you want me to update the PR for you, in which case I can just do that as well)

Member

addaleax commented May 18, 2017

@XadillaX No problem, I didn’t notice that either. :) I’ll kick off a new CI run once this PR is updated (unless you want me to update the PR for you, in which case I can just do that as well)

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 18, 2017

Member

@addaleax thx, i've updated.

Member

XadillaX commented May 18, 2017

@addaleax thx, i've updated.

@addaleax

This comment has been minimized.

Show comment
Hide comment
Member

addaleax commented May 18, 2017

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 18, 2017

Member

@addaleax Finally the CI passed. 🎉ヘ|・∀・|ノ*~●

image

Member

XadillaX commented May 18, 2017

@addaleax Finally the CI passed. 🎉ヘ|・∀・|ノ*~●

image

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax

addaleax May 18, 2017

Member

Landed in 5a948f6, thanks for the PR!

Member

addaleax commented May 18, 2017

Landed in 5a948f6, thanks for the PR!

@addaleax addaleax closed this May 18, 2017

addaleax added a commit that referenced this pull request May 18, 2017

dns: fix crash using dns.setServers after resolve4
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
PR-URL: #13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@refack

This comment has been minimized.

Show comment
Hide comment
@refack

refack May 18, 2017

Member

@XadillaX congrats 🎉 is this your first code contribution?

Member

refack commented May 18, 2017

@XadillaX congrats 🎉 is this your first code contribution?

@silverwind

This comment has been minimized.

Show comment
Hide comment
@silverwind

silverwind May 18, 2017

Contributor

It is. Pretty awesome first contribution!

Contributor

silverwind commented May 18, 2017

It is. Pretty awesome first contribution!

@XadillaX

This comment has been minimized.

Show comment
Hide comment
@XadillaX

XadillaX May 19, 2017

Member

Yes, it is my first contribution. Thank you all for helping with my first contribution!

Member

XadillaX commented May 19, 2017

Yes, it is my first contribution. Thank you all for helping with my first contribution!

anchnk added a commit to anchnk/node that referenced this pull request May 19, 2017

dns: fix crash using dns.setServers after resolve4
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: nodejs#894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
PR-URL: nodejs#13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@sam-github

This comment has been minimized.

Show comment
Hide comment
@sam-github

sam-github May 19, 2017

Member
2 new defect(s) introduced to Node.js found with Coverity Scan.


New defect(s) Reported-by: Coverity Scan
Showing 2 of 2 defect(s)


** CID 169571:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 467 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, unsigned char *, int)()


________________________________________________________________________________________________________
*** CID 169571:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 467 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, unsigned char *, int)()
461         data->wrap = wrap;
462         data->is_host = false;
463         data->data.buf = buf_copy;
464         data->len = answer_len;
465
466         uv_async_t* async_handle = &data->async_handle;
>>>     CID 169571:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "uv_async_init" without checking return value (as is done elsewhere 9 out of 11 times).
467         uv_async_init(wrap->env()->event_loop(), async_handle, CaresAsyncCb);
468
469         async_handle->data = data;
470         uv_async_send(async_handle);
471       }
472

** CID 169570:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 490 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, hostent *)()


________________________________________________________________________________________________________
*** CID 169570:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 490 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, hostent *)()
484         data->status = status;
485         data->data.host = host_copy;
486         data->wrap = wrap;
487         data->is_host = true;
488
489         uv_async_t* async_handle = &data->async_handle;
>>>     CID 169570:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "uv_async_init" without checking return value (as is done elsewhere 9 out of 11 times).
490         uv_async_init(wrap->env()->event_loop(), async_handle, CaresAsyncCb);
491
492         async_handle->data = data;
493         uv_async_send(async_handle);
494       }
495
Member

sam-github commented May 19, 2017

2 new defect(s) introduced to Node.js found with Coverity Scan.


New defect(s) Reported-by: Coverity Scan
Showing 2 of 2 defect(s)


** CID 169571:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 467 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, unsigned char *, int)()


________________________________________________________________________________________________________
*** CID 169571:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 467 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, unsigned char *, int)()
461         data->wrap = wrap;
462         data->is_host = false;
463         data->data.buf = buf_copy;
464         data->len = answer_len;
465
466         uv_async_t* async_handle = &data->async_handle;
>>>     CID 169571:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "uv_async_init" without checking return value (as is done elsewhere 9 out of 11 times).
467         uv_async_init(wrap->env()->event_loop(), async_handle, CaresAsyncCb);
468
469         async_handle->data = data;
470         uv_async_send(async_handle);
471       }
472

** CID 169570:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 490 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, hostent *)()


________________________________________________________________________________________________________
*** CID 169570:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 490 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, hostent *)()
484         data->status = status;
485         data->data.host = host_copy;
486         data->wrap = wrap;
487         data->is_host = true;
488
489         uv_async_t* async_handle = &data->async_handle;
>>>     CID 169570:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "uv_async_init" without checking return value (as is done elsewhere 9 out of 11 times).
490         uv_async_init(wrap->env()->event_loop(), async_handle, CaresAsyncCb);
491
492         async_handle->data = data;
493         uv_async_send(async_handle);
494       }
495
@cjihrig

This comment has been minimized.

Show comment
Hide comment
@cjihrig
Contributor

cjihrig commented May 19, 2017

@gibfahn gibfahn referenced this pull request May 19, 2017

Closed

Run coverity on PRs #13117

cjihrig added a commit to cjihrig/node-1 that referenced this pull request May 22, 2017

src: assert that uv_async_init() succeeds
This commit fixes two coverity warnings for unchecked
return values.

Refs: nodejs#13050
PR-URL: nodejs#13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

jasnell added a commit that referenced this pull request May 23, 2017

src: assert that uv_async_init() succeeds
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

jasnell added a commit that referenced this pull request May 23, 2017

src: assert that uv_async_init() succeeds
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

@jasnell jasnell referenced this pull request May 28, 2017

Closed

8.0.0 Release Proposal #12220

@gibfahn gibfahn referenced this pull request Jun 15, 2017

Closed

Auditing for 6.11.1 #230

2 of 3 tasks complete

XadillaX added a commit to XadillaX/node that referenced this pull request Jun 16, 2017

dns: fix crash using dns.setServers after resolve4
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: nodejs#894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
PR-URL: nodejs#13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@MylesBorins

This comment has been minimized.

Show comment
Hide comment
@MylesBorins

MylesBorins Jun 23, 2017

Member

It would appear that this is causing build errors on v6.x. I have labelled it as dont-land

If it does land it needs to come with 06f62eb

edit: I left dont land off for now until we hear that someone can say if this needs to land

Member

MylesBorins commented Jun 23, 2017

It would appear that this is causing build errors on v6.x. I have labelled it as dont-land

If it does land it needs to come with 06f62eb

edit: I left dont land off for now until we hear that someone can say if this needs to land

MylesBorins added a commit that referenced this pull request Jul 10, 2017

dns: fix crash using dns.setServers after resolve4
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
Backport-PR-URL: #13724
PR-URL: #13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>

MylesBorins added a commit that referenced this pull request Jul 10, 2017

src: assert that uv_async_init() succeeds
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

MylesBorins added a commit that referenced this pull request Jul 11, 2017

dns: fix crash using dns.setServers after resolve4
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
Backport-PR-URL: #13724
PR-URL: #13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>

MylesBorins added a commit that referenced this pull request Jul 11, 2017

src: assert that uv_async_init() succeeds
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

@MylesBorins MylesBorins referenced this pull request Jul 18, 2017

Merged

v6.11.2 proposal #14356

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment