]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/patches/glibc/glibc-rh797094-1.patch
Merge branch 'kernel-update' of ssh://git.ipfire.org/pub/git/ipfire-2.x into kernel...
[ipfire-2.x.git] / src / patches / glibc / glibc-rh797094-1.patch
diff --git a/src/patches/glibc/glibc-rh797094-1.patch b/src/patches/glibc/glibc-rh797094-1.patch
new file mode 100644 (file)
index 0000000..e98b9c0
--- /dev/null
@@ -0,0 +1,657 @@
+diff -rup a/include/alloca.h b/include/alloca.h
+--- a/include/alloca.h 2012-02-29 13:11:19.439693476 -0700
++++ b/include/alloca.h 2012-02-29 13:11:49.832530623 -0700
+@@ -49,15 +49,24 @@ libc_hidden_proto (__libc_alloca_cutoff)
+ #if defined stackinfo_get_sp && defined stackinfo_sub_sp
+ # define alloca_account(size, avar) \
+-  ({ void *old__ = stackinfo_get_sp ();                       \
+-     void *m__ = __alloca (size);                     \
+-     avar += stackinfo_sub_sp (old__);                        \
++  ({ void *old__ = stackinfo_get_sp ();                                             \
++     void *m__ = __alloca (size);                                           \
++     avar += stackinfo_sub_sp (old__);                                              \
++     m__; })
++# define extend_alloca_account(buf, len, newlen, avar) \
++  ({ void *old__ = stackinfo_get_sp ();                                             \
++     void *m__ = extend_alloca (buf, len, newlen);                          \
++     avar += stackinfo_sub_sp (old__);                                              \
+      m__; })
+ #else
+ # define alloca_account(size, avar) \
+-  ({ size_t s__ = (size);                 \
+-     avar += s__;                         \
++  ({ size_t s__ = (size);                                                   \
++     avar += s__;                                                           \
+      __alloca (s__); })
++# define extend_alloca_account(buf, len, newlen, avar) \
++  ({ size_t s__ = (newlen);                                                 \
++     avar += s__;                                                           \
++     extend_alloca (buf, len, s__); })
+ #endif
+ #endif
+diff -rup a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+--- a/sysdeps/posix/getaddrinfo.c      2012-02-29 13:11:19.588692676 -0700
++++ b/sysdeps/posix/getaddrinfo.c      2012-02-29 13:12:42.972245862 -0700
+@@ -278,6 +278,7 @@ gaih_inet (const char *name, const struc
+   bool got_ipv6 = false;
+   const char *canon = NULL;
+   const char *orig_name = name;
++  size_t alloca_used = 0;
+   if (req->ai_protocol || req->ai_socktype)
+     {
+@@ -310,7 +311,7 @@ gaih_inet (const char *name, const struc
+         if (tp->name[0])
+           {
+             st = (struct gaih_servtuple *)
+-              __alloca (sizeof (struct gaih_servtuple));
++              alloca_account (sizeof (struct gaih_servtuple), alloca_used);
+             if ((rc = gaih_inet_serv (service->name, tp, req, st)))
+               return rc;
+@@ -334,7 +335,8 @@ gaih_inet (const char *name, const struc
+                   continue;
+                 newp = (struct gaih_servtuple *)
+-                  __alloca (sizeof (struct gaih_servtuple));
++                  alloca_account (sizeof (struct gaih_servtuple),
++                                  alloca_used);
+                 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
+                   {
+@@ -362,7 +364,7 @@ gaih_inet (const char *name, const struc
+       if (req->ai_socktype || req->ai_protocol)
+       {
+-        st = __alloca (sizeof (struct gaih_servtuple));
++        st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
+         st->next = NULL;
+         st->socktype = tp->socktype;
+         st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
+@@ -379,7 +381,8 @@ gaih_inet (const char *name, const struc
+             {
+               struct gaih_servtuple *newp;
+-              newp = __alloca (sizeof (struct gaih_servtuple));
++              newp = alloca_account (sizeof (struct gaih_servtuple),
++                                     alloca_used);
+               newp->next = NULL;
+               newp->socktype = tp->socktype;
+               newp->protocol = tp->protocol;
+@@ -391,10 +394,17 @@ gaih_inet (const char *name, const struc
+       }
+     }
++  bool malloc_name = false;
++  bool malloc_addrmem = false;
++  struct gaih_addrtuple *addrmem = NULL;
++  bool malloc_canonbuf = false;
++  char *canonbuf = NULL;
++  bool malloc_tmpbuf = false;
++  char *tmpbuf = NULL;
++  int result = 0;
+   if (name != NULL)
+     {
+-      at = __alloca (sizeof (struct gaih_addrtuple));
+-
++      at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
+       at->family = AF_UNSPEC;
+       at->scopeid = 0;
+       at->next = NULL;
+@@ -412,6 +422,7 @@ gaih_inet (const char *name, const struc
+         rc = __idna_to_ascii_lz (name, &p, idn_flags);
+         if (rc != IDNA_SUCCESS)
+           {
++            /* No need to jump to free_and_return here.  */
+             if (rc == IDNA_MALLOC_ERROR)
+               return -EAI_MEMORY;
+             if (rc == IDNA_DLOPEN_ERROR)
+@@ -421,10 +432,7 @@ gaih_inet (const char *name, const struc
+         /* In case the output string is the same as the input string
+            no new string has been allocated.  */
+         if (p != name)
+-          {
+-            name = strdupa (p);
+-            free (p);
+-          }
++          malloc_name = true;
+       }
+ #endif
+@@ -441,23 +449,59 @@ gaih_inet (const char *name, const struc
+             at->family = AF_INET6;
+           }
+         else
+-          return -EAI_ADDRFAMILY;
++          {
++            result = -EAI_ADDRFAMILY;
++            goto free_and_return;
++          }
+         if (req->ai_flags & AI_CANONNAME)
+           canon = name;
+       }
+       else if (at->family == AF_UNSPEC)
+       {
+-        char *namebuf = (char *) name;
+         char *scope_delim = strchr (name, SCOPE_DELIMITER);
++        int e;
+-        if (__builtin_expect (scope_delim != NULL, 0))
+-          {
+-            namebuf = alloca (scope_delim - name + 1);
+-            *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
+-          }
++        {
++          bool malloc_namebuf = false;
++          char *namebuf = (char *) name;
++
++          if (__builtin_expect (scope_delim != NULL, 0))
++            {
++              if (malloc_name)
++                *scope_delim = '\0';
++              else
++                {
++                  if (__libc_use_alloca (alloca_used
++                                         + scope_delim - name + 1))
++                    {
++                      namebuf = alloca_account (scope_delim - name + 1,
++                                                alloca_used);
++                      *((char *) __mempcpy (namebuf, name,
++                                            scope_delim - name)) = '\0';
++                    }
++                  else
++                    {
++                      namebuf = strndup (name, scope_delim - name);
++                      if (namebuf == NULL)
++                        {
++                          assert (!malloc_name);
++                          return -EAI_MEMORY;
++                        }
++                      malloc_namebuf = true;
++                    }
++                }
++            }
+-        if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
++          e = inet_pton (AF_INET6, namebuf, at->addr);
++
++          if (malloc_namebuf)
++            free (namebuf);
++          else if (scope_delim != NULL && malloc_name)
++            /* Undo what we did above.  */
++            *scope_delim = SCOPE_DELIMITER;
++        }
++        if (e > 0)
+           {
+             if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
+               at->family = AF_INET6;
+@@ -468,7 +512,10 @@ gaih_inet (const char *name, const struc
+                 at->family = AF_INET;
+               }
+             else
+-              return -EAI_ADDRFAMILY;
++              {
++                result = -EAI_ADDRFAMILY;
++                goto free_and_return;
++              }
+             if (scope_delim != NULL)
+               {
+@@ -490,7 +537,10 @@ gaih_inet (const char *name, const struc
+                     at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
+                                                       10);
+                     if (*end != '\0')
+-                      return GAIH_OKIFUNSPEC | -EAI_NONAME;
++                      {
++                        result = GAIH_OKIFUNSPEC | -EAI_NONAME;
++                        goto free_and_return;
++                      }
+                   }
+               }
+@@ -520,59 +570,80 @@ gaih_inet (const char *name, const struc
+           {
+             int family = req->ai_family;
+             size_t tmpbuflen = 512;
+-            char *tmpbuf = alloca (tmpbuflen);
++            assert (tmpbuf == NULL);
++            tmpbuf = alloca_account (tmpbuflen, alloca_used);
+             int rc;
+             struct hostent th;
+             struct hostent *h;
+             int herrno;
+-          simple_again:
+             while (1)
+               {
+-                rc = __gethostbyname2_r (name, family, &th, tmpbuf,
++                rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
+                                          tmpbuflen, &h, &herrno);
+                 if (rc != ERANGE || herrno != NETDB_INTERNAL)
+                   break;
+-                tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
++
++                if (!malloc_tmpbuf
++                    && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
++                  tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
++                                                  2 * tmpbuflen,
++                                                  alloca_used);
++                else
++                  {
++                    char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
++                                          2 * tmpbuflen);
++                    if (newp == NULL)
++                      {
++                        result = -EAI_MEMORY;
++                        goto free_and_return;
++                      }
++                    tmpbuf = newp;
++                    malloc_tmpbuf = true;
++                    tmpbuflen = 2 * tmpbuflen;
++                  }
+               }
+             if (rc == 0)
+               {
+-                if (h == NULL)
++                if (h != NULL)
+                   {
+-                    if (req->ai_family == AF_INET6
+-                        && (req->ai_flags & AI_V4MAPPED)
+-                        && family == AF_INET6)
++                    int i;
++                    /* We found data, count the number of addresses.  */
++                    for (i = 0; h->h_addr_list[i]; ++i)
++                      ;
++                    if (i > 0 && *pat != NULL)
++                      --i;
++
++                    if (__libc_use_alloca (alloca_used
++                                           + i * sizeof (struct gaih_addrtuple)))
++                      addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
++                                                alloca_used);
++                    else
+                       {
+-                        /* Try again, this time looking for IPv4
+-                           addresses.  */
+-                        family = AF_INET;
+-                        goto simple_again;
++                        addrmem = malloc (i
++                                          * sizeof (struct gaih_addrtuple));
++                        if (addrmem == NULL)
++                      {
++                            result = -EAI_MEMORY;
++                            goto free_and_return;
+                       }
++                        malloc_addrmem = true;
+                   }
+-                else
+-                  {
+-                    /* We found data, now convert it into the list.  */
+-                    for (int i = 0; h->h_addr_list[i]; ++i)
++
++                    /* Now convert it into the list.  */
++                    struct gaih_addrtuple *addrfree = addrmem;
++                    for (i = 0; h->h_addr_list[i]; ++i)
+                       {
+                         if (*pat == NULL)
+                           {
+-                            *pat = __alloca (sizeof (struct gaih_addrtuple));
++                            *pat = addrfree++;
+                             (*pat)->scopeid = 0;
+                           }
+                         (*pat)->next = NULL;
+-                        (*pat)->family = req->ai_family;
+-                        if (family == req->ai_family)
++                        (*pat)->family = AF_INET;
+                           memcpy ((*pat)->addr, h->h_addr_list[i],
+                                   h->h_length);
+-                        else
+-                          {
+-                            uint32_t *addr = (uint32_t *) (*pat)->addr;
+-                            addr[3] = *(uint32_t *) h->h_addr_list[i];
+-                            addr[2] = htonl (0xffff);
+-                            addr[1] = 0;
+-                            addr[0] = 0;
+-                          }
+                         pat = &((*pat)->next);
+                       }
+                   }
+@@ -582,15 +653,16 @@ gaih_inet (const char *name, const struc
+                 if (herrno == NETDB_INTERNAL)
+                   {
+                     __set_h_errno (herrno);
+-                    return -EAI_SYSTEM;
+-                  }
+-                if (herrno == TRY_AGAIN)
+-                  {
+-                    return -EAI_AGAIN;
++                    result = -EAI_SYSTEM;
+                   }
++                else if (herrno == TRY_AGAIN)
++                  result = -EAI_AGAIN;
++                else
+                 /* We made requests but they turned out no data.
+                    The name is known, though.  */
+-                return GAIH_OKIFUNSPEC | -EAI_NODATA;
++                  result = GAIH_OKIFUNSPEC | -EAI_NODATA;
++
++                goto free_and_return;
+               }
+             goto process_list;
+@@ -613,21 +685,56 @@ gaih_inet (const char *name, const struc
+                 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
+                 char *addrs = air->addrs;
++                if (__libc_use_alloca (alloca_used
++                                       + air->naddrs * sizeof (struct gaih_addrtuple)))
++                  addrmem = alloca_account (air->naddrs
++                                            * sizeof (struct gaih_addrtuple),
++                                            alloca_used);
++                else
++                  {
++                    addrmem = malloc (air->naddrs
++                                      * sizeof (struct gaih_addrtuple));
++                    if (addrmem == NULL)
++                      {
++                        result = -EAI_MEMORY;
++                        goto free_and_return;
++                      }
++                    malloc_addrmem = true;
++                  }
++
++                struct gaih_addrtuple *addrfree = addrmem;
+                 for (int i = 0; i < air->naddrs; ++i)
+                   {
+                     socklen_t size = (air->family[i] == AF_INET
+                                       ? INADDRSZ : IN6ADDRSZ);
+                     if (*pat == NULL)
+                       {
+-                        *pat = __alloca (sizeof (struct gaih_addrtuple));
++                        *pat = addrfree++;
+                         (*pat)->scopeid = 0;
+                       }
+                     uint32_t *pataddr = (*pat)->addr;
+                     (*pat)->next = NULL;
+                     if (added_canon || air->canon == NULL)
+                       (*pat)->name = NULL;
+-                    else
+-                      canon = (*pat)->name = strdupa (air->canon);
++                    else if (canonbuf == NULL)
++                      {
++                        size_t canonlen = strlen (air->canon) + 1;
++                        if ((req->ai_flags & AI_CANONIDN) != 0
++                            && __libc_use_alloca (alloca_used + canonlen))
++                          canonbuf = alloca_account (canonlen, alloca_used);
++                        else
++                          {
++                            canonbuf = malloc (canonlen);
++                            if (canonbuf == NULL)
++                              {
++                                result = -EAI_MEMORY;
++                                goto free_and_return;
++                              }
++                            malloc_canonbuf = true;
++                          }
++                        canon = (*pat)->name = memcpy (canonbuf, air->canon,
++                                                       canonlen);
++                      }
+                     if (air->family[i] == AF_INET
+                         && req->ai_family == AF_INET6
+@@ -657,20 +764,26 @@ gaih_inet (const char *name, const struc
+                 free (air);
+                 if (at->family == AF_UNSPEC)
+-                  return GAIH_OKIFUNSPEC | -EAI_NONAME;
++                  {
++                    result = GAIH_OKIFUNSPEC | -EAI_NONAME;
++                    goto free_and_return;
++                  }
+                 goto process_list;
+               }
+             else if (err == 0)
+               /* The database contains a negative entry.  */
+-              return 0;
++              goto free_and_return;
+             else if (__nss_not_use_nscd_hosts == 0)
+               {
+                 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
+-                  return -EAI_MEMORY;
+-                if (herrno == TRY_AGAIN)
+-                  return -EAI_AGAIN;
+-                return -EAI_SYSTEM;
++                  result = -EAI_MEMORY;
++                else if (herrno == TRY_AGAIN)
++                  result = -EAI_AGAIN;
++                else
++                  result = -EAI_SYSTEM;
++
++                goto free_and_return;
+               }
+           }
+ #endif
+@@ -699,7 +812,19 @@ gaih_inet (const char *name, const struc
+         _res.options &= ~RES_USE_INET6;
+         size_t tmpbuflen = 1024;
+-        char *tmpbuf = alloca (tmpbuflen);
++        malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
++        assert (tmpbuf == NULL);
++        if (!malloc_tmpbuf)
++          tmpbuf = alloca_account (tmpbuflen, alloca_used);
++        else
++          {
++            tmpbuf = malloc (tmpbuflen);
++            if (tmpbuf == NULL)
++              {
++                result = -EAI_MEMORY;
++                goto free_and_return;
++              }
++          }
+         while (!no_more)
+           {
+@@ -728,8 +853,25 @@ gaih_inet (const char *name, const struc
+                           no_data = herrno == NO_DATA;
+                         break;
+                       }
+-                    tmpbuf = extend_alloca (tmpbuf,
+-                                            tmpbuflen, 2 * tmpbuflen);
++
++                    if (!malloc_tmpbuf
++                        && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
++                      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
++                                                      2 * tmpbuflen,
++                                                      alloca_used);
++                    else
++                      {
++                        char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
++                                              2 * tmpbuflen);
++                        if (newp == NULL)
++                          {
++                            result = -EAI_MEMORY;
++                            goto free_and_return;
++                          }
++                        tmpbuf = newp;
++                        malloc_tmpbuf = true;
++                        tmpbuflen = 2 * tmpbuflen;
++                      }
+                   }
+                 if (status == NSS_STATUS_SUCCESS)
+@@ -832,18 +974,40 @@ gaih_inet (const char *name, const struc
+                             if (cfct != NULL)
+                               {
+                                 const size_t max_fqdn_len = 256;
+-                                char *buf = alloca (max_fqdn_len);
++                                if ((req->ai_flags & AI_CANONIDN) != 0
++                                    && __libc_use_alloca (alloca_used
++                                                          + max_fqdn_len))
++                                  canonbuf = alloca_account (max_fqdn_len,
++                                                             alloca_used);
++                                else
++                                  {
++                                    canonbuf = malloc (max_fqdn_len);
++                                    if (canonbuf == NULL)
++                                      {
++                                        result = -EAI_MEMORY;
++                                        goto free_and_return;
++                                      }
++                                    malloc_canonbuf = true;
++                                  }
+                                 char *s;
+                                 if (DL_CALL_FCT (cfct, (at->name ?: name,
+-                                                        buf, max_fqdn_len,
++                                                        canonbuf,
++                                                        max_fqdn_len,
+                                                         &s, &rc, &herrno))
+                                     == NSS_STATUS_SUCCESS)
+                                   canon = s;
+                                 else
+-                                  /* Set to name now to avoid using
+-                                     gethostbyaddr.  */
+-                                  canon = name;
++                                  {
++                                    /* Set to name now to avoid using
++                                       gethostbyaddr.  */
++                                    if (malloc_canonbuf)
++                                      {
++                                        free (canonbuf);
++                                        malloc_canonbuf = false;
++                                      }
++                                    canon = name;
++                                  }
+                               }
+                           }
+                         status = NSS_STATUS_SUCCESS;
+@@ -878,22 +1042,27 @@ gaih_inet (const char *name, const struc
+           {
+             /* If both requests timed out report this.  */
+             if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
+-              return -EAI_AGAIN;
++              result = -EAI_AGAIN;
++            else
++              /* We made requests but they turned out no data.  The name
++                 is known, though.  */
++              result = GAIH_OKIFUNSPEC | -EAI_NODATA;
+-            /* We made requests but they turned out no data.  The name
+-               is known, though.  */
+-            return GAIH_OKIFUNSPEC | -EAI_NODATA;
++            goto free_and_return;
+           }
+       }
+     process_list:
+       if (at->family == AF_UNSPEC)
+-      return GAIH_OKIFUNSPEC | -EAI_NONAME;
++      {
++        result = GAIH_OKIFUNSPEC | -EAI_NONAME;
++        goto free_and_return;
++      }
+     }
+   else
+     {
+       struct gaih_addrtuple *atr;
+-      atr = at = __alloca (sizeof (struct gaih_addrtuple));
++      atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
+       memset (at, '\0', sizeof (struct gaih_addrtuple));
+       if (req->ai_family == AF_UNSPEC)
+@@ -932,6 +1101,9 @@ gaih_inet (const char *name, const struc
+       /* Only the first entry gets the canonical name.  */
+       if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
+         {
++          char *tmpbuf2 = NULL;
++          bool malloc_tmpbuf2 = false;
++
+           if (canon == NULL)
+             {
+               /* If the canonical name cannot be determined, use
+@@ -952,11 +1124,16 @@ gaih_inet (const char *name, const struc
+               int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
+               if (rc != IDNA_SUCCESS)
+                 {
++                  if (malloc_tmpbuf2)
++                    free (tmpbuf2);
++
+                   if (rc == IDNA_MALLOC_ERROR)
+-                    return -EAI_MEMORY;
+-                  if (rc == IDNA_DLOPEN_ERROR)
+-                    return -EAI_SYSTEM;
+-                  return -EAI_IDN_ENCODE;
++                    result = -EAI_MEMORY;
++                  else if (rc == IDNA_DLOPEN_ERROR)
++                    result = -EAI_SYSTEM;
++                  else
++                    result = -EAI_IDN_ENCODE;
++                  goto free_and_return;
+                 }
+               /* In case the output string is the same as the input
+                  string no new string has been allocated and we
+@@ -970,10 +1147,25 @@ gaih_inet (const char *name, const struc
+ #ifdef HAVE_LIBIDN
+             make_copy:
+ #endif
+-              canon = strdup (canon);
+-              if (canon == NULL)
+-                return -EAI_MEMORY;
++              if (malloc_canonbuf)
++                /* We already allocated the string using malloc.  */
++                malloc_canonbuf = false;
++              else
++                {
++                  canon = strdup (canon);
++                  if (canon == NULL)
++                    {
++                      if (malloc_tmpbuf2)
++                        free (tmpbuf2);
++
++                      result = -EAI_MEMORY;
++                      goto free_and_return;
++                    }
++                }
+             }
++
++          if (malloc_tmpbuf2)
++            free (tmpbuf2);
+         }
+       family = at2->family;
+@@ -999,7 +1191,8 @@ gaih_inet (const char *name, const struc
+           if (ai == NULL)
+             {
+               free ((char *) canon);
+-              return -EAI_MEMORY;
++              result = -EAI_MEMORY;
++              goto free_and_return;
+             }
+           ai->ai_flags = req->ai_flags;
+@@ -1052,7 +1245,18 @@ gaih_inet (const char *name, const struc
+       at2 = at2->next;
+       }
+   }
+-  return 0;
++
++ free_and_return:
++  if (malloc_name)
++    free ((char *) name);
++  if (malloc_addrmem)
++    free (addrmem);
++  if (malloc_canonbuf)
++    free (canonbuf);
++  if (malloc_tmpbuf)
++    free (tmpbuf);
++
++  return result;
+ }