hostip: make create_hostcache_id avoid alloc + free

Closes #3544
This commit is contained in:
Daniel Stenberg 2019-02-10 00:10:18 +01:00
parent e81cd9028f
commit 81a9fe4e92
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -73,6 +73,8 @@
#define USE_ALARM_TIMEOUT #define USE_ALARM_TIMEOUT
#endif #endif
#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
/* /*
* hostip.c explained * hostip.c explained
* ================== * ==================
@ -198,23 +200,19 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
} }
/* /*
* Return a hostcache id string for the provided host + port, to be used by * Create a hostcache id string for the provided host + port, to be used by
* the DNS caching. * the DNS caching. Without alloc.
*/ */
static char * static void
create_hostcache_id(const char *name, int port) create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
{ {
/* create and return the new allocated entry */ size_t len = strlen(name);
char *id = aprintf("%s:%d", name, port); if(len > (buflen - 7))
char *ptr = id; len = buflen - 7;
if(ptr) { /* store and lower case the name */
/* lower case the name part */ while(len--)
while(*ptr && (*ptr != ':')) { *ptr++ = (char)TOLOWER(*name++);
*ptr = (char)TOLOWER(*ptr); msnprintf(ptr, 7, ":%u", port);
ptr++;
}
}
return id;
} }
struct hostcache_prune_data { struct hostcache_prune_data {
@ -296,17 +294,13 @@ fetch_addr(struct connectdata *conn,
const char *hostname, const char *hostname,
int port) int port)
{ {
char *entry_id = NULL;
struct Curl_dns_entry *dns = NULL; struct Curl_dns_entry *dns = NULL;
size_t entry_len; size_t entry_len;
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
char entry_id[MAX_HOSTCACHE_LEN];
/* Create an entry id, based upon the hostname and port */ /* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port); create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
/* If we can't create the entry id, fail */
if(!entry_id)
return dns;
entry_len = strlen(entry_id); entry_len = strlen(entry_id);
/* See if its already in our dns cache */ /* See if its already in our dns cache */
@ -314,18 +308,7 @@ fetch_addr(struct connectdata *conn,
/* No entry found in cache, check if we might have a wildcard entry */ /* No entry found in cache, check if we might have a wildcard entry */
if(!dns && data->change.wildcard_resolve) { if(!dns && data->change.wildcard_resolve) {
/* create_hostcache_id("*", port, entry_id, sizeof(entry_id));
* Free the previous entry_id before requesting a new one to avoid leaking
* memory
*/
free(entry_id);
entry_id = create_hostcache_id("*", port);
/* If we can't create the entry id, fail */
if(!entry_id)
return dns;
entry_len = strlen(entry_id); entry_len = strlen(entry_id);
/* See if it's already in our dns cache */ /* See if it's already in our dns cache */
@ -346,9 +329,6 @@ fetch_addr(struct connectdata *conn,
} }
} }
/* free the allocated entry_id again */
free(entry_id);
return dns; return dns;
} }
@ -471,7 +451,7 @@ Curl_cache_addr(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port) int port)
{ {
char *entry_id; char entry_id[MAX_HOSTCACHE_LEN];
size_t entry_len; size_t entry_len;
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2; struct Curl_dns_entry *dns2;
@ -483,20 +463,16 @@ Curl_cache_addr(struct Curl_easy *data,
return NULL; return NULL;
} }
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!entry_id)
return NULL;
entry_len = strlen(entry_id);
/* Create a new cache entry */ /* Create a new cache entry */
dns = calloc(1, sizeof(struct Curl_dns_entry)); dns = calloc(1, sizeof(struct Curl_dns_entry));
if(!dns) { if(!dns) {
free(entry_id);
return NULL; return NULL;
} }
/* Create an entry id, based upon the hostname and port */
create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
entry_len = strlen(entry_id);
dns->inuse = 1; /* the cache has the first reference */ dns->inuse = 1; /* the cache has the first reference */
dns->addr = addr; /* this is the address(es) */ dns->addr = addr; /* this is the address(es) */
time(&dns->timestamp); time(&dns->timestamp);
@ -508,16 +484,11 @@ Curl_cache_addr(struct Curl_easy *data,
(void *)dns); (void *)dns);
if(!dns2) { if(!dns2) {
free(dns); free(dns);
free(entry_id);
return NULL; return NULL;
} }
dns = dns2; dns = dns2;
dns->inuse++; /* mark entry as in-use */ dns->inuse++; /* mark entry as in-use */
/* free the allocated entry_id */
free(entry_id);
return dns; return dns;
} }
@ -900,10 +871,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
data->change.wildcard_resolve = false; data->change.wildcard_resolve = false;
for(hostp = data->change.resolve; hostp; hostp = hostp->next) { for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
char entry_id[MAX_HOSTCACHE_LEN];
if(!hostp->data) if(!hostp->data)
continue; continue;
if(hostp->data[0] == '-') { if(hostp->data[0] == '-') {
char *entry_id;
size_t entry_len; size_t entry_len;
if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
@ -913,12 +884,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
} }
/* Create an entry id, based upon the hostname and port */ /* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port); create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
/* If we can't create the entry id, fail */
if(!entry_id) {
return CURLE_OUT_OF_MEMORY;
}
entry_len = strlen(entry_id); entry_len = strlen(entry_id);
if(data->share) if(data->share)
@ -929,14 +895,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(data->share) if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS); Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
/* free the allocated entry_id again */
free(entry_id);
} }
else { else {
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns;
Curl_addrinfo *head = NULL, *tail = NULL; Curl_addrinfo *head = NULL, *tail = NULL;
char *entry_id;
size_t entry_len; size_t entry_len;
char address[64]; char address[64];
#if !defined(CURL_DISABLE_VERBOSE_STRINGS) #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@ -1032,12 +994,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
} }
/* Create an entry id, based upon the hostname and port */ /* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port); create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
/* If we can't create the entry id, fail */
if(!entry_id) {
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
entry_len = strlen(entry_id); entry_len = strlen(entry_id);
if(data->share) if(data->share)
@ -1058,8 +1015,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
} }
/* free the allocated entry_id again */
free(entry_id);
/* put this new host in the cache */ /* put this new host in the cache */
dns = Curl_cache_addr(data, head, hostname, port); dns = Curl_cache_addr(data, head, hostname, port);