api: Allow injection of user-specified malloc/free functions

Add a new ares_library_init_mem() initialization function for the
library which allows the library user to specify their own malloc,
realloc & free equivalents for use library-wide.

Store these function pointers in library-wide global variables,
defaulting to libc's malloc(), realloc() and free().

Change all calls to malloc, realloc and free to use the function pointer
instead.  Also ensure that ares_strdup() is always available
(even if the local environment includes strdup(3)), and change the
library code to always use it.

Convert calls to calloc() to use ares_malloc() + memset
This commit is contained in:
David Drysdale 2015-09-29 10:12:25 +01:00
parent d493e9b17c
commit f1bcfa1122
35 changed files with 352 additions and 309 deletions

5
ares.h
View File

@ -296,6 +296,11 @@ typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd,
CARES_EXTERN int ares_library_init(int flags);
CARES_EXTERN int ares_library_init_mem(int flags,
void *(*amalloc)(size_t size),
void (*afree)(void *ptr),
void *(*arealloc)(void *ptr, size_t size));
CARES_EXTERN int ares_library_initialized(void);
CARES_EXTERN void ares_library_cleanup(void);

View File

@ -30,14 +30,14 @@ void ares__close_sockets(ares_channel channel, struct server_state *server)
sendreq = server->qhead;
server->qhead = sendreq->next;
if (sendreq->data_storage != NULL)
free(sendreq->data_storage);
free(sendreq);
ares_free(sendreq->data_storage);
ares_free(sendreq);
}
server->qtail = NULL;
/* Reset any existing input buffer. */
if (server->tcp_buffer)
free(server->tcp_buffer);
ares_free(server->tcp_buffer);
server->tcp_buffer = NULL;
server->tcp_lenbuf_pos = 0;

View File

@ -164,7 +164,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
*/
/* Allocate memory for the hostent structure. */
hostent = malloc(sizeof(struct hostent));
hostent = ares_malloc(sizeof(struct hostent));
if (!hostent)
break;
@ -173,16 +173,16 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
hostent->h_addr_list = NULL;
/* Copy official host name. */
hostent->h_name = strdup(txthost);
hostent->h_name = ares_strdup(txthost);
if (!hostent->h_name)
break;
/* Copy network address. */
hostent->h_addr_list = malloc(2 * sizeof(char *));
hostent->h_addr_list = ares_malloc(2 * sizeof(char *));
if (!hostent->h_addr_list)
break;
hostent->h_addr_list[1] = NULL;
hostent->h_addr_list[0] = malloc(addrlen);
hostent->h_addr_list[0] = ares_malloc(addrlen);
if (!hostent->h_addr_list[0])
break;
if (addr.family == AF_INET)
@ -191,7 +191,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
/* Copy aliases. */
hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
hostent->h_aliases = ares_malloc((naliases + 1) * sizeof(char *));
if (!hostent->h_aliases)
break;
alias = hostent->h_aliases;
@ -207,7 +207,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
while (*q && ISSPACE(*q))
q++;
*p = '\0';
if ((*alias = strdup(txtalias)) == NULL)
if ((*alias = ares_strdup(txtalias)) == NULL)
break;
alias++;
txtalias = *q ? q : NULL;
@ -221,7 +221,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
hostent->h_length = aresx_uztoss(addrlen);
/* Free line buffer. */
free(line);
ares_free(line);
/* Return hostent successfully */
*host = hostent;
@ -231,7 +231,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
/* If allocated, free line buffer. */
if (line)
free(line);
ares_free(line);
if (status == ARES_SUCCESS)
{
@ -239,20 +239,20 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
if (hostent)
{
if (hostent->h_name)
free((char *) hostent->h_name);
ares_free((char *) hostent->h_name);
if (hostent->h_aliases)
{
for (alias = hostent->h_aliases; *alias; alias++)
free(*alias);
free(hostent->h_aliases);
ares_free(*alias);
ares_free(hostent->h_aliases);
}
if (hostent->h_addr_list)
{
if (hostent->h_addr_list[0])
free(hostent->h_addr_list[0]);
free(hostent->h_addr_list);
ares_free(hostent->h_addr_list[0]);
ares_free(hostent->h_addr_list);
}
free(hostent);
ares_free(hostent);
}
return ARES_ENOMEM;
}

View File

@ -36,7 +36,7 @@ int ares__read_line(FILE *fp, char **buf, size_t *bufsize)
if (*buf == NULL)
{
*buf = malloc(128);
*buf = ares_malloc(128);
if (!*buf)
return ARES_ENOMEM;
*bufsize = 128;
@ -59,10 +59,10 @@ int ares__read_line(FILE *fp, char **buf, size_t *bufsize)
continue;
/* Allocate more space. */
newbuf = realloc(*buf, *bufsize * 2);
newbuf = ares_realloc(*buf, *bufsize * 2);
if (!newbuf)
{
free(*buf);
ares_free(*buf);
*buf = NULL;
return ARES_ENOMEM;
}

View File

@ -130,7 +130,7 @@ int ares_create_query(const char *name, int dnsclass, int type,
return ARES_EBADNAME;
*buflen = len + HFIXEDSZ + QFIXEDSZ + (max_udp_size ? EDNSFIXEDSZ : 0);
*buf = malloc(*buflen);
*buf = ares_malloc(*buflen);
if (!*buf)
return ARES_ENOMEM;

View File

@ -67,7 +67,7 @@ void ares_free_data(void *dataptr)
if (ptr->data.mx_reply.next)
ares_free_data(ptr->data.mx_reply.next);
if (ptr->data.mx_reply.host)
free(ptr->data.mx_reply.host);
ares_free(ptr->data.mx_reply.host);
break;
case ARES_DATATYPE_SRV_REPLY:
@ -75,7 +75,7 @@ void ares_free_data(void *dataptr)
if (ptr->data.srv_reply.next)
ares_free_data(ptr->data.srv_reply.next);
if (ptr->data.srv_reply.host)
free(ptr->data.srv_reply.host);
ares_free(ptr->data.srv_reply.host);
break;
case ARES_DATATYPE_TXT_REPLY:
@ -83,7 +83,7 @@ void ares_free_data(void *dataptr)
if (ptr->data.txt_reply.next)
ares_free_data(ptr->data.txt_reply.next);
if (ptr->data.txt_reply.txt)
free(ptr->data.txt_reply.txt);
ares_free(ptr->data.txt_reply.txt);
break;
case ARES_DATATYPE_ADDR_NODE:
@ -97,27 +97,27 @@ void ares_free_data(void *dataptr)
if (ptr->data.naptr_reply.next)
ares_free_data(ptr->data.naptr_reply.next);
if (ptr->data.naptr_reply.flags)
free(ptr->data.naptr_reply.flags);
ares_free(ptr->data.naptr_reply.flags);
if (ptr->data.naptr_reply.service)
free(ptr->data.naptr_reply.service);
ares_free(ptr->data.naptr_reply.service);
if (ptr->data.naptr_reply.regexp)
free(ptr->data.naptr_reply.regexp);
ares_free(ptr->data.naptr_reply.regexp);
if (ptr->data.naptr_reply.replacement)
free(ptr->data.naptr_reply.replacement);
ares_free(ptr->data.naptr_reply.replacement);
break;
case ARES_DATATYPE_SOA_REPLY:
if (ptr->data.soa_reply.nsname)
free(ptr->data.soa_reply.nsname);
ares_free(ptr->data.soa_reply.nsname);
if (ptr->data.soa_reply.hostmaster)
free(ptr->data.soa_reply.hostmaster);
ares_free(ptr->data.soa_reply.hostmaster);
break;
default:
return;
}
free(ptr);
ares_free(ptr);
}
@ -136,7 +136,7 @@ void *ares_malloc_data(ares_datatype type)
{
struct ares_data *ptr;
ptr = malloc(sizeof(struct ares_data));
ptr = ares_malloc(sizeof(struct ares_data));
if (!ptr)
return NULL;
@ -190,7 +190,7 @@ void *ares_malloc_data(ares_datatype type)
break;
default:
free(ptr);
ares_free(ptr);
return NULL;
}

View File

@ -27,15 +27,15 @@ void ares_destroy_options(struct ares_options *options)
int i;
if(options->servers)
free(options->servers);
ares_free(options->servers);
for (i = 0; i < options->ndomains; i++)
free(options->domains[i]);
ares_free(options->domains[i]);
if(options->domains)
free(options->domains);
ares_free(options->domains);
if(options->sortlist)
free(options->sortlist);
ares_free(options->sortlist);
if(options->lookups)
free(options->lookups);
ares_free(options->lookups);
}
void ares_destroy(ares_channel channel)
@ -75,17 +75,17 @@ void ares_destroy(ares_channel channel)
if (channel->domains) {
for (i = 0; i < channel->ndomains; i++)
free(channel->domains[i]);
free(channel->domains);
ares_free(channel->domains[i]);
ares_free(channel->domains);
}
if(channel->sortlist)
free(channel->sortlist);
ares_free(channel->sortlist);
if (channel->lookups)
free(channel->lookups);
ares_free(channel->lookups);
free(channel);
ares_free(channel);
}
void ares__destroy_servers_state(ares_channel channel)
@ -101,7 +101,7 @@ void ares__destroy_servers_state(ares_channel channel)
ares__close_sockets(channel, server);
assert(ares__is_list_empty(&server->queries_to_server));
}
free(channel->servers);
ares_free(channel->servers);
channel->servers = NULL;
}
channel->nservers = -1;

View File

@ -74,7 +74,7 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
if (nlen.sig < 0)
return ARES_EBADNAME;
*s = malloc(nlen.uns + 1);
*s = ares_malloc(nlen.uns + 1);
if (!*s)
return ARES_ENOMEM;
q = *s;

View File

@ -54,7 +54,7 @@ int ares_expand_string(const unsigned char *encoded,
encoded++;
*s = malloc(elen.uns+1);
*s = ares_malloc(elen.uns+1);
if (*s == NULL)
return ARES_ENOMEM;
q = *s;

View File

@ -30,12 +30,12 @@ void ares_free_hostent(struct hostent *host)
if (!host)
return;
free((char *)(host->h_name));
ares_free((char *)(host->h_name));
for (p = host->h_aliases; *p; p++)
free(*p);
free(host->h_aliases);
free(host->h_addr_list[0]); /* no matter if there is one or many entries,
ares_free(*p);
ares_free(host->h_aliases);
ares_free(host->h_addr_list[0]); /* no matter if there is one or many entries,
there is only one malloc for all of them */
free(host->h_addr_list);
free(host);
ares_free(host->h_addr_list);
ares_free(host);
}

View File

@ -21,5 +21,5 @@
void ares_free_string(void *str)
{
free(str);
ares_free(str);
}

View File

@ -79,7 +79,7 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
return;
}
aquery = malloc(sizeof(struct addr_query));
aquery = ares_malloc(sizeof(struct addr_query));
if (!aquery)
{
callback(arg, ARES_ENOMEM, 0, NULL);
@ -169,7 +169,7 @@ static void end_aquery(struct addr_query *aquery, int status,
aquery->callback(aquery->arg, status, aquery->timeouts, host);
if (host)
ares_free_hostent(host);
free(aquery);
ares_free(aquery);
}
static int file_lookup(struct ares_addr *addr, struct hostent **host)

View File

@ -99,18 +99,18 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
return;
/* Allocate and fill in the host query structure. */
hquery = malloc(sizeof(struct host_query));
hquery = ares_malloc(sizeof(struct host_query));
if (!hquery)
{
callback(arg, ARES_ENOMEM, 0, NULL);
return;
}
hquery->channel = channel;
hquery->name = strdup(name);
hquery->name = ares_strdup(name);
hquery->want_family = family;
hquery->sent_family = -1; /* nothing is sent yet */
if (!hquery->name) {
free(hquery);
ares_free(hquery);
callback(arg, ARES_ENOMEM, 0, NULL);
return;
}
@ -227,8 +227,8 @@ static void end_hquery(struct host_query *hquery, int status,
hquery->callback(hquery->arg, status, hquery->timeouts, host);
if (host)
ares_free_hostent(host);
free(hquery->name);
free(hquery);
ares_free(hquery->name);
ares_free(hquery);
}
/* If the name looks like an IP address, fake up a host entry, end the
@ -287,7 +287,7 @@ static int fake_hostent(const char *name, int family,
addrs[0] = (char *)&in6;
}
/* Duplicate the name, to avoid a constness violation. */
hostent.h_name = strdup(name);
hostent.h_name = ares_strdup(name);
if (!hostent.h_name)
{
callback(arg, ARES_ENOMEM, 0, NULL);
@ -301,7 +301,7 @@ static int fake_hostent(const char *name, int family,
hostent.h_addr_list = addrs;
callback(arg, ARES_SUCCESS, 0, &hostent);
free((char *)(hostent.h_name));
ares_free((char *)(hostent.h_name));
return 1;
}

View File

@ -163,7 +163,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa,
/* This is where a DNS lookup becomes necessary */
else
{
niquery = malloc(sizeof(struct nameinfo_query));
niquery = ares_malloc(sizeof(struct nameinfo_query));
if (!niquery)
{
callback(arg, ARES_ENOMEM, 0, NULL, NULL);
@ -234,7 +234,7 @@ static void nameinfo_callback(void *arg, int status, int timeouts,
niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts,
(char *)(host->h_name),
service);
free(niquery);
ares_free(niquery);
return;
}
/* We couldn't find the host, but it's OK, we can use the IP */
@ -265,11 +265,11 @@ static void nameinfo_callback(void *arg, int status, int timeouts,
}
niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, ipbuf,
service);
free(niquery);
ares_free(niquery);
return;
}
niquery->callback(niquery->arg, status, niquery->timeouts, NULL, NULL);
free(niquery);
ares_free(niquery);
}
static char *lookup_service(unsigned short port, int flags,

View File

@ -131,7 +131,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
if (ares_library_initialized() != ARES_SUCCESS)
return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
channel = malloc(sizeof(struct ares_channeldata));
channel = ares_malloc(sizeof(struct ares_channeldata));
if (!channel) {
*channelptr = NULL;
return ARES_ENOMEM;
@ -233,18 +233,18 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
{
/* Something failed; clean up memory we may have allocated. */
if (channel->servers)
free(channel->servers);
ares_free(channel->servers);
if (channel->domains)
{
for (i = 0; i < channel->ndomains; i++)
free(channel->domains[i]);
free(channel->domains);
ares_free(channel->domains[i]);
ares_free(channel->domains);
}
if (channel->sortlist)
free(channel->sortlist);
ares_free(channel->sortlist);
if(channel->lookups)
free(channel->lookups);
free(channel);
ares_free(channel->lookups);
ares_free(channel);
return status;
}
@ -367,7 +367,7 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
ipv4_nservers++;
}
if (ipv4_nservers) {
options->servers = malloc(ipv4_nservers * sizeof(struct in_addr));
options->servers = ares_malloc(ipv4_nservers * sizeof(struct in_addr));
if (!options->servers)
return ARES_ENOMEM;
for (i = j = 0; i < channel->nservers; i++)
@ -383,14 +383,14 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
/* copy domains */
if (channel->ndomains) {
options->domains = malloc(channel->ndomains * sizeof(char *));
options->domains = ares_malloc(channel->ndomains * sizeof(char *));
if (!options->domains)
return ARES_ENOMEM;
for (i = 0; i < channel->ndomains; i++)
{
options->ndomains = i;
options->domains[i] = strdup(channel->domains[i]);
options->domains[i] = ares_strdup(channel->domains[i]);
if (!options->domains[i])
return ARES_ENOMEM;
}
@ -399,14 +399,14 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
/* copy lookups */
if (channel->lookups) {
options->lookups = strdup(channel->lookups);
options->lookups = ares_strdup(channel->lookups);
if (!options->lookups && channel->lookups)
return ARES_ENOMEM;
}
/* copy sortlist */
if (channel->nsort) {
options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
options->sortlist = ares_malloc(channel->nsort * sizeof(struct apattern));
if (!options->sortlist)
return ARES_ENOMEM;
for (i = 0; i < channel->nsort; i++)
@ -462,7 +462,7 @@ static int init_by_options(ares_channel channel,
if (options->nservers > 0)
{
channel->servers =
malloc(options->nservers * sizeof(struct server_state));
ares_malloc(options->nservers * sizeof(struct server_state));
if (!channel->servers)
return ARES_ENOMEM;
for (i = 0; i < options->nservers; i++)
@ -484,13 +484,13 @@ static int init_by_options(ares_channel channel,
/* Avoid zero size allocations at any cost */
if (options->ndomains > 0)
{
channel->domains = malloc(options->ndomains * sizeof(char *));
channel->domains = ares_malloc(options->ndomains * sizeof(char *));
if (!channel->domains)
return ARES_ENOMEM;
for (i = 0; i < options->ndomains; i++)
{
channel->ndomains = i;
channel->domains[i] = strdup(options->domains[i]);
channel->domains[i] = ares_strdup(options->domains[i]);
if (!channel->domains[i])
return ARES_ENOMEM;
}
@ -501,7 +501,7 @@ static int init_by_options(ares_channel channel,
/* Set lookups, if given. */
if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
{
channel->lookups = strdup(options->lookups);
channel->lookups = ares_strdup(options->lookups);
if (!channel->lookups)
return ARES_ENOMEM;
}
@ -509,7 +509,7 @@ static int init_by_options(ares_channel channel,
/* copy sortlist */
if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1) &&
(options->nsort>0)) {
channel->sortlist = malloc(options->nsort * sizeof(struct apattern));
channel->sortlist = ares_malloc(options->nsort * sizeof(struct apattern));
if (!channel->sortlist)
return ARES_ENOMEM;
for (i = 0; i < options->nsort; i++)
@ -575,7 +575,7 @@ static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
/* Allocate buffer of indicated size plus one given that string
might have been stored without null termination */
*outptr = malloc(size+1);
*outptr = ares_malloc(size+1);
if (!*outptr)
return 0;
@ -584,7 +584,7 @@ static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
(unsigned char *)*outptr, &size);
if ((res != ERROR_SUCCESS) || (size == 1))
{
free(*outptr);
ares_free(*outptr);
*outptr = NULL;
return 0;
}
@ -617,7 +617,7 @@ static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
/* Allocate buffer of indicated size plus one given that string
might have been stored without null termination */
*outptr = malloc(size+1);
*outptr = ares_malloc(size+1);
if (!*outptr)
return 0;
@ -626,7 +626,7 @@ static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
(unsigned char *)*outptr, &size);
if ((res != ERROR_SUCCESS) || (size == 1))
{
free(*outptr);
ares_free(*outptr);
*outptr = NULL;
return 0;
}
@ -827,16 +827,16 @@ static void commajoin(char **dst, const char *src)
if (*dst)
{
tmp = malloc(strlen(*dst) + strlen(src) + 2);
tmp = ares_malloc(strlen(*dst) + strlen(src) + 2);
if (!tmp)
return;
sprintf(tmp, "%s,%s", *dst, src);
free(*dst);
ares_free(*dst);
*dst = tmp;
}
else
{
*dst = malloc(strlen(src) + 1);
*dst = ares_malloc(strlen(src) + 1);
if (!*dst)
return;
strcpy(*dst, src);
@ -874,7 +874,7 @@ static int get_DNS_NetworkParams(char **outptr)
if (ares_fpGetNetworkParams == ZERO_NULL)
return 0;
fi = malloc(size);
fi = ares_malloc(size);
if (!fi)
return 0;
@ -882,7 +882,7 @@ static int get_DNS_NetworkParams(char **outptr)
if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
goto done;
newfi = realloc(fi, size);
newfi = ares_realloc(fi, size);
if (!newfi)
goto done;
@ -919,7 +919,7 @@ static int get_DNS_NetworkParams(char **outptr)
done:
if (fi)
free(fi);
ares_free(fi);
if (!*outptr)
return 0;
@ -967,7 +967,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
if (ares_fpGetAdaptersAddresses == ZERO_NULL)
return 0;
ipaa = malloc(Bufsz);
ipaa = ares_malloc(Bufsz);
if (!ipaa)
return 0;
@ -981,7 +981,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
{
if (Bufsz < ReqBufsz)
{
newipaa = realloc(ipaa, ReqBufsz);
newipaa = ares_realloc(ipaa, ReqBufsz);
if (!newipaa)
goto done;
Bufsz = ReqBufsz;
@ -1036,7 +1036,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
done:
if (ipaa)
free(ipaa);
ares_free(ipaa);
if (!*outptr)
return 0;
@ -1097,7 +1097,7 @@ static int init_by_resolv_conf(ares_channel channel)
if (get_DNS_Windows(&line))
{
status = config_nameserver(&servers, &nservers, line);
free(line);
ares_free(line);
}
if (status == ARES_SUCCESS)
@ -1115,7 +1115,7 @@ static int init_by_resolv_conf(ares_channel channel)
line = getenv("Inet$Resolvers");
status = ARES_EOF;
if (line) {
char *resolvers = strdup(line), *pos, *space;
char *resolvers = ares_strdup(line), *pos, *space;
if (!resolvers)
return ARES_ENOMEM;
@ -1134,7 +1134,7 @@ static int init_by_resolv_conf(ares_channel channel)
if (status == ARES_SUCCESS)
status = ARES_EOF;
free(resolvers);
ares_free(resolvers);
}
#elif defined(WATT32)
@ -1147,9 +1147,10 @@ static int init_by_resolv_conf(ares_channel channel)
return ARES_SUCCESS; /* use localhost DNS server */
nservers = i;
servers = calloc(i, sizeof(struct server_state));
servers = ares_malloc(sizeof(struct server_state));
if (!servers)
return ARES_ENOMEM;
memset(servers, 0, sizeof(struct server_state));
for (i = 0; def_nameservers[i]; i++)
{
@ -1208,13 +1209,13 @@ static int init_by_resolv_conf(ares_channel channel)
while ((entries < MAXDNSRCH) && res.dnsrch[entries])
entries++;
channel->domains = malloc(entries * sizeof(char *));
channel->domains = ares_malloc(entries * sizeof(char *));
if (!channel->domains) {
status = ARES_ENOMEM;
} else {
channel->ndomains = entries;
for (int i = 0; i < channel->ndomains; ++i) {
channel->domains[i] = strdup(res.dnsrch[i]);
channel->domains[i] = ares_strdup(res.dnsrch[i]);
if (!channel->domains[i])
status = ARES_ENOMEM;
}
@ -1376,7 +1377,7 @@ static int init_by_resolv_conf(ares_channel channel)
}
if(line)
free(line);
ares_free(line);
}
#endif
@ -1385,9 +1386,9 @@ static int init_by_resolv_conf(ares_channel channel)
if (status != ARES_EOF)
{
if (servers != NULL)
free(servers);
ares_free(servers);
if (sortlist != NULL)
free(sortlist);
ares_free(sortlist);
return status;
}
@ -1436,7 +1437,7 @@ static int init_by_defaults(ares_channel channel)
if (channel->nservers == -1) {
/* If nobody specified servers, try a local named. */
channel->servers = malloc(sizeof(struct server_state));
channel->servers = ares_malloc(sizeof(struct server_state));
if (!channel->servers) {
rc = ARES_ENOMEM;
goto error;
@ -1467,7 +1468,7 @@ static int init_by_defaults(ares_channel channel)
int res;
channel->ndomains = 0; /* default to none */
hostname = malloc(len);
hostname = ares_malloc(len);
if(!hostname) {
rc = ARES_ENOMEM;
goto error;
@ -1480,7 +1481,7 @@ static int init_by_defaults(ares_channel channel)
char *p;
len *= 2;
lenv *= 2;
p = realloc(hostname, len);
p = ares_realloc(hostname, len);
if(!p) {
rc = ARES_ENOMEM;
goto error;
@ -1498,12 +1499,12 @@ static int init_by_defaults(ares_channel channel)
dot = strchr(hostname, '.');
if (dot) {
/* a dot was found */
channel->domains = malloc(sizeof(char *));
channel->domains = ares_malloc(sizeof(char *));
if (!channel->domains) {
rc = ARES_ENOMEM;
goto error;
}
channel->domains[0] = strdup(dot + 1);
channel->domains[0] = ares_strdup(dot + 1);
if (!channel->domains[0]) {
rc = ARES_ENOMEM;
goto error;
@ -1519,7 +1520,7 @@ static int init_by_defaults(ares_channel channel)
}
if (!channel->lookups) {
channel->lookups = strdup("fb");
channel->lookups = ares_strdup("fb");
if (!channel->lookups)
rc = ARES_ENOMEM;
}
@ -1527,25 +1528,25 @@ static int init_by_defaults(ares_channel channel)
error:
if(rc) {
if(channel->servers) {
free(channel->servers);
ares_free(channel->servers);
channel->servers = NULL;
}
if(channel->domains && channel->domains[0])
free(channel->domains[0]);
ares_free(channel->domains[0]);
if(channel->domains) {
free(channel->domains);
ares_free(channel->domains);
channel->domains = NULL;
}
if(channel->lookups) {
free(channel->lookups);
ares_free(channel->lookups);
channel->lookups = NULL;
}
}
if(hostname)
free(hostname);
ares_free(hostname);
return rc;
}
@ -1596,7 +1597,7 @@ static int config_lookup(ares_channel channel, const char *str,
p++;
}
*l = '\0';
channel->lookups = strdup(lookups);
channel->lookups = ares_strdup(lookups);
return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
}
#endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
@ -1642,8 +1643,8 @@ static int config_nameserver(struct server_state **servers, int *nservers,
continue;
/* Resize servers state array. */
newserv = realloc(*servers, (*nservers + 1) *
sizeof(struct server_state));
newserv = ares_realloc(*servers, (*nservers + 1) *
sizeof(struct server_state));
if (!newserv)
return ARES_ENOMEM;
@ -1705,7 +1706,7 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
pat.mask.bits = (unsigned short)bits;
pat.family = AF_INET6;
if (!sortlist_alloc(sortlist, nsort, &pat)) {
free(*sortlist);
ares_free(*sortlist);
*sortlist = NULL;
return ARES_ENOMEM;
}
@ -1718,7 +1719,7 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
pat.mask.bits = (unsigned short)bits;
pat.family = AF_INET;
if (!sortlist_alloc(sortlist, nsort, &pat)) {
free(*sortlist);
ares_free(*sortlist);
*sortlist = NULL;
return ARES_ENOMEM;
}
@ -1738,7 +1739,7 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
pat.family = AF_INET;
pat.type = PATTERN_MASK;
if (!sortlist_alloc(sortlist, nsort, &pat)) {
free(*sortlist);
ares_free(*sortlist);
*sortlist = NULL;
return ARES_ENOMEM;
}
@ -1767,8 +1768,8 @@ static int set_search(ares_channel channel, const char *str)
/* LCOV_EXCL_START: all callers check ndomains == -1 */
/* if we already have some domains present, free them first */
for(n=0; n < channel->ndomains; n++)
free(channel->domains[n]);
free(channel->domains);
ares_free(channel->domains[n]);
ares_free(channel->domains);
channel->domains = NULL;
channel->ndomains = -1;
} /* LCOV_EXCL_STOP */
@ -1791,7 +1792,7 @@ static int set_search(ares_channel channel, const char *str)
return ARES_SUCCESS;
}
channel->domains = malloc(n * sizeof(char *));
channel->domains = ares_malloc(n * sizeof(char *));
if (!channel->domains)
return ARES_ENOMEM;
@ -1804,7 +1805,7 @@ static int set_search(ares_channel channel, const char *str)
q = p;
while (*q && !ISSPACE(*q))
q++;
channel->domains[n] = malloc(q - p + 1);
channel->domains[n] = ares_malloc(q - p + 1);
if (!channel->domains[n])
return ARES_ENOMEM;
memcpy(channel->domains[n], p, q - p);
@ -1931,7 +1932,7 @@ static int sortlist_alloc(struct apattern **sortlist, int *nsort,
struct apattern *pat)
{
struct apattern *newsort;
newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
if (!newsort)
return 0;
newsort[*nsort] = *pat;
@ -2017,9 +2018,10 @@ static int init_id_key(rc4_key* key,int key_data_len)
short counter;
unsigned char *key_data_ptr = 0;
key_data_ptr = calloc(1,key_data_len);
key_data_ptr = ares_malloc(key_data_len);
if (!key_data_ptr)
return ARES_ENOMEM;
memset(key_data_ptr, 0, key_data_len);
state = &key->state[0];
for(counter = 0; counter < 256; counter++)
@ -2038,7 +2040,7 @@ static int init_id_key(rc4_key* key,int key_data_len)
index1 = (unsigned char)((index1 + 1) % key_data_len);
}
free(key_data_ptr);
ares_free(key_data_ptr);
return ARES_SUCCESS;
}

View File

@ -22,6 +22,7 @@ ares_library_init \- c-ares library initialization
.B #include <ares.h>
.PP
.B int ares_library_init(int \fIflags\fP)
.B int ares_library_init_mem(int \fIflags\fP, void *(*\fIamalloc\fP)(size_t), void (*\fIafree\fP)(void *))
.PP
.B cc file.c -lcares
.fi
@ -51,6 +52,12 @@ ORing the values together. In normal operation you should specify
\fIARES_LIB_INIT_ALL\fP. Don't use any other value unless you are
familiar with it and trying to control some internal c-ares feature.
.PP
The
.B ares_library_init_mem
function allows the caller to provide memory management
functions that the c-ares library will be use instead of \fImalloc(3)\fP and
\fIfree(3)\fP.
.PP
.B This function is not thread safe.
You have to call it once the program has started, but this call must be done
before the program starts any other thread. This is required to avoid

View File

@ -34,6 +34,11 @@ fpGetAdaptersAddresses_t ares_fpGetAdaptersAddresses = ZERO_NULL;
static unsigned int ares_initialized;
static int ares_init_flags;
/* library-private global vars with visibility across the whole library */
void *(*ares_malloc)(size_t size) = malloc;
void *(*ares_realloc)(void *ptr, size_t size) = realloc;
void (*ares_free)(void *ptr) = free;
#ifdef USE_WINSOCK
static HMODULE hnd_iphlpapi;
static HMODULE hnd_advapi32;
@ -119,6 +124,20 @@ int ares_library_init(int flags)
return ARES_SUCCESS;
}
int ares_library_init_mem(int flags,
void *(*amalloc)(size_t size),
void (*afree)(void *ptr),
void *(*arealloc)(void *ptr, size_t size))
{
if (amalloc)
ares_malloc = amalloc;
if (arealloc)
ares_realloc = arealloc;
if (afree)
ares_free = afree;
return ares_library_init(flags);
}
void ares_library_cleanup(void)
{
@ -132,6 +151,8 @@ void ares_library_cleanup(void)
ares_win32_cleanup();
ares_init_flags = ARES_LIB_INIT_NONE;
ares_malloc = malloc;
ares_free = free;
}

View File

@ -107,7 +107,7 @@ int ares_set_servers(ares_channel channel,
if (num_srvrs > 0)
{
/* Allocate storage for servers state */
channel->servers = malloc(num_srvrs * sizeof(struct server_state));
channel->servers = ares_malloc(num_srvrs * sizeof(struct server_state));
if (!channel->servers)
{
return ARES_ENOMEM;
@ -157,7 +157,7 @@ int ares_set_servers_csv(ares_channel channel,
if (i == 0)
return ARES_SUCCESS; /* blank all servers */
csv = malloc(i + 2);
csv = ares_malloc(i + 2);
if (!csv)
return ARES_ENOMEM;
@ -227,7 +227,7 @@ int ares_set_servers_csv(ares_channel channel,
goto out;
}
/* was ipv6, add new server */
s = malloc(sizeof(*s));
s = ares_malloc(sizeof(*s));
if (!s) {
rv = ARES_ENOMEM;
goto out;
@ -237,7 +237,7 @@ int ares_set_servers_csv(ares_channel channel,
}
else {
/* was ipv4, add new server */
s = malloc(sizeof(*s));
s = ares_malloc(sizeof(*s));
if (!s) {
rv = ARES_ENOMEM;
goto out;
@ -270,11 +270,11 @@ int ares_set_servers_csv(ares_channel channel,
out:
if (csv)
free(csv);
ares_free(csv);
while (servers) {
struct ares_addr_node *s = servers;
servers = servers->next;
free(s);
ares_free(s);
}
return rv;

View File

@ -85,7 +85,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
return status;
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free(hostname);
ares_free(hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
@ -94,17 +94,17 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
{
/* Allocate addresses and aliases; ancount gives an upper bound for
both. */
addrs = malloc(ancount * sizeof(struct in_addr));
addrs = ares_malloc(ancount * sizeof(struct in_addr));
if (!addrs)
{
free(hostname);
ares_free(hostname);
return ARES_ENOMEM;
}
aliases = malloc((ancount + 1) * sizeof(char *));
aliases = ares_malloc((ancount + 1) * sizeof(char *));
if (!aliases)
{
free(hostname);
free(addrs);
ares_free(hostname);
ares_free(addrs);
return ARES_ENOMEM;
}
}
@ -127,7 +127,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
aptr += len;
if (aptr + RRFIXEDSZ > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -138,7 +138,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
aptr += RRFIXEDSZ;
if (aptr + rr_len > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -151,7 +151,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
{
if (aptr + sizeof(struct in_addr) > abuf + alen)
{ /* LCOV_EXCL_START: already checked above */
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
} /* LCOV_EXCL_STOP */
@ -162,7 +162,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
struct ares_addrttl * const at = &addrttls[naddrs];
if (aptr + sizeof(struct in_addr) > abuf + alen)
{ /* LCOV_EXCL_START: already checked above */
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
} /* LCOV_EXCL_STOP */
@ -179,7 +179,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
if (aliases)
aliases[naliases] = rr_name;
else
free(rr_name);
ares_free(rr_name);
naliases++;
/* Decode the RR data and replace the hostname with it. */
@ -187,7 +187,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
&len);
if (status != ARES_SUCCESS)
break;
free(hostname);
ares_free(hostname);
hostname = rr_data;
/* Take the min of the TTLs we see in the CNAME chain. */
@ -195,7 +195,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
cname_ttl = rr_ttl;
}
else
free(rr_name);
ares_free(rr_name);
aptr += rr_len;
if (aptr > abuf + alen)
@ -228,10 +228,10 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
if (host)
{
/* Allocate memory to build the host entry. */
hostent = malloc(sizeof(struct hostent));
hostent = ares_malloc(sizeof(struct hostent));
if (hostent)
{
hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char *));
hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
if (hostent->h_addr_list)
{
/* Fill in the hostent and return successfully. */
@ -243,11 +243,11 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
hostent->h_addr_list[i] = (char *) &addrs[i];
hostent->h_addr_list[naddrs] = NULL;
if (!naddrs && addrs)
free(addrs);
ares_free(addrs);
*host = hostent;
return ARES_SUCCESS;
}
free(hostent);
ares_free(hostent);
}
status = ARES_ENOMEM;
}
@ -255,10 +255,10 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
if (aliases)
{
for (i = 0; i < naliases; i++)
free(aliases[i]);
free(aliases);
ares_free(aliases[i]);
ares_free(aliases);
}
free(addrs);
free(hostname);
ares_free(addrs);
ares_free(hostname);
return status;
}

View File

@ -87,7 +87,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
return status;
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free(hostname);
ares_free(hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
@ -95,17 +95,17 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
/* Allocate addresses and aliases; ancount gives an upper bound for both. */
if (host)
{
addrs = malloc(ancount * sizeof(struct ares_in6_addr));
addrs = ares_malloc(ancount * sizeof(struct ares_in6_addr));
if (!addrs)
{
free(hostname);
ares_free(hostname);
return ARES_ENOMEM;
}
aliases = malloc((ancount + 1) * sizeof(char *));
aliases = ares_malloc((ancount + 1) * sizeof(char *));
if (!aliases)
{
free(hostname);
free(addrs);
ares_free(hostname);
ares_free(addrs);
return ARES_ENOMEM;
}
}
@ -127,7 +127,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
aptr += len;
if (aptr + RRFIXEDSZ > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -138,7 +138,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
aptr += RRFIXEDSZ;
if (aptr + rr_len > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -151,7 +151,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
{
if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
{ /* LCOV_EXCL_START: already checked above */
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
} /* LCOV_EXCL_STOP */
@ -162,7 +162,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
struct ares_addr6ttl * const at = &addrttls[naddrs];
if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
{ /* LCOV_EXCL_START: already checked above */
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
} /* LCOV_EXCL_STOP */
@ -179,7 +179,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
if (aliases)
aliases[naliases] = rr_name;
else
free(rr_name);
ares_free(rr_name);
naliases++;
/* Decode the RR data and replace the hostname with it. */
@ -187,7 +187,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
&len);
if (status != ARES_SUCCESS)
break;
free(hostname);
ares_free(hostname);
hostname = rr_data;
/* Take the min of the TTLs we see in the CNAME chain. */
@ -195,7 +195,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
cname_ttl = rr_ttl;
}
else
free(rr_name);
ares_free(rr_name);
aptr += rr_len;
if (aptr > abuf + alen)
@ -228,10 +228,10 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
if (host)
{
/* Allocate memory to build the host entry. */
hostent = malloc(sizeof(struct hostent));
hostent = ares_malloc(sizeof(struct hostent));
if (hostent)
{
hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char *));
hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
if (hostent->h_addr_list)
{
/* Fill in the hostent and return successfully. */
@ -243,11 +243,11 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
hostent->h_addr_list[i] = (char *) &addrs[i];
hostent->h_addr_list[naddrs] = NULL;
if (!naddrs && addrs)
free(addrs);
ares_free(addrs);
*host = hostent;
return ARES_SUCCESS;
}
free(hostent);
ares_free(hostent);
}
status = ARES_ENOMEM;
}
@ -255,10 +255,10 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
if (aliases)
{
for (i = 0; i < naliases; i++)
free(aliases[i]);
free(aliases);
ares_free(aliases[i]);
ares_free(aliases);
}
free(addrs);
free(hostname);
ares_free(addrs);
ares_free(hostname);
return status;
}

View File

@ -76,7 +76,7 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen,
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free (hostname);
ares_free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
@ -143,7 +143,7 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen,
}
/* Don't lose memory in the next iteration */
free (rr_name);
ares_free (rr_name);
rr_name = NULL;
/* Move on to the next record */
@ -151,9 +151,9 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen,
}
if (hostname)
free (hostname);
ares_free (hostname);
if (rr_name)
free (rr_name);
ares_free (rr_name);
/* clean up on error */
if (status != ARES_SUCCESS)

View File

@ -81,7 +81,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen,
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free (hostname);
ares_free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
@ -160,7 +160,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen,
}
/* Don't lose memory in the next iteration */
free (rr_name);
ares_free (rr_name);
rr_name = NULL;
/* Move on to the next record */
@ -168,9 +168,9 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen,
}
if (hostname)
free (hostname);
ares_free (hostname);
if (rr_name)
free (rr_name);
ares_free (rr_name);
/* clean up on error */
if (status != ARES_SUCCESS)

View File

@ -73,16 +73,16 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
return status;
if ( aptr + len + QFIXEDSZ > abuf + alen )
{
free( hostname );
ares_free( hostname );
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
/* Allocate nameservers array; ancount gives an upper bound */
nameservers = malloc( ( ancount + 1 ) * sizeof( char * ) );
nameservers = ares_malloc( ( ancount + 1 ) * sizeof( char * ) );
if ( !nameservers )
{
free( hostname );
ares_free( hostname );
return ARES_ENOMEM;
}
nameservers_num = 0;
@ -98,7 +98,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
if ( aptr + RRFIXEDSZ > abuf + alen )
{
status = ARES_EBADRESP;
free(rr_name);
ares_free(rr_name);
break;
}
rr_type = DNS_RR_TYPE( aptr );
@ -107,7 +107,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
aptr += RRFIXEDSZ;
if (aptr + rr_len > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -119,26 +119,26 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
&len);
if ( status != ARES_SUCCESS )
{
free(rr_name);
ares_free(rr_name);
break;
}
nameservers[nameservers_num] = malloc(strlen(rr_data)+1);
nameservers[nameservers_num] = ares_malloc(strlen(rr_data)+1);
if (nameservers[nameservers_num]==NULL)
{
free(rr_name);
free(rr_data);
ares_free(rr_name);
ares_free(rr_data);
status=ARES_ENOMEM;
break;
}
strcpy(nameservers[nameservers_num],rr_data);
free(rr_data);
ares_free(rr_data);
nameservers_num++;
}
free( rr_name );
ares_free( rr_name );
aptr += rr_len;
if ( aptr > abuf + alen )
@ -156,10 +156,10 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
{
/* We got our answer. Allocate memory to build the host entry. */
nameservers[nameservers_num] = NULL;
hostent = malloc( sizeof( struct hostent ) );
hostent = ares_malloc( sizeof( struct hostent ) );
if ( hostent )
{
hostent->h_addr_list = malloc( 1 * sizeof( char * ) );
hostent->h_addr_list = ares_malloc( 1 * sizeof( char * ) );
if ( hostent->h_addr_list )
{
/* Fill in the hostent and return successfully. */
@ -171,13 +171,13 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
*host = hostent;
return ARES_SUCCESS;
}
free( hostent );
ares_free( hostent );
}
status = ARES_ENOMEM;
}
for ( i = 0; i < nameservers_num; i++ )
free( nameservers[i] );
free( nameservers );
free( hostname );
ares_free( nameservers[i] );
ares_free( nameservers );
ares_free( hostname );
return status;
}

View File

@ -73,17 +73,17 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
return status;
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free(ptrname);
ares_free(ptrname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
/* Examine each answer resource record (RR) in turn. */
hostname = NULL;
aliases = malloc(alias_alloc * sizeof(char *));
aliases = ares_malloc(alias_alloc * sizeof(char *));
if (!aliases)
{
free(ptrname);
ares_free(ptrname);
return ARES_ENOMEM;
}
for (i = 0; i < (int)ancount; i++)
@ -95,7 +95,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
aptr += len;
if (aptr + RRFIXEDSZ > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -105,7 +105,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
aptr += RRFIXEDSZ;
if (aptr + rr_len > abuf + alen)
{
free(rr_name);
ares_free(rr_name);
status = ARES_EBADRESP;
break;
}
@ -118,16 +118,16 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
&len);
if (status != ARES_SUCCESS)
{
free(rr_name);
ares_free(rr_name);
break;
}
if (hostname)
free(hostname);
ares_free(hostname);
hostname = rr_data;
aliases[aliascnt] = malloc((strlen(rr_data)+1) * sizeof(char));
aliases[aliascnt] = ares_malloc((strlen(rr_data)+1) * sizeof(char));
if (!aliases[aliascnt])
{
free(rr_name);
ares_free(rr_name);
status = ARES_ENOMEM;
break;
}
@ -136,9 +136,9 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
if (aliascnt >= alias_alloc) {
char **ptr;
alias_alloc *= 2;
ptr = realloc(aliases, alias_alloc * sizeof(char *));
ptr = ares_realloc(aliases, alias_alloc * sizeof(char *));
if(!ptr) {
free(rr_name);
ares_free(rr_name);
status = ARES_ENOMEM;
break;
}
@ -153,14 +153,14 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
&len);
if (status != ARES_SUCCESS)
{
free(rr_name);
ares_free(rr_name);
break;
}
free(ptrname);
ares_free(ptrname);
ptrname = rr_data;
}
free(rr_name);
ares_free(rr_name);
aptr += rr_len;
if (aptr > abuf + alen)
{ /* LCOV_EXCL_START: already checked above */
@ -174,16 +174,16 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
if (status == ARES_SUCCESS)
{
/* We got our answer. Allocate memory to build the host entry. */
hostent = malloc(sizeof(struct hostent));
hostent = ares_malloc(sizeof(struct hostent));
if (hostent)
{
hostent->h_addr_list = malloc(2 * sizeof(char *));
hostent->h_addr_list = ares_malloc(2 * sizeof(char *));
if (hostent->h_addr_list)
{
hostent->h_addr_list[0] = malloc(addrlen);
hostent->h_addr_list[0] = ares_malloc(addrlen);
if (hostent->h_addr_list[0])
{
hostent->h_aliases = malloc((aliascnt+1) * sizeof (char *));
hostent->h_aliases = ares_malloc((aliascnt+1) * sizeof (char *));
if (hostent->h_aliases)
{
/* Fill in the hostent and return successfully. */
@ -196,24 +196,24 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
memcpy(hostent->h_addr_list[0], addr, addrlen);
hostent->h_addr_list[1] = NULL;
*host = hostent;
free(aliases);
free(ptrname);
ares_free(aliases);
ares_free(ptrname);
return ARES_SUCCESS;
}
free(hostent->h_addr_list[0]);
ares_free(hostent->h_addr_list[0]);
}
free(hostent->h_addr_list);
ares_free(hostent->h_addr_list);
}
free(hostent);
ares_free(hostent);
}
status = ARES_ENOMEM;
}
for (i=0 ; i<aliascnt ; i++)
if (aliases[i])
free(aliases[i]);
free(aliases);
ares_free(aliases[i]);
ares_free(aliases);
if (hostname)
free(hostname);
free(ptrname);
ares_free(hostname);
ares_free(ptrname);
return status;
}

View File

@ -112,8 +112,8 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen,
soa->expire = DNS__32BIT(aptr + 3 * 4);
soa->minttl = DNS__32BIT(aptr + 4 * 4);
free(qname);
free(rr_name);
ares_free(qname);
ares_free(rr_name);
*soa_out = soa;
@ -125,9 +125,9 @@ failed:
failed_stat:
ares_free_data(soa);
if (qname)
free(qname);
ares_free(qname);
if (rr_name)
free(rr_name);
ares_free(rr_name);
return status;
}

View File

@ -81,7 +81,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen,
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free (hostname);
ares_free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
@ -152,7 +152,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen,
}
/* Don't lose memory in the next iteration */
free (rr_name);
ares_free (rr_name);
rr_name = NULL;
/* Move on to the next record */
@ -160,9 +160,9 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen,
}
if (hostname)
free (hostname);
ares_free (hostname);
if (rr_name)
free (rr_name);
ares_free (rr_name);
/* clean up on error */
if (status != ARES_SUCCESS)

View File

@ -82,7 +82,7 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free (hostname);
ares_free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
@ -153,7 +153,7 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
txt_last = txt_curr;
txt_curr->length = substr_len;
txt_curr->txt = malloc (substr_len + 1/* Including null byte */);
txt_curr->txt = ares_malloc (substr_len + 1/* Including null byte */);
if (txt_curr->txt == NULL)
{
status = ARES_ENOMEM;
@ -175,7 +175,7 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
}
/* Don't lose memory in the next iteration */
free (rr_name);
ares_free (rr_name);
rr_name = NULL;
/* Move on to the next record */
@ -183,9 +183,9 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
}
if (hostname)
free (hostname);
ares_free (hostname);
if (rr_name)
free (rr_name);
ares_free (rr_name);
/* clean up on error */
if (status != ARES_SUCCESS)

View File

@ -93,10 +93,7 @@
# define getenv(ptr) ares_getenv(ptr)
#endif
#ifndef HAVE_STRDUP
# include "ares_strdup.h"
# define strdup(ptr) ares_strdup(ptr)
#endif
#include "ares_strdup.h"
#ifndef HAVE_STRCASECMP
# include "ares_strcasecmp.h"
@ -314,6 +311,11 @@ struct ares_channeldata {
void *sock_create_cb_data;
};
/* Memory management functions */
extern void *(*ares_malloc)(size_t size);
extern void *(*ares_realloc)(void *ptr, size_t size);
extern void (*ares_free)(void *ptr);
/* return true if now is exactly check time or later */
int ares__timedout(struct timeval *now,
struct timeval *check);

View File

@ -227,7 +227,7 @@ static void write_tcp_data(ares_channel channel,
n++;
/* Allocate iovecs so we can send all our data at once. */
vec = malloc(n * sizeof(struct iovec));
vec = ares_malloc(n * sizeof(struct iovec));
if (vec)
{
/* Fill in the iovecs and send. */
@ -239,7 +239,7 @@ static void write_tcp_data(ares_channel channel,
n++;
}
wcount = (ssize_t)writev(server->tcp_socket, vec, (int)n);
free(vec);
ares_free(vec);
if (wcount < 0)
{
if (!try_again(SOCKERRNO))
@ -281,8 +281,8 @@ static void advance_tcp_send_queue(ares_channel channel, int whichserver,
num_bytes -= sendreq->len;
server->qhead = sendreq->next;
if (sendreq->data_storage)
free(sendreq->data_storage);
free(sendreq);
ares_free(sendreq->data_storage);
ares_free(sendreq);
if (server->qhead == NULL) {
SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0);
server->qtail = NULL;
@ -361,7 +361,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds,
*/
server->tcp_length = server->tcp_lenbuf[0] << 8
| server->tcp_lenbuf[1];
server->tcp_buffer = malloc(server->tcp_length);
server->tcp_buffer = ares_malloc(server->tcp_length);
if (!server->tcp_buffer) {
handle_error(channel, i, now);
return; /* bail out on malloc failure. TODO: make this
@ -392,7 +392,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds,
process_answer(channel, server->tcp_buffer, server->tcp_length,
i, 1, now);
if (server->tcp_buffer)
free(server->tcp_buffer);
ares_free(server->tcp_buffer);
server->tcp_buffer = NULL;
server->tcp_lenbuf_pos = 0;
server->tcp_buffer_pos = 0;
@ -573,7 +573,7 @@ static void process_answer(ares_channel channel, unsigned char *abuf,
query->tcpbuf[0] = (unsigned char)((qlen >> 8) & 0xff);
query->tcpbuf[1] = (unsigned char)(qlen & 0xff);
DNS_HEADER_SET_ARCOUNT(query->tcpbuf + 2, 0);
query->tcpbuf = realloc(query->tcpbuf, query->tcplen);
query->tcpbuf = ares_realloc(query->tcpbuf, query->tcplen);
query->qbuf = query->tcpbuf + 2;
ares__send_query(channel, query, now);
return;
@ -773,12 +773,13 @@ void ares__send_query(ares_channel channel, struct query *query,
return;
}
}
sendreq = calloc(1, sizeof(struct send_request));
sendreq = ares_malloc(sizeof(struct send_request));
if (!sendreq)
{
end_query(channel, query, ARES_ENOMEM, NULL, 0);
return;
}
memset(sendreq, 0, sizeof(struct send_request));
/* To make the common case fast, we avoid copies by using the query's
* tcpbuf for as long as the query is alive. In the rare case where the
* query ends while it's queued for transmission, then we give the
@ -1160,7 +1161,7 @@ static int same_questions(const unsigned char *qbuf, int qlen,
q.p += q.namelen;
if (q.p + QFIXEDSZ > qbuf + qlen)
{
free(q.name);
ares_free(q.name);
return 0;
}
q.type = DNS_QUESTION_TYPE(q.p);
@ -1175,14 +1176,14 @@ static int same_questions(const unsigned char *qbuf, int qlen,
if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen)
!= ARES_SUCCESS)
{
free(q.name);
ares_free(q.name);
return 0;
}
a.p += a.namelen;
if (a.p + QFIXEDSZ > abuf + alen)
{
free(q.name);
free(a.name);
ares_free(q.name);
ares_free(a.name);
return 0;
}
a.type = DNS_QUESTION_TYPE(a.p);
@ -1193,13 +1194,13 @@ static int same_questions(const unsigned char *qbuf, int qlen,
if (strcasecmp(q.name, a.name) == 0 && q.type == a.type
&& q.dnsclass == a.dnsclass)
{
free(a.name);
ares_free(a.name);
break;
}
free(a.name);
ares_free(a.name);
}
free(q.name);
ares_free(q.name);
if (j == a.qdcount)
return 0;
}
@ -1265,7 +1266,7 @@ static void end_query (ares_channel channel, struct query *query, int status,
* to the query's tcpbuf and handle these cases, we just give
* such sendreqs their own copy of the query packet.
*/
sendreq->data_storage = malloc(sendreq->len);
sendreq->data_storage = ares_malloc(sendreq->len);
if (sendreq->data_storage != NULL)
{
memcpy(sendreq->data_storage, sendreq->data, sendreq->len);
@ -1315,7 +1316,7 @@ void ares__free_query(struct query *query)
query->callback = NULL;
query->arg = NULL;
/* Deallocate the memory associated with the query */
free(query->tcpbuf);
free(query->server_info);
free(query);
ares_free(query->tcpbuf);
ares_free(query->server_info);
ares_free(query);
}

View File

@ -121,7 +121,7 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
&qlen, (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0);
if (status != ARES_SUCCESS)
{
if (qbuf != NULL) free(qbuf);
if (qbuf != NULL) ares_free(qbuf);
callback(arg, status, 0, NULL, 0);
return;
}
@ -129,7 +129,7 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
channel->next_id = generate_unique_id(channel);
/* Allocate and fill in the query structure. */
qquery = malloc(sizeof(struct qquery));
qquery = ares_malloc(sizeof(struct qquery));
if (!qquery)
{
ares_free_string(qbuf);
@ -182,5 +182,5 @@ static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf,
}
qquery->callback(qquery->arg, status, timeouts, abuf, alen);
}
free(qquery);
ares_free(qquery);
}

View File

@ -66,24 +66,24 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
if (s)
{
ares_query(channel, s, dnsclass, type, callback, arg);
free(s);
ares_free(s);
return;
}
/* Allocate a search_query structure to hold the state necessary for
* doing multiple lookups.
*/
squery = malloc(sizeof(struct search_query));
squery = ares_malloc(sizeof(struct search_query));
if (!squery)
{
callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
squery->channel = channel;
squery->name = strdup(name);
squery->name = ares_strdup(name);
if (!squery->name)
{
free(squery);
ares_free(squery);
callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
@ -123,13 +123,13 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
if (status == ARES_SUCCESS)
{
ares_query(channel, s, dnsclass, type, search_callback, squery);
free(s);
ares_free(s);
}
else
{
/* failed, free the malloc()ed memory */
free(squery->name);
free(squery);
ares_free(squery->name);
ares_free(squery);
callback(arg, status, 0, NULL, 0);
}
}
@ -177,7 +177,7 @@ static void search_callback(void *arg, int status, int timeouts,
squery->next_domain++;
ares_query(channel, s, squery->dnsclass, squery->type,
search_callback, squery);
free(s);
ares_free(s);
}
}
else if (squery->status_as_is == -1)
@ -201,8 +201,8 @@ static void end_squery(struct search_query *squery, int status,
unsigned char *abuf, int alen)
{
squery->callback(squery->arg, status, squery->timeouts, abuf, alen);
free(squery->name);
free(squery);
ares_free(squery->name);
ares_free(squery);
}
/* Concatenate two domains. */
@ -211,7 +211,7 @@ static int cat_domain(const char *name, const char *domain, char **s)
size_t nlen = strlen(name);
size_t dlen = strlen(domain);
*s = malloc(nlen + 1 + dlen + 1);
*s = ares_malloc(nlen + 1 + dlen + 1);
if (!*s)
return ARES_ENOMEM;
memcpy(*s, name, nlen);
@ -241,7 +241,7 @@ STATIC_TESTABLE int single_domain(ares_channel channel, const char *name, char *
*/
if ((len > 0) && (name[len - 1] == '.'))
{
*s = strdup(name);
*s = ares_strdup(name);
return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
}
@ -268,18 +268,18 @@ STATIC_TESTABLE int single_domain(ares_channel channel, const char *name, char *
q = p + 1;
while (*q && !ISSPACE(*q))
q++;
*s = malloc(q - p + 1);
*s = ares_malloc(q - p + 1);
if (*s)
{
memcpy(*s, p, q - p);
(*s)[q - p] = 0;
}
free(line);
ares_free(line);
fclose(fp);
return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
}
}
free(line);
ares_free(line);
fclose(fp);
if (status != ARES_SUCCESS && status != ARES_EOF)
return status;
@ -307,7 +307,7 @@ STATIC_TESTABLE int single_domain(ares_channel channel, const char *name, char *
if (channel->flags & ARES_FLAG_NOSEARCH || channel->ndomains == 0)
{
/* No domain search to do; just try the name as-is. */
*s = strdup(name);
*s = ares_strdup(name);
return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
}

View File

@ -47,25 +47,25 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
}
/* Allocate space for query and allocated fields. */
query = malloc(sizeof(struct query));
query = ares_malloc(sizeof(struct query));
if (!query)
{
callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
query->tcpbuf = malloc(qlen + 2);
query->tcpbuf = ares_malloc(qlen + 2);
if (!query->tcpbuf)
{
free(query);
ares_free(query);
callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
query->server_info = malloc(channel->nservers *
sizeof(query->server_info[0]));
query->server_info = ares_malloc(channel->nservers *
sizeof(query->server_info[0]));
if (!query->server_info)
{
free(query->tcpbuf);
free(query);
ares_free(query->tcpbuf);
ares_free(query);
callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}

View File

@ -17,26 +17,33 @@
#include "ares_setup.h"
#include "ares_strdup.h"
#include "ares.h"
#include "ares_private.h"
#ifndef HAVE_STRDUP
char *ares_strdup(const char *s1)
{
size_t sz;
char * s2;
#ifdef HAVE_STRDUP
if (ares_malloc == malloc)
return strdup(s1);
else
#endif
{
size_t sz;
char * s2;
if(s1) {
sz = strlen(s1);
if(sz < (size_t)-1) {
sz++;
if(sz < ((size_t)-1) / sizeof(char)) {
s2 = malloc(sz * sizeof(char));
if(s2) {
memcpy(s2, s1, sz * sizeof(char));
return s2;
if(s1) {
sz = strlen(s1);
if(sz < (size_t)-1) {
sz++;
if(sz < ((size_t)-1) / sizeof(char)) {
s2 = ares_malloc(sz * sizeof(char));
if(s2) {
memcpy(s2, s1, sz * sizeof(char));
return s2;
}
}
}
}
return (char *)NULL;
}
return (char *)NULL;
}
#endif

View File

@ -19,8 +19,6 @@
#include "ares_setup.h"
#ifndef HAVE_STRDUP
extern char *ares_strdup(const char *s1);
#endif
#endif /* HEADER_CARES_STRDUP_H */

View File

@ -54,7 +54,7 @@ ssize_t ares_writev(ares_socket_t s, const struct iovec *iov, int iovcnt)
return (0);
/* Allocate a temporary buffer to hold the data */
buffer = malloc(bytes);
buffer = ares_malloc(bytes);
if (!buffer)
{
SET_ERRNO(ENOMEM);
@ -71,7 +71,7 @@ ssize_t ares_writev(ares_socket_t s, const struct iovec *iov, int iovcnt)
/* Send buffer contents */
result = swrite(s, buffer, bytes);
free(buffer);
ares_free(buffer);
return (result);
}