Skip to content

Commit c982bf4

Browse files
committed
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 nodejs/node#50800 Fix By: Brad House (@bradh352)
1 parent 5ec2c68 commit c982bf4

1 file changed

Lines changed: 88 additions & 31 deletions

File tree

src/lib/ares_options.c

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -272,24 +272,46 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
272272
}
273273

274274
if (optmask & ARES_OPT_TIMEOUTMS) {
275-
channel->timeout = (unsigned int)options->timeout;
275+
/* Apparently some integrations were passing -1 to tell c-ares to use
276+
* the default instead of just omitting the optmask */
277+
if (options->timeout <= 0) {
278+
optmask &= ~(ARES_OPT_TIMEOUTMS);
279+
} else {
280+
channel->timeout = (unsigned int)options->timeout;
281+
}
276282
} else if (optmask & ARES_OPT_TIMEOUT) {
277-
/* Convert to milliseconds */
278-
optmask |= ARES_OPT_TIMEOUTMS;
279-
optmask &= ~(ARES_OPT_TIMEOUT);
280-
channel->timeout = (unsigned int)options->timeout * 1000;
283+
optmask &= ~(ARES_OPT_TIMEOUT);
284+
/* Apparently some integrations were passing -1 to tell c-ares to use
285+
* the default instead of just omitting the optmask */
286+
if (options->timeout > 0) {
287+
/* Convert to milliseconds */
288+
optmask |= ARES_OPT_TIMEOUTMS;
289+
channel->timeout = (unsigned int)options->timeout * 1000;
290+
}
281291
}
282292

283293
if (optmask & ARES_OPT_TRIES) {
284-
channel->tries = (size_t)options->tries;
294+
if (options->tries <= 0) {
295+
optmask &= ~(ARES_OPT_TRIES);
296+
} else {
297+
channel->tries = (size_t)options->tries;
298+
}
285299
}
286300

287301
if (optmask & ARES_OPT_NDOTS) {
288-
channel->ndots = (size_t)options->ndots;
302+
if (options->ndots <= 0) {
303+
optmask &= ~(ARES_OPT_NDOTS);
304+
} else {
305+
channel->ndots = (size_t)options->ndots;
306+
}
289307
}
290308

291309
if (optmask & ARES_OPT_MAXTIMEOUTMS) {
292-
channel->maxtimeout = (size_t)options->maxtimeout;
310+
if (options->maxtimeout <= 0) {
311+
optmask &= ~(ARES_OPT_MAXTIMEOUTMS);
312+
} else {
313+
channel->maxtimeout = (size_t)options->maxtimeout;
314+
}
293315
}
294316

295317
if (optmask & ARES_OPT_ROTATE) {
@@ -313,17 +335,28 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
313335
channel->sock_state_cb_data = options->sock_state_cb_data;
314336
}
315337

316-
if (optmask & ARES_OPT_SOCK_SNDBUF && options->socket_send_buffer_size > 0) {
317-
channel->socket_send_buffer_size = options->socket_send_buffer_size;
338+
if (optmask & ARES_OPT_SOCK_SNDBUF) {
339+
if (options->socket_send_buffer_size <= 0) {
340+
optmask &= ~(ARES_OPT_SOCK_SNDBUF);
341+
} else {
342+
channel->socket_send_buffer_size = options->socket_send_buffer_size;
343+
}
318344
}
319345

320-
if (optmask & ARES_OPT_SOCK_RCVBUF &&
321-
options->socket_receive_buffer_size > 0) {
322-
channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
346+
if (optmask & ARES_OPT_SOCK_RCVBUF) {
347+
if (options->socket_receive_buffer_size <= 0) {
348+
optmask &= ~(ARES_OPT_SOCK_RCVBUF);
349+
} else {
350+
channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
351+
}
323352
}
324353

325354
if (optmask & ARES_OPT_EDNSPSZ) {
326-
channel->ednspsz = (size_t)options->ednspsz;
355+
if (options->ednspsz <= 0) {
356+
optmask &= ~(ARES_OPT_EDNSPSZ);
357+
} else {
358+
channel->ednspsz = (size_t)options->ednspsz;
359+
}
327360
}
328361

329362
/* Copy the domains, if given. Keep channel->ndomains consistent so
@@ -346,9 +379,13 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
346379

347380
/* Set lookups, if given. */
348381
if (optmask & ARES_OPT_LOOKUPS) {
349-
channel->lookups = ares_strdup(options->lookups);
350-
if (!channel->lookups) {
351-
return ARES_ENOMEM;
382+
if (options->lookups == NULL) {
383+
optmask &= ~(ARES_OPT_LOOKUPS);
384+
} else {
385+
channel->lookups = ares_strdup(options->lookups);
386+
if (!channel->lookups) {
387+
return ARES_ENOMEM;
388+
}
352389
}
353390
}
354391

@@ -367,35 +404,55 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
367404

368405
/* Set path for resolv.conf file, if given. */
369406
if (optmask & ARES_OPT_RESOLVCONF) {
370-
channel->resolvconf_path = ares_strdup(options->resolvconf_path);
371-
if (!channel->resolvconf_path && options->resolvconf_path) {
372-
return ARES_ENOMEM;
407+
if (options->resolvconf_path == NULL) {
408+
optmask &= ~(ARES_OPT_RESOLVCONF);
409+
} else {
410+
channel->resolvconf_path = ares_strdup(options->resolvconf_path);
411+
if (channel->resolvconf_path == NULL) {
412+
return ARES_ENOMEM;
413+
}
373414
}
374415
}
375416

376417
/* Set path for hosts file, if given. */
377418
if (optmask & ARES_OPT_HOSTS_FILE) {
378-
channel->hosts_path = ares_strdup(options->hosts_path);
379-
if (!channel->hosts_path && options->hosts_path) {
380-
return ARES_ENOMEM;
419+
if (options->hosts_path == NULL) {
420+
optmask &= ~(ARES_OPT_HOSTS_FILE);
421+
} else {
422+
channel->hosts_path = ares_strdup(options->hosts_path);
423+
if (channel->hosts_path == NULL) {
424+
return ARES_ENOMEM;
425+
}
381426
}
382427
}
383428

384429
if (optmask & ARES_OPT_UDP_MAX_QUERIES) {
385-
channel->udp_max_queries = (size_t)options->udp_max_queries;
430+
if (options->udp_max_queries <= 0) {
431+
optmask &= ~(ARES_OPT_UDP_MAX_QUERIES);
432+
} else {
433+
channel->udp_max_queries = (size_t)options->udp_max_queries;
434+
}
386435
}
387436

388437
if (optmask & ARES_OPT_QUERY_CACHE) {
389-
channel->qcache_max_ttl = options->qcache_max_ttl;
438+
if (options->qcache_max_ttl <= 0) {
439+
optmask &= ~(ARES_OPT_QUERY_CACHE);
440+
} else {
441+
channel->qcache_max_ttl = options->qcache_max_ttl;
442+
}
390443
}
391444

392445
/* Initialize the ipv4 servers if provided */
393-
if (optmask & ARES_OPT_SERVERS && options->nservers > 0) {
394-
ares_status_t status;
395-
status = ares__init_options_servers(channel, options->servers,
396-
(size_t)options->nservers);
397-
if (status != ARES_SUCCESS) {
398-
return status;
446+
if (optmask & ARES_OPT_SERVERS) {
447+
if (options->nservers <= 0) {
448+
optmask &= ~(ARES_OPT_SERVERS);
449+
} else {
450+
ares_status_t status;
451+
status = ares__init_options_servers(channel, options->servers,
452+
(size_t)options->nservers);
453+
if (status != ARES_SUCCESS) {
454+
return status;
455+
}
399456
}
400457
}
401458

0 commit comments

Comments
 (0)