]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
gaih_inet: Simplify canon name resolution
authorSiddhesh Poyarekar <siddhesh@sourceware.org>
Mon, 7 Mar 2022 16:47:36 +0000 (22:17 +0530)
committerSiddhesh Poyarekar <siddhesh@sourceware.org>
Tue, 22 Mar 2022 14:09:12 +0000 (19:39 +0530)
Simplify logic for allocation of canon to remove the canonbuf variable;
canon now always points to an allocated block.  Also pull the canon name
set into a separate function.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: DJ Delorie <dj@redhat.com>
sysdeps/posix/getaddrinfo.c

index 3d9bea60c6638ffaf230fe2ca3c7160ef846673b..0629fd147b2ede2ac3c13dfa61bfdf56bbd1aba3 100644 (file)
@@ -285,7 +285,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
                                                                              \
       if (localcanon != NULL && canon == NULL)                               \
        {                                                                     \
-         canonbuf = __strdup (localcanon);                                   \
+         char *canonbuf = __strdup (localcanon);                             \
          if (canonbuf == NULL)                                               \
            {                                                                 \
              __resolv_context_put (res_ctx);                                 \
@@ -323,6 +323,41 @@ getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
   return __strdup (name);
 }
 
+/* Process looked up canonical name and if necessary, decode to IDNA.  Result
+   is a new string written to CANONP and the earlier string is freed.  */
+
+static int
+process_canonname (const struct addrinfo *req, const char *orig_name,
+                  char **canonp)
+{
+  char *canon = *canonp;
+
+  if ((req->ai_flags & AI_CANONNAME) != 0)
+    {
+      bool do_idn = req->ai_flags & AI_CANONIDN;
+      if (do_idn)
+       {
+         char *out;
+         int rc = __idna_from_dns_encoding (canon ?: orig_name, &out);
+         if (rc == 0)
+           {
+             free (canon);
+             canon = out;
+           }
+         else if (rc == EAI_IDN_ENCODE)
+           /* Use the punycode name as a fallback.  */
+           do_idn = false;
+         else
+           return -rc;
+       }
+      if (!do_idn && canon == NULL && (canon = __strdup (orig_name)) == NULL)
+       return -EAI_MEMORY;
+    }
+
+  *canonp = canon;
+  return 0;
+}
+
 static int
 gaih_inet (const char *name, const struct gaih_service *service,
           const struct addrinfo *req, struct addrinfo **pai,
@@ -332,7 +367,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
   struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
   struct gaih_addrtuple *at = NULL;
   bool got_ipv6 = false;
-  const char *canon = NULL;
+  char *canon = NULL;
   const char *orig_name = name;
 
   /* Reserve stack memory for the scratch buffer in the getaddrinfo
@@ -453,7 +488,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
 
   bool malloc_name = false;
   struct gaih_addrtuple *addrmem = NULL;
-  char *canonbuf = NULL;
   int result = 0;
 
   if (name != NULL)
@@ -495,7 +529,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
            }
 
          if (req->ai_flags & AI_CANONNAME)
-           canon = name;
+           {
+             char *canonbuf = __strdup (name);
+             if (canonbuf == NULL)
+               {
+                 result = -EAI_MEMORY;
+                 goto free_and_return;
+               }
+             canon = canonbuf;
+           }
 
          goto process_list;
        }
@@ -545,7 +587,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
            }
 
          if (req->ai_flags & AI_CANONNAME)
-           canon = name;
+           {
+             char *canonbuf = __strdup (name);
+             if (canonbuf == NULL)
+               {
+                 result = -EAI_MEMORY;
+                 goto free_and_return;
+               }
+             canon = canonbuf;
+           }
 
          goto process_list;
        }
@@ -676,9 +726,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
                      (*pat)->next = NULL;
                      if (added_canon || air->canon == NULL)
                        (*pat)->name = NULL;
-                     else if (canonbuf == NULL)
+                     else if (canon == NULL)
                        {
-                         canonbuf = __strdup (air->canon);
+                         char *canonbuf = __strdup (air->canon);
                          if (canonbuf == NULL)
                            {
                              result = -EAI_MEMORY;
@@ -748,9 +798,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
              /* Always start afresh; continue should discard previous results
                 and the hosts database does not support merge.  */
              at = NULL;
-             free (canonbuf);
+             free (canon);
              free (addrmem);
-             canon = canonbuf = NULL;
+             canon = NULL;
              addrmem = NULL;
              got_ipv6 = false;
 
@@ -805,7 +855,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
                      no_data = 1;
 
                      if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
-                       canon = at->name;
+                       {
+                         char *canonbuf = __strdup (at->name);
+                         if (canonbuf == NULL)
+                           {
+                             __resolv_context_put (res_ctx);
+                             result = -EAI_MEMORY;
+                             goto free_and_return;
+                           }
+                         canon = canonbuf;
+                       }
 
                      struct gaih_addrtuple **pat = &at;
 
@@ -893,7 +952,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
                          if ((req->ai_flags & AI_CANONNAME) != 0
                              && canon == NULL)
                            {
-                             canonbuf = getcanonname (nip, at, name);
+                             char *canonbuf = getcanonname (nip, at, name);
                              if (canonbuf == NULL)
                                {
                                  __resolv_context_put (res_ctx);
@@ -1004,6 +1063,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
     }
 
   {
+    /* Set up the canonical name if we need it.  */
+    if ((result = process_canonname (req, orig_name, &canon)) != 0)
+      goto free_and_return;
+
     struct gaih_servtuple *st2;
     struct gaih_addrtuple *at2 = at;
     size_t socklen;
@@ -1014,48 +1077,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
      */
     while (at2 != NULL)
       {
-       /* Only the first entry gets the canonical name.  */
-       if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
-         {
-           if (canon == NULL)
-             /* If the canonical name cannot be determined, use
-                the passed in string.  */
-             canon = orig_name;
-
-           bool do_idn = req->ai_flags & AI_CANONIDN;
-           if (do_idn)
-             {
-               char *out;
-               int rc = __idna_from_dns_encoding (canon, &out);
-               if (rc == 0)
-                 canon = out;
-               else if (rc == EAI_IDN_ENCODE)
-                 /* Use the punycode name as a fallback.  */
-                 do_idn = false;
-               else
-                 {
-                   result = -rc;
-                   goto free_and_return;
-                 }
-             }
-           if (!do_idn)
-             {
-               if (canonbuf != NULL)
-                 /* We already allocated the string using malloc, but
-                    the buffer is now owned by canon.  */
-                 canonbuf = NULL;
-               else
-                 {
-                   canon = __strdup (canon);
-                   if (canon == NULL)
-                     {
-                       result = -EAI_MEMORY;
-                       goto free_and_return;
-                     }
-                 }
-             }
-         }
-
        family = at2->family;
        if (family == AF_INET6)
          {
@@ -1078,7 +1099,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
            ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
            if (ai == NULL)
              {
-               free ((char *) canon);
                result = -EAI_MEMORY;
                goto free_and_return;
              }
@@ -1138,7 +1158,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
   if (malloc_name)
     free ((char *) name);
   free (addrmem);
-  free (canonbuf);
+  free (canon);
 
   return result;
 }