8000 mem leak due to `ares__hosts_entry_to_hostent()` allocation strategy by bradh352 · Pull Request #824 · c-ares/c-ares · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

me 8000 m leak due to ares__hosts_entry_to_hostent() allocation strategy #824

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

Merged
merged 2 commits into from
Jul 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 38 additions & 124 deletions src/lib/ares__hosts_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,126 +767,6 @@ ares_status_t ares__hosts_search_host(ares_channel_t *channel,
return ARES_SUCCESS;
}

ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry,
int family, struct hostent **hostent)
{
ares_status_t status;
size_t naliases;
ares__llist_node_t *node;
size_t idx;

*hostent = ares_malloc_zero(sizeof(**hostent));
if (*hostent == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}

(*hostent)->h_addrtype = (HOSTENT_ADDRTYPE_TYPE)family;

/* Copy IP addresses that match the address family */
idx = 0;
for (node = ares__llist_node_first(entry->ips); node != NULL;
node = ares__llist_node_next(node)) {
struct ares_addr addr;
const void *ptr = NULL;
size_t ptr_len = 0;
const char *ipaddr = ares__llist_node_val(node);
char **temp = NULL;

memset(&addr, 0, sizeof(addr));

addr.family = family;
ptr = ares_dns_pton(ipaddr, &addr, &ptr_len);
if (ptr == NULL) {
continue;
}

/* If family == AF_UNSPEC, then we want to inherit this for future
* conversions as we can only support a single address class */
if (family == AF_UNSPEC) {
family = addr.family;
(*hostent)->h_addrtype = (HOSTENT_ADDRTYPE_TYPE)addr.family;
}

temp = ares_realloc_zero((*hostent)->h_addr_list,
(idx + 1) * sizeof(*(*hostent)->h_addr_list),
(idx + 2) * sizeof(*(*hostent)->h_addr_list));
if (temp == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}

(*hostent)->h_addr_list = temp;

(*hostent)->h_addr_list[idx] = ares_malloc(ptr_len);
if ((*hostent)->h_addr_list[idx] == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}

memcpy((*hostent)->h_addr_list[idx], ptr, ptr_len);
idx++;
(*hostent)->h_length = (HOSTENT_LENGTH_TYPE)ptr_len;
}

/* entry didn't match address class */
if (idx == 0) {
status = ARES_ENOTFOUND;
goto fail;
}

/* Copy main hostname */
(*hostent)->h_name = ares_strdup(ares__llist_first_val(entry->hosts));
if ((*hostent)->h_name == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}

/* Copy aliases */
naliases = ares__llist_len(entry->hosts) - 1;

/* Cap at 100, some people use https://github.com/StevenBlack/hosts and we
* don't need 200k+ aliases */
if (naliases > 100) {
naliases = 100; /* LCOV_EXCL_LINE: DefensiveCoding */
}

(*hostent)->h_aliases =
ares_malloc_zero((naliases + 1) * sizeof(*(*hostent)->h_aliases));
if ((*hostent)->h_aliases == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}

/* Copy all entries to the alias except the first */
idx = 0;
node = ares__llist_node_first(entry->hosts);
node = ares__llist_node_next(node);
while (node != NULL) {
(*hostent)->h_aliases[idx] = ares_strdup(ares__llist_node_val(node));
if ((*hostent)->h_aliases[idx] == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
idx++;

/* Break out if artificially capped */
if (idx == naliases) {
break;
}
node = ares__llist_node_next(node);
}

return ARES_SUCCESS;

/* LCOV_EXCL_START: defensive coding */
fail:
ares_free_hostent(*hostent);
*hostent = NULL;
return status;
/* LCOV_EXCL_STOP */
}

static ares_status_t
ares__hosts_ai_append_cnames(const ares_hosts_entry_t *entry,
struct ares_addrinfo_cname **cnames_out)
Expand Down Expand Up @@ -980,10 +860,12 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
return ARES_EBADFAMILY; /* LCOV_EXCL_LINE: DefensiveCoding */
}

ai->name = ares_strdup(name);
if (ai->name == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto done; /* LCOV_EXCL_LINE: OutOfMemory */
if (name != NULL) {
ai->name = ares_strdup(name);
if (ai->name == NULL) {
status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}

for (node = ares__llist_node_first(entry->ips); node != NULL;
Expand Down Expand Up @@ -1031,3 +913,35 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,

return status;
}

ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry,
int family, struct hostent **hostent)
{
ares_status_t status;
struct ares_addrinfo *ai = ares_malloc_zero(sizeof(*ai));

*hostent = NULL;

if (ai == NULL) {
return ARES_ENOMEM;
}

status = ares__hosts_entry_to_addrinfo(entry, NULL, family, 0, ARES_TRUE, ai);
if (status != ARES_SUCCESS) {
goto done;
}

status = ares__addrinfo2hostent(ai, family, hostent);
if (status != ARES_SUCCESS) {
goto done;
}

done:
ares_freeaddrinfo(ai);
if (status != ARES_SUCCESS) {
ares_free_hostent(*hostent);
*hostent = NULL;
}

return status;
}
Loading
0