From: Yang Tse <yangsita@gmail.com>
Date: Mon, 6 Nov 2006 13:56:51 +0000 (+0000)
Subject: avoid a couple of potential zero size memory allocations
X-Git-Tag: curl-7_16_1~184
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3274908551a92d546341ce6af294fd0e0f9e25e2;p=curl

avoid a couple of potential zero size memory allocations
---

diff --git a/ares/CHANGES b/ares/CHANGES
index 770f037eb..378a81816 100644
--- a/ares/CHANGES
+++ b/ares/CHANGES
@@ -2,6 +2,8 @@
 
 * November 6
 
+- Yang Tse removed a couple of potential zero size memory allocations.
+
 - Andreas Rieke fixed the line endings in the areslib.dsp file that I (Daniel)
   broke in the 1.3.2 release. We should switch to a system where that file is
   auto-generated. We could rip some code for that from curl...
diff --git a/ares/ares_cancel.c b/ares/ares_cancel.c
index 8e3efa3b2..9641dab20 100644
--- a/ares/ares_cancel.c
+++ b/ares/ares_cancel.c
@@ -39,7 +39,10 @@ void ares_cancel(ares_channel channel)
   channel->queries = NULL;
   if (!(channel->flags & ARES_FLAG_STAYOPEN))
   {
-    for (i = 0; i < channel->nservers; i++)
-      ares__close_sockets(channel, &channel->servers[i]);
+    if (channel->servers)
+    {
+      for (i = 0; i < channel->nservers; i++)
+        ares__close_sockets(channel, &channel->servers[i]);
+    }
   }
 }
diff --git a/ares/ares_destroy.c b/ares/ares_destroy.c
index b7a21e9e3..fd243c30a 100644
--- a/ares/ares_destroy.c
+++ b/ares/ares_destroy.c
@@ -25,23 +25,37 @@ void ares_destroy(ares_channel channel)
   int i;
   struct query *query;
 
-  for (i = 0; i < channel->nservers; i++)
-    ares__close_sockets(channel, &channel->servers[i]);
-  free(channel->servers);
-  for (i = 0; i < channel->ndomains; i++)
-    free(channel->domains[i]);
-  free(channel->domains);
+  if (!channel)
+    return;
+
+  if (channel->servers) {
+    for (i = 0; i < channel->nservers; i++)
+      ares__close_sockets(channel, &channel->servers[i]);
+    free(channel->servers);
+  }
+
+  if (channel->domains) {
+    for (i = 0; i < channel->ndomains; i++)
+      free(channel->domains[i]);
+    free(channel->domains);
+  }
+
   if(channel->sortlist)
     free(channel->sortlist);
-  free(channel->lookups);
-  while (channel->queries)
-    {
-      query = channel->queries;
-      channel->queries = query->next;
-      query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
+
+  if (channel->lookups)
+    free(channel->lookups);
+
+  while (channel->queries) {
+    query = channel->queries;
+    channel->queries = query->next;
+    query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
+    if (query->tcpbuf)
       free(query->tcpbuf);
+    if (query->skip_server)
       free(query->skip_server);
-      free(query);
-    }
+    free(query);
+  }
+
   free(channel);
 }
diff --git a/ares/ares_init.c b/ares/ares_init.c
index a9fa8fbc1..7246bc484 100644
--- a/ares/ares_init.c
+++ b/ares/ares_init.c
@@ -125,7 +125,9 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
   channel->queries = NULL;
   channel->domains = NULL;
   channel->sortlist = NULL;
+  channel->servers = NULL;
   channel->sock_state_cb = NULL;
+  channel->sock_state_cb_data = NULL;
 
   /* Initialize configuration by each of the four sources, from highest
    * precedence to lowest.
@@ -140,7 +142,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
   if (status != ARES_SUCCESS)
     {
       /* Something failed; clean up memory we may have allocated. */
-      if (channel->nservers != -1)
+      if (channel->servers)
         free(channel->servers);
       if (channel->domains)
         {
@@ -214,12 +216,16 @@ static int init_by_options(ares_channel channel, struct ares_options *options,
   /* Copy the servers, if given. */
   if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
     {
-      channel->servers =
-        malloc(options->nservers * sizeof(struct server_state));
-      if (!channel->servers && options->nservers != 0)
-        return ARES_ENOMEM;
-      for (i = 0; i < options->nservers; i++)
-        channel->servers[i].addr = options->servers[i];
+      /* Avoid zero size allocations at any cost */
+      if (options->nservers > 0)
+        {
+          channel->servers =
+            malloc(options->nservers * sizeof(struct server_state));
+          if (!channel->servers)
+            return ARES_ENOMEM;
+          for (i = 0; i < options->nservers; i++)
+            channel->servers[i].addr = options->servers[i];
+        }
       channel->nservers = options->nservers;
     }
 
@@ -228,16 +234,20 @@ static int init_by_options(ares_channel channel, struct ares_options *options,
    */
   if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
     {
-      channel->domains = malloc(options->ndomains * sizeof(char *));
-      if (!channel->domains && options->ndomains != 0)
-        return ARES_ENOMEM;
-      for (i = 0; i < options->ndomains; i++)
-        {
-          channel->ndomains = i;
-          channel->domains[i] = strdup(options->domains[i]);
-          if (!channel->domains[i])
-            return ARES_ENOMEM;
-        }
+      /* Avoid zero size allocations at any cost */
+      if (options->ndomains > 0)
+      {
+        channel->domains = malloc(options->ndomains * sizeof(char *));
+        if (!channel->domains)
+          return ARES_ENOMEM;
+        for (i = 0; i < options->ndomains; i++)
+          {
+            channel->ndomains = i;
+            channel->domains[i] = strdup(options->domains[i]);
+            if (!channel->domains[i])
+              return ARES_ENOMEM;
+          }
+      }
       channel->ndomains = options->ndomains;
     }
 
@@ -711,7 +721,6 @@ static int init_by_defaults(ares_channel channel)
       if (gethostname(hostname, sizeof(hostname)) == -1
           || !strchr(hostname, '.'))
         {
-          channel->domains = malloc(0);
           channel->ndomains = 0;
         }
       else
@@ -940,6 +949,7 @@ static int set_search(ares_channel channel, const char *str)
     for(n=0; n < channel->ndomains; n++)
       free(channel->domains[n]);
     free(channel->domains);
+    channel->domains = NULL;
     channel->ndomains = -1;
   }
 
@@ -955,8 +965,14 @@ static int set_search(ares_channel channel, const char *str)
       n++;
     }
 
+  if (!n)
+    {
+      channel->ndomains = 0;
+      return ARES_SUCCESS;
+    }
+
   channel->domains = malloc(n * sizeof(char *));
-  if (!channel->domains && n)
+  if (!channel->domains)
     return ARES_ENOMEM;
 
   /* Now copy the domains. */