summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2020-06-06 23:10:18 +0200
committerDaniel Stenberg <daniel@haxx.se>2020-06-08 11:12:28 +0200
commit12c178b734a0f00ef5ea708e7f9dad81ee2cb4c1 (patch)
treee90e8b7bdfdccacab6ef41b58342a76359778886
parent99e09d9046bfc7b13c09022248d17e5daf08e0e0 (diff)
downloadcurl-bagder/curl_he2ai-lessmalloc.tar.gz
Curl_addrinfo: use one malloc instead of threebagder/curl_he2ai-lessmalloc
To reduce the amount of allocations needed for creating a Curl_addrinfo struct, make one larger malloc instead of three separate smaller ones. Closes #5533
-rw-r--r--lib/curl_addrinfo.c59
-rw-r--r--lib/doh.c19
-rw-r--r--tests/unit/unit1305.c21
3 files changed, 30 insertions, 69 deletions
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index dd07b8669..947d0d375 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -83,11 +83,8 @@ Curl_freeaddrinfo(struct Curl_addrinfo *cahead)
struct Curl_addrinfo *vqualifier canext;
struct Curl_addrinfo *ca;
- for(ca = cahead; ca != NULL; ca = canext) {
- free(ca->ai_addr);
- free(ca->ai_canonname);
+ for(ca = cahead; ca; ca = canext) {
canext = ca->ai_next;
-
free(ca);
}
}
@@ -131,7 +128,7 @@ Curl_getaddrinfo_ex(const char *nodename,
/* traverse the addrinfo list */
for(ai = aihead; ai != NULL; ai = ai->ai_next) {
-
+ size_t namelen = ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0;
/* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
@@ -151,7 +148,7 @@ Curl_getaddrinfo_ex(const char *nodename,
if((size_t)ai->ai_addrlen < ss_size)
continue;
- ca = malloc(sizeof(struct Curl_addrinfo));
+ ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ca) {
error = EAI_MEMORY;
break;
@@ -169,22 +166,12 @@ Curl_getaddrinfo_ex(const char *nodename,
ca->ai_canonname = NULL;
ca->ai_next = NULL;
- ca->ai_addr = malloc(ss_size);
- if(!ca->ai_addr) {
- error = EAI_MEMORY;
- free(ca);
- break;
- }
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
- if(ai->ai_canonname != NULL) {
- ca->ai_canonname = strdup(ai->ai_canonname);
- if(!ca->ai_canonname) {
- error = EAI_MEMORY;
- free(ca->ai_addr);
- free(ca);
- break;
- }
+ if(namelen) {
+ ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
+ memcpy(ca->ai_canonname, ai->ai_canonname, namelen);
}
/* if the return list is empty, this becomes the first element */
@@ -289,8 +276,8 @@ Curl_he2ai(const struct hostent *he, int port)
DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
-
size_t ss_size;
+ size_t namelen = strlen(he->h_name) + 1; /* include zero termination */
#ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
@@ -298,24 +285,17 @@ Curl_he2ai(const struct hostent *he, int port)
#endif
ss_size = sizeof(struct sockaddr_in);
- ai = calloc(1, sizeof(struct Curl_addrinfo));
+ /* allocate memory to told the struct, the address and the name */
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
- ai->ai_canonname = strdup(he->h_name);
- if(!ai->ai_canonname) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai);
- break;
- }
- ai->ai_addr = calloc(1, ss_size);
- if(!ai->ai_addr) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai->ai_canonname);
- free(ai);
- break;
- }
+ /* put the address after the struct */
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ /* then put the name after the address */
+ ai->ai_canonname = (char *)ai->ai_addr + ss_size;
+ memcpy(ai->ai_canonname, he->h_name, namelen);
if(!firstai)
/* store the pointer we want to return from this function */
@@ -496,14 +476,10 @@ struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
*longpath = FALSE;
- ai = calloc(1, sizeof(struct Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un));
if(!ai)
return NULL;
- ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
- if(!ai->ai_addr) {
- free(ai);
- return NULL;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
sa_un = (void *) ai->ai_addr;
sa_un->sun_family = AF_UNIX;
@@ -511,7 +487,6 @@ struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
/* sun_path must be able to store the NUL-terminated path */
path_len = strlen(path) + 1;
if(path_len > sizeof(sa_un->sun_path)) {
- free(ai->ai_addr);
free(ai);
*longpath = TRUE;
return NULL;
diff --git a/lib/doh.c b/lib/doh.c
index 8f9e42c33..ebb2c243b 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -803,6 +803,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
#endif
CURLcode result = CURLE_OK;
int i;
+ size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
if(!de)
/* no input == no output! */
@@ -825,24 +826,14 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
addrtype = AF_INET;
}
- ai = calloc(1, sizeof(struct Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
- ai->ai_canonname = strdup(hostname);
- if(!ai->ai_canonname) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai);
- break;
- }
- ai->ai_addr = calloc(1, ss_size);
- if(!ai->ai_addr) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai->ai_canonname);
- free(ai);
- break;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ ai->ai_canonname = (void *)((char *)ai->ai_addr + ss_size);
+ memcpy(ai->ai_canonname, hostname, hostlen);
if(!firstai)
/* store the pointer we want to return from this function */
diff --git a/tests/unit/unit1305.c b/tests/unit/unit1305.c
index f3cd9d8f0..50f6da8bb 100644
--- a/tests/unit/unit1305.c
+++ b/tests/unit/unit1305.c
@@ -76,23 +76,18 @@ static void unit_stop(void)
static struct Curl_addrinfo *fake_ai(void)
{
static struct Curl_addrinfo *ai;
+ static const char dummy[]="dummy";
+ size_t namelen = sizeof(dummy); /* including the zero terminator */
- ai = calloc(1, sizeof(struct Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_in) +
+ namelen);
if(!ai)
return NULL;
- ai->ai_canonname = strdup("dummy");
- if(!ai->ai_canonname) {
- free(ai);
- return NULL;
- }
-
- ai->ai_addr = calloc(1, sizeof(struct sockaddr_in));
- if(!ai->ai_addr) {
- free(ai->ai_canonname);
- free(ai);
- return NULL;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ ai->ai_canonname = (void *)((char *)ai->ai_addr +
+ sizeof(struct sockaddr_in));
+ memcpy(ai->ai_canonname, dummy, namelen);
ai->ai_family = AF_INET;
ai->ai_addrlen = sizeof(struct sockaddr_in);