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
#endif
#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
/*
* 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
* the DNS caching.
* Create a hostcache id string for the provided host + port, to be used by
* the DNS caching. Without alloc.
*/
static char *
create_hostcache_id(const char *name, int port)
static void
create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
{
/* create and return the new allocated entry */
char *id = aprintf("%s:%d", name, port);
char *ptr = id;
if(ptr) {
/* lower case the name part */
while(*ptr && (*ptr != ':')) {
*ptr = (char)TOLOWER(*ptr);
ptr++;
}
}
return id;
size_t len = strlen(name);
if(len > (buflen - 7))
len = buflen - 7;
/* store and lower case the name */
while(len--)
*ptr++ = (char)TOLOWER(*name++);
msnprintf(ptr, 7, ":%u", port);
}
struct hostcache_prune_data {
@ -296,17 +294,13 @@ fetch_addr(struct connectdata *conn,
const char *hostname,
int port)
{
char *entry_id = NULL;
struct Curl_dns_entry *dns = NULL;
size_t entry_len;
struct Curl_easy *data = conn->data;
char entry_id[MAX_HOSTCACHE_LEN];
/* 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 dns;
create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
entry_len = strlen(entry_id);
/* 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 */
if(!dns && data->change.wildcard_resolve) {
/*
* 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;
create_hostcache_id("*", port, entry_id, sizeof(entry_id));
entry_len = strlen(entry_id);
/* 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;
}
@ -471,7 +451,7 @@ Curl_cache_addr(struct Curl_easy *data,
const char *hostname,
int port)
{
char *entry_id;
char entry_id[MAX_HOSTCACHE_LEN];
size_t entry_len;
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
@ -483,20 +463,16 @@ Curl_cache_addr(struct Curl_easy *data,
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 */
dns = calloc(1, sizeof(struct Curl_dns_entry));
if(!dns) {
free(entry_id);
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->addr = addr; /* this is the address(es) */
time(&dns->timestamp);
@ -508,16 +484,11 @@ Curl_cache_addr(struct Curl_easy *data,
(void *)dns);
if(!dns2) {
free(dns);
free(entry_id);
return NULL;
}
dns = dns2;
dns->inuse++; /* mark entry as in-use */
/* free the allocated entry_id */
free(entry_id);
return dns;
}
@ -900,10 +871,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
data->change.wildcard_resolve = false;
for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
char entry_id[MAX_HOSTCACHE_LEN];
if(!hostp->data)
continue;
if(hostp->data[0] == '-') {
char *entry_id;
size_t entry_len;
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 */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!entry_id) {
return CURLE_OUT_OF_MEMORY;
}
create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
entry_len = strlen(entry_id);
if(data->share)
@ -929,14 +895,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
/* free the allocated entry_id again */
free(entry_id);
}
else {
struct Curl_dns_entry *dns;
Curl_addrinfo *head = NULL, *tail = NULL;
char *entry_id;
size_t entry_len;
char address[64];
#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 */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!entry_id) {
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
entry_len = strlen(entry_id);
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);
}
/* free the allocated entry_id again */
free(entry_id);
/* put this new host in the cache */
dns = Curl_cache_addr(data, head, hostname, port);