From 05b26e7566b9788fcdecda3c49e0b0ca1f7d25ec Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 22 Sep 2007 20:45:50 +0000
Subject: [PATCH] Brad House provided a fix for ares_save_options(): Apparently
 I overlooked something with the ares_save_options() where it would try to do
 a malloc(0) when no options of that type needed to be saved.  On most
 platforms, this was fine because malloc(0) doesn't actually return NULL, but
 on AIX it does, so ares_save_options would return ARES_ENOMEM.

---
 ares/CHANGES     | 10 ++++++++-
 ares/ares_init.c | 57 ++++++++++++++++++++++++++++--------------------
 2 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/ares/CHANGES b/ares/CHANGES
index 86d46ed44f..160489c64c 100644
--- a/ares/CHANGES
+++ b/ares/CHANGES
@@ -1,9 +1,17 @@
   Changelog for the c-ares project
 
+* September 22 2007 (Daniel Stenberg)
+
+- Brad House provided a fix for ares_save_options():
+
+  Apparently I overlooked something with the ares_save_options() where it
+  would try to do a malloc(0) when no options of that type needed to be saved.
+  On most platforms, this was fine because malloc(0) doesn't actually return
+  NULL, but on AIX it does, so ares_save_options would return ARES_ENOMEM.
+
 * July 14 2007 (Daniel Stenberg)
 
 - Vlad Dinulescu fixed two outstanding valgrind reports:
-
  
   1. In ares_query.c , in find_query_by_id we compare q->qid (which is a short
   int variable) with qid, which is declared as an int variable.  Moreover,
diff --git a/ares/ares_init.c b/ares/ares_init.c
index 06dbb6cfe2..add3ffe0db 100644
--- a/ares/ares_init.c
+++ b/ares/ares_init.c
@@ -244,40 +244,49 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
   options->sock_state_cb_data = channel->sock_state_cb_data;
 
   /* Copy servers */
-  options->servers =
-    malloc(channel->nservers * sizeof(struct server_state));
-  if (!options->servers && channel->nservers != 0)
-    return ARES_ENOMEM;
-  for (i = 0; i < channel->nservers; i++)
-    options->servers[i] = channel->servers[i].addr;
+  if (channel->nservers) {
+    options->servers =
+      malloc(channel->nservers * sizeof(struct server_state));
+    if (!options->servers && channel->nservers != 0)
+      return ARES_ENOMEM;
+    for (i = 0; i < channel->nservers; i++)
+      options->servers[i] = channel->servers[i].addr;
+  }
   options->nservers = channel->nservers;
 
   /* copy domains */
-  options->domains = malloc(channel->ndomains * sizeof(char *));
-  if (!options->domains)
-    return ARES_ENOMEM;
-  for (i = 0; i < channel->ndomains; i++)
-  {
-    options->ndomains = i;
-    options->domains[i] = strdup(channel->domains[i]);
-    if (!options->domains[i])
+  if (channel->ndomains) {
+    options->domains = malloc(channel->ndomains * sizeof(char *));
+    if (!options->domains)
       return ARES_ENOMEM;
+
+    for (i = 0; i < channel->ndomains; i++)
+    {
+      options->ndomains = i;
+      options->domains[i] = strdup(channel->domains[i]);
+      if (!options->domains[i])
+        return ARES_ENOMEM;
+    }
   }
   options->ndomains = channel->ndomains;
 
   /* copy lookups */
-  options->lookups = strdup(channel->lookups);
-  if (!options->lookups)
-    return ARES_ENOMEM;
+  if (channel->lookups) {
+    options->lookups = strdup(channel->lookups);
+    if (!options->lookups && channel->lookups)
+      return ARES_ENOMEM;
+  }
 
   /* copy sortlist */
-  options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
-  if (!options->sortlist)
-    return ARES_ENOMEM;
-  for (i = 0; i < channel->nsort; i++)
-  {
-    memcpy(&(options->sortlist[i]), &(channel->sortlist[i]),
-           sizeof(struct apattern));
+  if (channel->nsort) {
+    options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
+    if (!options->sortlist)
+      return ARES_ENOMEM;
+    for (i = 0; i < channel->nsort; i++)
+    {
+      memcpy(&(options->sortlist[i]), &(channel->sortlist[i]),
+             sizeof(struct apattern));
+    }
   }
   options->nsort = channel->nsort;
 
-- 
GitLab