]> granicus.if.org Git - curl/commitdiff
hostip: make create_hostcache_id avoid alloc + free
authorDaniel Stenberg <daniel@haxx.se>
Sat, 9 Feb 2019 23:10:18 +0000 (00:10 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 11 Feb 2019 07:57:54 +0000 (08:57 +0100)
Closes #3544

lib/hostip.c

index 8a62a34ec402e5f0e28a061b5d3dd2c954869303..0c6615986b30ae0edc3da3cc29684f0eb79d8cda 100644 (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);