Nameserver parsing: replace another hand-written parser (#643)

This replaces the nameserver parsing code with code that use ares__buf_*() in the name of memory safety.

Fix By: Brad House (@bradh352)
pull/651/head
Brad House 12 months ago committed by GitHub
parent f83830f95b
commit 86ac418970
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 157
      src/lib/ares__buf.c
  2. 69
      src/lib/ares__buf.h
  3. 3
      src/lib/ares_private.h
  4. 10
      src/lib/ares_sysconfig.c
  5. 2
      src/lib/ares_sysconfig_files.c
  6. 342
      src/lib/ares_update_servers.c
  7. 2
      test/ares-test-internal.cc
  8. 6
      test/ares-test-misc.cc

@ -722,25 +722,168 @@ done:
return i;
}
ares_status_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data, size_t data_len)
size_t ares__buf_consume_until_charset(ares__buf_t *buf,
const unsigned char *charset,
size_t len,
ares_bool_t require_charset)
{
size_t remaining_len = 0;
const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len);
size_t i;
ares_bool_t found = ARES_FALSE;
if (ptr == NULL || data == NULL || data_len == 0) {
if (ptr == NULL || charset == NULL || len == 0) {
return 0;
}
for (i = 0; i < remaining_len; i++) {
size_t j;
for (j = 0; j < len; j++) {
if (ptr[i] == charset[j]) {
found = ARES_TRUE;
goto done;
}
}
}
done:
if (require_charset && !found)
return 0;
if (i > 0) {
ares__buf_consume(buf, i);
}
return i;
}
size_t ares__buf_consume_charset(ares__buf_t *buf,
const unsigned char *charset,
size_t len)
{
size_t remaining_len = 0;
const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len);
size_t i;
if (ptr == NULL || charset == NULL || len == 0) {
return 0;
}
for (i = 0; i < remaining_len; i++) {
size_t j;
for (j = 0; j < len; j++) {
if (ptr[i] == charset[j]) {
break;
}
}
/* Not found */
if (j == len)
break;
}
if (i > 0) {
ares__buf_consume(buf, i);
}
return i;
}
static void ares__buf_destroy_cb(void *arg)
{
ares__buf_destroy(arg);
}
ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
size_t delims_len, ares__buf_split_t flags,
ares__llist_t **list)
{
ares_status_t status = ARES_SUCCESS;
ares_bool_t first = ARES_TRUE;
if (buf == NULL || delims == NULL || delims_len == 0 || list == NULL) {
return ARES_EFORMERR;
}
*list = ares__llist_create(ares__buf_destroy_cb);
if (*list == NULL) {
status = ARES_ENOMEM;
goto done;
}
while (ares__buf_len(buf)) {
size_t len;
ares__buf_tag(buf);
len = ares__buf_consume_until_charset(buf, delims, delims_len, ARES_FALSE);
/* Don't treat a delimiter as part of the length */
if (!first && len && flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) {
len--;
}
if (len != 0 || flags & ARES_BUF_SPLIT_ALLOW_BLANK) {
const unsigned char *ptr = ares__buf_tag_fetch(buf, &len);
ares__buf_t *data;
/* Since we don't allow const buffers of 0 length, and user wants 0-length
* buffers, swap what we do here */
if (len) {
data = ares__buf_create_const(ptr, len);
} else {
data = ares__buf_create();
}
if (data == NULL) {
status = ARES_ENOMEM;
goto done;
}
if (ares__llist_insert_last(*list, data) == NULL) {
ares__buf_destroy(data);
status = ARES_ENOMEM;
goto done;
}
}
if (!(flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) &&
ares__buf_len(buf) != 0) {
/* Consume delimiter */
ares__buf_consume(buf, 1);
}
first = ARES_FALSE;
}
done:
if (status != ARES_SUCCESS) {
ares__llist_destroy(*list);
*list = NULL;
}
return status;
}
ares_bool_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data, size_t data_len)
{
size_t remaining_len = 0;
const unsigned char *ptr = ares__buf_fetch(buf, &remaining_len);
if (ptr == NULL || data == NULL || data_len == 0) {
return ARES_FALSE;
}
if (data_len > remaining_len) {
return ARES_EBADRESP;
return ARES_FALSE;
}
if (memcmp(ptr, data, data_len) == 0) {
return ARES_EBADRESP;
if (memcmp(ptr, data, data_len) != 0) {
return ARES_FALSE;
}
return ARES_SUCCESS;
return ARES_TRUE;
}
size_t ares__buf_len(const ares__buf_t *buf)

@ -372,6 +372,36 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf,
*/
size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf);
/*! Consume until a character in the character set provided is reached
*
* \param[in] buf Initialized buffer object
* \param[in] charset character set
* \param[in] len length of character set
* \param[in] require_charset require we find a character from the charset.
* if ARES_FALSE it will simply consume the
* rest of the buffer. If ARES_TRUE will return
* 0 if not found.
* \return number of characters consumed
*/
size_t ares__buf_consume_until_charset(ares__buf_t *buf,
const unsigned char *charset,
size_t len,
ares_bool_t require_charset);
/*! Consume while the characters match the characters in the provided set.
*
* \param[in] buf Initialized buffer object
* \param[in] charset character set
* \param[in] len length of character set
* \return number of characters consumed
*/
size_t ares__buf_consume_charset(ares__buf_t *buf,
const unsigned char *charset,
size_t len);
/*! Consume from the current position until the end of the line, and optionally
* the end of line character (0x0A) itself.
*
@ -383,16 +413,49 @@ size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf);
size_t ares__buf_consume_line(ares__buf_t *buf, ares_bool_t include_linefeed);
typedef enum {
/*! No flags */
ARES_BUF_SPLIT_NONE = 0,
/*! The delimiter will be the first character in the buffer, except the
* first buffer since the start doesn't have a delimiter
*/
ARES_BUF_SPLIT_DONT_CONSUME_DELIMS = 1 << 0,
/*! Allow blank sections, by default blank sections are not emitted. If using
* ARES_BUF_SPLIT_DONT_CONSUME_DELIMS, the delimiter is not counted as part
* of the section */
ARES_BUF_SPLIT_ALLOW_BLANK = 1 << 1
} ares__buf_split_t;
/*! Split the provided buffer into multiple sub-buffers stored in the variable
* pointed to by the linked list. The sub buffers are const buffers pointing
* into the buf provided.
*
* \param[in] buf Initialized buffer object
* \param[in] delims Possible delimiters
* \param[in] delims_len Length of possible delimiters
* \param[in] flags One more more flags
* \param[out] list Result. Depending on flags, this may be a
* valid list with no elements. Use
* ares__llist_destroy() to free the memory which
* will also free the contained ares__buf_t
* objects.
* \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
*/
ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
size_t delims_len, ares__buf_split_t flags,
ares__llist_t **list);
/*! Check the unprocessed buffer to see if it begins with the sequence of
* characters provided.
*
* \param[in] buf Initialized buffer object
* \param[in] data Bytes of data to compare.
* \param[in] data_len Length of data to compare.
* \return ARES_SUCCESS or one of the c-ares error codes
* \return ARES_TRUE on match, ARES_FALSE otherwise.
*/
ares_status_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data, size_t data_len);
ares_bool_t ares__buf_begins_with(const ares__buf_t *buf,
const unsigned char *data, size_t data_len);
/*! Size of unprocessed remaining data length

@ -482,7 +482,8 @@ ares_status_t ares__sconfig_append(ares__llist_t **sconfig,
unsigned short udp_port,
unsigned short tcp_port);
ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig,
const char *str);
const char *str,
ares_bool_t ignore_invalid);
ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
size_t nservers,
ares__llist_t **llist);

@ -597,7 +597,7 @@ static ares_status_t ares__init_sysconfig_windows(ares_sysconfig_t *sysconfig)
ares_status_t status = ARES_SUCCESS;
if (get_DNS_Windows(&line)) {
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, line);
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, line, ARES_TRUE);
ares_free(line);
if (status != ARES_SUCCESS) {
goto done;
@ -713,7 +713,7 @@ static ares_status_t ares__init_sysconfig_riscos(ares_sysconfig_t *sysconfig)
if (space) {
*space = '\0';
}
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, pos);
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, pos, ARES_TRUE);
if (status != ARES_SUCCESS) {
break;
}
@ -771,7 +771,7 @@ static ares_status_t ares__init_sysconfig_android(ares_sysconfig_t *sysconfig)
if (dns_servers != NULL) {
for (i = 0; i < num_servers; i++) {
status =
ares__sconfig_append_fromstr(&sysconfig->sconfig, dns_servers[i]);
ares__sconfig_append_fromstr(&sysconfig->sconfig, dns_servers[i], ARES_TRUE);
if (status != ARES_SUCCESS) {
return status;
}
@ -802,7 +802,7 @@ static ares_status_t ares__init_sysconfig_android(ares_sysconfig_t *sysconfig)
if (__system_property_get(propname, propvalue) < 1) {
break;
}
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, propvalue);
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, propvalue, ARES_TRUE);
if (status != ARES_SUCCESS) {
return status;
}
@ -854,7 +854,7 @@ static ares_status_t ares__init_sysconfig_libresolv(ares_sysconfig_t *sysconfig)
snprintf(ipaddr_port, sizeof(ipaddr_port), "%s", ipaddr);
}
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, ipaddr_port);
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, ipaddr_port, ARES_TRUE);
if (status != ARES_SUCCESS) {
goto done;
}

@ -516,7 +516,7 @@ ares_status_t ares__init_sysconfig_files(const ares_channel_t *channel,
} else if ((p = try_config(line, "search", ';'))) {
status = config_search(sysconfig, p);
} else if ((p = try_config(line, "nameserver", ';'))) {
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, p);
status = ares__sconfig_append_fromstr(&sysconfig->sconfig, p, ARES_TRUE);
} else if ((p = try_config(line, "sortlist", ';'))) {
status =
ares__parse_sortlist(&sysconfig->sortlist, &sysconfig->nsortlist, p);

@ -140,9 +140,13 @@ static ares_bool_t ares_server_blacklisted(const struct ares_addr *addr)
/* Parse address and port in these formats, either ipv4 or ipv6 addresses
* are allowed:
* ipaddr
* ipv4addr:port
* [ipaddr]
* [ipaddr]:port
*
* TODO: in the future we need to add % and # syntax modifications to support
* the link-local interface name and domain, respectively.
*
* If a port is not specified, will set port to 0.
*
* Will fail if an IPv6 nameserver as detected by
@ -150,84 +154,106 @@ static ares_bool_t ares_server_blacklisted(const struct ares_addr *addr)
*
* Returns an error code on failure, else ARES_SUCCESS
*/
static ares_status_t parse_dnsaddrport(const char *str, size_t len,
static ares_status_t parse_dnsaddrport(ares__buf_t *buf,
struct ares_addr *host,
unsigned short *port)
{
char ipaddr[INET6_ADDRSTRLEN] = "";
char ipport[6] = "";
size_t mylen;
const char *addr_start = NULL;
const char *addr_end = NULL;
const char *port_start = NULL;
const char *port_end = NULL;
/* Must start with [, hex digit or : */
if (len == 0 || (*str != '[' && !isxdigit(*str) && *str != ':')) {
return ARES_EBADSTR;
}
ares_status_t status;
char ipaddr[INET6_ADDRSTRLEN] = "";
size_t addrlen;
*port = 0;
/* If it starts with a bracket, must end with a bracket */
if (*str == '[') {
const char *ptr;
addr_start = str + 1;
ptr = memchr(addr_start, ']', len - 1);
if (ptr == NULL) {
/* Consume any leading whitespace */
ares__buf_consume_whitespace(buf, ARES_TRUE);
/* pop off IP address. If it is in [ ] then it can be ipv4 or ipv6. If
* not, ipv4 only */
if (ares__buf_begins_with(buf, (const unsigned char *)"[", 1)) {
/* Consume [ */
ares__buf_consume(buf, 1);
ares__buf_tag(buf);
/* Consume until ] */
if (ares__buf_consume_until_charset(buf, (const unsigned char *)"]", 1, ARES_TRUE) == 0) {
return ARES_EBADSTR;
}
addr_end = ptr - 1;
/* Try to pull off port */
if ((size_t)(ptr - str) < len) {
ptr++;
if (*ptr != ':') {
status = ares__buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr));
if (status != ARES_SUCCESS) {
return status;
}
/* Skip over ] */
ares__buf_consume(buf, 1);
} else {
size_t offset;
/* Not in [ ], see if '.' is in first 4 characters, if it is, then its ipv4,
* otherwise treat as ipv6 */
ares__buf_tag(buf);
offset = ares__buf_consume_until_charset(buf, (const unsigned char *)".", 1, ARES_TRUE);
ares__buf_tag_rollback(buf);
ares__buf_tag(buf);
if (offset > 0 && offset < 4) {
/* IPv4 */
if (ares__buf_consume_charset(buf, (const unsigned char *)"0123456789.", 11) == 0) {
return ARES_EBADSTR;
}
/* Missing port number */
if ((size_t)(ptr - str) == len) {
} else {
/* IPv6 */
const unsigned char ipv6_charset[] = "ABCDEFabcdef0123456789.:";
if (ares__buf_consume_charset(buf, ipv6_charset, sizeof(ipv6_charset)) == 0) {
return ARES_EBADSTR;
}
}
port_start = ptr + 1;
port_end = str + (len - 1);
status = ares__buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr));
if (status != ARES_SUCCESS) {
return status;
}
} else {
addr_start = str;
addr_end = str + (len - 1);
}
mylen = (size_t)(addr_end - addr_start) + 1;
/* Larger than buffer with null term */
if (mylen + 1 > sizeof(ipaddr)) {
/* Convert ip address from string to network byte order */
host->family = AF_UNSPEC;
if (ares_dns_pton(ipaddr, host, &addrlen) == NULL) {
return ARES_EBADSTR;
}
memset(ipaddr, 0, sizeof(ipaddr));
memcpy(ipaddr, addr_start, mylen);
/* Pull off port */
if (ares__buf_begins_with(buf, (const unsigned char *)":", 1)) {
char portstr[6];
/* Consume : */
ares__buf_consume(buf, 1);
ares__buf_tag(buf);
if (port_start) {
mylen = (size_t)(port_end - port_start) + 1;
/* Larger than buffer with null term */
if (mylen + 1 > sizeof(ipport)) {
/* Read numbers */
if (ares__buf_consume_charset(buf, (const unsigned char *)"0123456789", 10) == 0) {
return ARES_EBADSTR;
}
memset(ipport, 0, sizeof(ipport));
memcpy(ipport, port_start, mylen);
} else {
snprintf(ipport, sizeof(ipport), "0");
status = ares__buf_tag_fetch_string(buf, portstr, sizeof(portstr));
if (status != ARES_SUCCESS) {
return status;
}
*port = (unsigned short)atoi(portstr);
}
/* Convert textual address to binary format. */
if (ares_inet_pton(AF_INET, ipaddr, &host->addr.addr4) == 1) {
host->family = AF_INET;
} else if (ares_inet_pton(AF_INET6, ipaddr, &host->addr.addr6) == 1) {
host->family = AF_INET6;
} else {
/* Consume any trailing whitespace so we can bail out if there is something
* after we didn't read */
ares__buf_consume_whitespace(buf, ARES_TRUE);
if (ares__buf_len(buf) != 0) {
return ARES_EBADSTR;
}
*port = (unsigned short)atoi(ipport);
return ARES_SUCCESS;
}
@ -295,48 +321,56 @@ fail:
* Returns an error code on failure, else ARES_SUCCESS.
*/
ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig,
const char *str)
const char *str,
ares_bool_t ignore_invalid)
{
struct ares_addr host;
const char *p;
const char *txtaddr;
ares_status_t status;
ares_status_t status = ARES_SUCCESS;
ares__buf_t *buf = NULL;
ares__llist_t *list = NULL;
ares__llist_node_t *node;
/* On Windows, there may be more than one nameserver specified in the same
* registry key, so we parse input as a space or comma separated list.
*/
for (p = str; p;) {
unsigned short port;
/* Skip whitespace and commas. */
while (*p && (ISSPACE(*p) || (*p == ','))) {
p++;
}
if (!*p) {
/* No more input, done. */
break;
}
buf = ares__buf_create_const((const unsigned char *)str, ares_strlen(str));
if (buf == NULL) {
status = ARES_ENOMEM;
goto done;
}
/* Pointer to start of IPv4 or IPv6 address part. */
txtaddr = p;
status = ares__buf_split(buf, (const unsigned char *)" ,", 2,
ARES_BUF_SPLIT_NONE, &list);
if (status != ARES_SUCCESS) {
goto done;
}
/* Advance past this address. */
while (*p && !ISSPACE(*p) && (*p != ',')) {
p++;
}
for (node = ares__llist_node_first(list); node != NULL;
node = ares__llist_node_next(node)) {
ares__buf_t *entry = ares__llist_node_val(node);
struct ares_addr host;
unsigned short port;
if (parse_dnsaddrport(txtaddr, (size_t)(p - txtaddr), &host, &port) !=
ARES_SUCCESS) {
continue;
status = parse_dnsaddrport(entry, &host, &port);
if (status != ARES_SUCCESS) {
if (ignore_invalid) {
continue;
} else {
goto done;
}
}
status = ares__sconfig_append(sconfig, &host, port, port);
if (status != ARES_SUCCESS) {
return status;
goto done;
}
}
return ARES_SUCCESS;
status = ARES_SUCCESS;
done:
ares__llist_destroy(list);
ares__buf_destroy(buf);
return status;
}
static unsigned short ares__sconfig_get_port(const ares_channel_t *channel,
@ -895,165 +929,45 @@ int ares_set_servers_ports(ares_channel_t *channel,
/* Incoming string format: host[:port][,host[:port]]... */
/* IPv6 addresses with ports require square brackets [fe80::1]:53 */
static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv,
int use_port)
static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv)
{
size_t i;
char *csv = NULL;
char *ptr;
const char *start_host;
int cc = 0;
ares_status_t status = ARES_SUCCESS;
struct ares_addr_port_node *servers = NULL;
struct ares_addr_port_node *last = NULL;
if (ares_library_initialized() != ARES_SUCCESS) {
return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
}
ares_status_t status;
ares__llist_t *slist = NULL;
if (!channel) {
if (channel == NULL) {
return ARES_ENODATA;
}
/* NOTE: lock is in ares__servers_update() */
i = ares_strlen(_csv);
if (i == 0) {
if (ares_strlen(_csv) == 0) {
/* blank all servers */
return (ares_status_t)ares_set_servers_ports(channel, NULL);
}
csv = ares_malloc(i + 2);
if (!csv) {
return ARES_ENOMEM;
}
ares_strcpy(csv, _csv, i + 2);
if (csv[i - 1] != ',') { /* make parsing easier by ensuring ending ',' */
csv[i] = ',';
csv[i + 1] = 0;
}
start_host = csv;
for (ptr = csv; *ptr; ptr++) {
if (*ptr == ':') {
/* count colons to determine if we have an IPv6 number or IPv4 with
port */
cc++;
} else if (*ptr == '[') {
/* move start_host if an open square bracket is found wrapping an IPv6
address */
start_host = ptr + 1;
} else if (*ptr == ',') {
char *pp = ptr - 1;
char *p = ptr;
int port = 0;
struct in_addr in4;
struct ares_in6_addr in6;
struct ares_addr_port_node *s = NULL;
*ptr = 0; /* null terminate host:port string */
/* Got an entry..see if the port was specified. */
if (cc > 0) {
while (pp > start_host) {
/* a single close square bracket followed by a colon, ']:' indicates
an IPv6 address with port */
if ((*pp == ']') && (*p == ':')) {
break; /* found port */
}
/* a single colon, ':' indicates an IPv4 address with port */
if ((*pp == ':') && (cc == 1)) {
break; /* found port */
}
if (!(ISDIGIT(*pp) || (*pp == ':'))) {
/* Found end of digits before we found :, so wasn't a port */
/* must allow ':' for IPv6 case of ']:' indicates we found a port */
pp = p = ptr;
break;
}
pp--;
p--;
}
if ((pp != start_host) && ((pp + 1) < ptr)) {
/* Found it. Parse over the port number */
/* when an IPv6 address is wrapped with square brackets the port
starts at pp + 2 */
if (*pp == ']') {
p++; /* move p before ':' */
}
/* p will point to the start of the port */
port = (int)strtol(p, NULL, 10);
*pp = 0; /* null terminate host */
}
}
/* resolve host, try ipv4 first, rslt is in network byte order */
if (!ares_inet_pton(AF_INET, start_host, &in4)) {
/* Ok, try IPv6 then */
if (!ares_inet_pton(AF_INET6, start_host, &in6)) {
status = ARES_EBADSTR;
goto out;
}
/* was ipv6, add new server */
s = ares_malloc(sizeof(*s));
if (!s) {
status = ARES_ENOMEM;
goto out;
}
s->family = AF_INET6;
memcpy(&s->addr, &in6, sizeof(struct ares_in6_addr));
} else {
/* was ipv4, add new server */
s = ares_malloc(sizeof(*s));
if (!s) {
status = ARES_ENOMEM;
goto out;
}
s->family = AF_INET;
memcpy(&s->addr, &in4, sizeof(struct in_addr));
}
if (s) {
s->udp_port = use_port ? port : 0;
s->tcp_port = s->udp_port;
s->next = NULL;
if (last) {
last->next = s;
/* need to move last to maintain the linked list */
last = last->next;
} else {
servers = s;
last = s;
}
}
/* Set up for next one */
start_host = ptr + 1;
cc = 0;
}
status = ares__sconfig_append_fromstr(&slist, _csv, ARES_FALSE);
if (status != ARES_SUCCESS) {
ares__llist_destroy(slist);
return status;
}
status = (ares_status_t)ares_set_servers_ports(channel, servers);
/* NOTE: lock is in ares__servers_update() */
status = ares__servers_update(channel, slist, ARES_TRUE);
out:
if (csv) {
ares_free(csv);
}
while (servers) {
struct ares_addr_port_node *s = servers;
servers = servers->next;
ares_free(s);
}
ares__llist_destroy(slist);
return status;
}
/* We'll go ahead and honor ports anyhow */
int ares_set_servers_csv(ares_channel_t *channel, const char *_csv)
{
/* NOTE: lock is in ares__servers_update() */
return (int)set_servers_csv(channel, _csv, ARES_FALSE);
return (int)set_servers_csv(channel, _csv);
}
int ares_set_servers_ports_csv(ares_channel_t *channel, const char *_csv)
{
/* NOTE: lock is in ares__servers_update() */
return (int)set_servers_csv(channel, _csv, ARES_TRUE);
return (int)set_servers_csv(channel, _csv);
}

@ -869,7 +869,7 @@ TEST_F(LibraryTest, BufMisuse) {
EXPECT_EQ((size_t)0, ares__buf_consume_whitespace(NULL, ARES_FALSE));
EXPECT_EQ((size_t)0, ares__buf_consume_nonwhitespace(NULL));
EXPECT_EQ((size_t)0, ares__buf_consume_line(NULL, ARES_FALSE));
EXPECT_NE(ARES_SUCCESS, ares__buf_begins_with(NULL, NULL, 0));
EXPECT_EQ(ARES_FALSE, ares__buf_begins_with(NULL, NULL, 0));
EXPECT_EQ((size_t)0, ares__buf_get_position(NULL));
EXPECT_NE(ARES_SUCCESS, ares__buf_set_position(NULL, 0));
EXPECT_NE(ARES_SUCCESS, ares__dns_name_parse(NULL, NULL, ARES_FALSE));

@ -134,13 +134,11 @@ TEST_F(DefaultChannelTest, SetServersCSV) {
EXPECT_EQ(expected, GetNameServers(channel_));
// Same, with spaces
EXPECT_EQ(ARES_EBADSTR,
EXPECT_EQ(ARES_SUCCESS,
ares_set_servers_csv(channel_, "1.2.3.4 , [0102:0304:0506:0708:0910:1112:1314:1516]:53, 2.3.4.5"));
EXPECT_EQ(expected, GetNameServers(channel_));
// Same, with ports
EXPECT_EQ(ARES_SUCCESS,
ares_set_servers_csv(channel_, "1.2.3.4:54,[0102:0304:0506:0708:0910:1112:1314:1516]:80,2.3.4.5:55"));
EXPECT_EQ(expected, GetNameServers(channel_));
EXPECT_EQ(ARES_SUCCESS,
ares_set_servers_ports_csv(channel_, "1.2.3.4:54,[0102:0304:0506:0708:0910:1112:1314:1516]:80,2.3.4.5:55"));
std::vector<std::string> expected2 = {"1.2.3.4:54", "[0102:0304:0506:0708:0910:1112:1314:1516]:80", "2.3.4.5:55"};

Loading…
Cancel
Save