ares_init_options() with invalid options values should unset the option

Apparently nodejs is relying on the above behavior for legacy reasons.  Add
sanity checks to the various optmask parameters where it makes sense.

See https://github.com/nodejs/node/pull/50800

Fix By: Brad House (@bradh352)
v1.23
Brad House 1 year ago
parent f83830f95b
commit 2656c38259
  1. 71
      src/lib/ares_options.c

@ -272,25 +272,47 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
} }
if (optmask & ARES_OPT_TIMEOUTMS) { if (optmask & ARES_OPT_TIMEOUTMS) {
/* Apparently some integrations were passing -1 to tell c-ares to use
* the default instead of just omitting the optmask */
if (options->timeout <= 0) {
optmask &= ~(ARES_OPT_TIMEOUTMS);
} else {
channel->timeout = (unsigned int)options->timeout; channel->timeout = (unsigned int)options->timeout;
}
} else if (optmask & ARES_OPT_TIMEOUT) { } else if (optmask & ARES_OPT_TIMEOUT) {
optmask &= ~(ARES_OPT_TIMEOUT);
/* Apparently some integrations were passing -1 to tell c-ares to use
* the default instead of just omitting the optmask */
if (options->timeout > 0) {
/* Convert to milliseconds */ /* Convert to milliseconds */
optmask |= ARES_OPT_TIMEOUTMS; optmask |= ARES_OPT_TIMEOUTMS;
optmask &= ~(ARES_OPT_TIMEOUT);
channel->timeout = (unsigned int)options->timeout * 1000; channel->timeout = (unsigned int)options->timeout * 1000;
} }
}
if (optmask & ARES_OPT_TRIES) { if (optmask & ARES_OPT_TRIES) {
if (options->tries <= 0) {
optmask &= ~(ARES_OPT_TRIES);
} else {
channel->tries = (size_t)options->tries; channel->tries = (size_t)options->tries;
} }
}
if (optmask & ARES_OPT_NDOTS) { if (optmask & ARES_OPT_NDOTS) {
if (options->ndots <= 0) {
optmask &= ~(ARES_OPT_NDOTS);
} else {
channel->ndots = (size_t)options->ndots; channel->ndots = (size_t)options->ndots;
} }
}
if (optmask & ARES_OPT_MAXTIMEOUTMS) { if (optmask & ARES_OPT_MAXTIMEOUTMS) {
if (options->maxtimeout <= 0) {
optmask &= ~(ARES_OPT_MAXTIMEOUTMS);
} else {
channel->maxtimeout = (size_t)options->maxtimeout; channel->maxtimeout = (size_t)options->maxtimeout;
} }
}
if (optmask & ARES_OPT_ROTATE) { if (optmask & ARES_OPT_ROTATE) {
channel->rotate = ARES_TRUE; channel->rotate = ARES_TRUE;
@ -313,18 +335,29 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
channel->sock_state_cb_data = options->sock_state_cb_data; channel->sock_state_cb_data = options->sock_state_cb_data;
} }
if (optmask & ARES_OPT_SOCK_SNDBUF && options->socket_send_buffer_size > 0) { if (optmask & ARES_OPT_SOCK_SNDBUF) {
if (options->socket_send_buffer_size <= 0) {
optmask &= ~(ARES_OPT_SOCK_SNDBUF);
} else {
channel->socket_send_buffer_size = options->socket_send_buffer_size; channel->socket_send_buffer_size = options->socket_send_buffer_size;
} }
}
if (optmask & ARES_OPT_SOCK_RCVBUF && if (optmask & ARES_OPT_SOCK_RCVBUF) {
options->socket_receive_buffer_size > 0) { if (options->socket_receive_buffer_size <= 0) {
optmask &= ~(ARES_OPT_SOCK_RCVBUF);
} else {
channel->socket_receive_buffer_size = options->socket_receive_buffer_size; channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
} }
}
if (optmask & ARES_OPT_EDNSPSZ) { if (optmask & ARES_OPT_EDNSPSZ) {
if (options->ednspsz <= 0) {
optmask &= ~(ARES_OPT_EDNSPSZ);
} else {
channel->ednspsz = (size_t)options->ednspsz; channel->ednspsz = (size_t)options->ednspsz;
} }
}
/* Copy the domains, if given. Keep channel->ndomains consistent so /* Copy the domains, if given. Keep channel->ndomains consistent so
* we can clean up in case of error. * we can clean up in case of error.
@ -346,11 +379,15 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
/* Set lookups, if given. */ /* Set lookups, if given. */
if (optmask & ARES_OPT_LOOKUPS) { if (optmask & ARES_OPT_LOOKUPS) {
if (options->lookups == NULL) {
optmask &= ~(ARES_OPT_LOOKUPS);
} else {
channel->lookups = ares_strdup(options->lookups); channel->lookups = ares_strdup(options->lookups);
if (!channel->lookups) { if (!channel->lookups) {
return ARES_ENOMEM; return ARES_ENOMEM;
} }
} }
}
/* copy sortlist */ /* copy sortlist */
if (optmask & ARES_OPT_SORTLIST && options->nsort > 0) { if (optmask & ARES_OPT_SORTLIST && options->nsort > 0) {
@ -367,30 +404,49 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
/* Set path for resolv.conf file, if given. */ /* Set path for resolv.conf file, if given. */
if (optmask & ARES_OPT_RESOLVCONF) { if (optmask & ARES_OPT_RESOLVCONF) {
if (options->resolvconf_path == NULL) {
optmask &= ~(ARES_OPT_RESOLVCONF);
} else {
channel->resolvconf_path = ares_strdup(options->resolvconf_path); channel->resolvconf_path = ares_strdup(options->resolvconf_path);
if (!channel->resolvconf_path && options->resolvconf_path) { if (channel->resolvconf_path == NULL) {
return ARES_ENOMEM; return ARES_ENOMEM;
} }
} }
}
/* Set path for hosts file, if given. */ /* Set path for hosts file, if given. */
if (optmask & ARES_OPT_HOSTS_FILE) { if (optmask & ARES_OPT_HOSTS_FILE) {
if (options->hosts_path == NULL) {
optmask &= ~(ARES_OPT_HOSTS_FILE);
} else {
channel->hosts_path = ares_strdup(options->hosts_path); channel->hosts_path = ares_strdup(options->hosts_path);
if (!channel->hosts_path && options->hosts_path) { if (channel->hosts_path == NULL) {
return ARES_ENOMEM; return ARES_ENOMEM;
} }
} }
}
if (optmask & ARES_OPT_UDP_MAX_QUERIES) { if (optmask & ARES_OPT_UDP_MAX_QUERIES) {
if (options->udp_max_queries <= 0) {
optmask &= ~(ARES_OPT_UDP_MAX_QUERIES);
} else {
channel->udp_max_queries = (size_t)options->udp_max_queries; channel->udp_max_queries = (size_t)options->udp_max_queries;
} }
}
if (optmask & ARES_OPT_QUERY_CACHE) { if (optmask & ARES_OPT_QUERY_CACHE) {
if (options->qcache_max_ttl <= 0) {
optmask &= ~(ARES_OPT_QUERY_CACHE);
} else {
channel->qcache_max_ttl = options->qcache_max_ttl; channel->qcache_max_ttl = options->qcache_max_ttl;
} }
}
/* Initialize the ipv4 servers if provided */ /* Initialize the ipv4 servers if provided */
if (optmask & ARES_OPT_SERVERS && options->nservers > 0) { if (optmask & ARES_OPT_SERVERS) {
if (options->nservers <= 0) {
optmask &= ~(ARES_OPT_SERVERS);
} else {
ares_status_t status; ares_status_t status;
status = ares__init_options_servers(channel, options->servers, status = ares__init_options_servers(channel, options->servers,
(size_t)options->nservers); (size_t)options->nservers);
@ -398,6 +454,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
return status; return status;
} }
} }
}
channel->optmask = (unsigned int)optmask; channel->optmask = (unsigned int)optmask;

Loading…
Cancel
Save