Index: glibc-2.11.3/sysdeps/unix/sysv/linux/check_pf.c
===================================================================
--- glibc-2.11.3.orig/sysdeps/unix/sysv/linux/check_pf.c
+++ glibc-2.11.3/sysdeps/unix/sysv/linux/check_pf.c
@@ -42,6 +42,105 @@
 # define IFA_F_OPTIMISTIC 0
 #endif
 
+#define IN6AI_FIXED_SIZE 16
+#define IN6AI_CHUNK_SIZE 64
+
+
+struct in6ai_chunk
+{
+  struct in6addrinfo info[IN6AI_CHUNK_SIZE];
+  struct in6ai_chunk *next;
+};
+
+struct in6ai_list
+{
+  struct in6addrinfo info[IN6AI_FIXED_SIZE];
+  unsigned count;
+  struct in6ai_chunk *next;
+};
+
+
+static void
+in6ailist_init (struct in6ai_list *list)
+{
+  list->count = 0;
+  list->next = NULL;
+}
+
+
+static struct in6addrinfo *
+in6ailist_add (struct in6ai_list *list)
+{
+  if (list->count < IN6AI_FIXED_SIZE)
+    return &list->info[list->count++];
+
+  unsigned idx = list->count - IN6AI_FIXED_SIZE;
+  struct in6ai_chunk **chunk = &list->next;
+  while (idx >= IN6AI_CHUNK_SIZE)
+    {
+      chunk = &(*chunk)->next;
+      idx -= IN6AI_CHUNK_SIZE;
+    }
+
+  if (idx == 0)
+    {
+      *chunk = malloc (sizeof (struct in6ai_chunk));
+      if (*chunk == NULL)
+	return NULL;
+      (*chunk)->next = NULL;
+    }
+  list->count++;
+  return &(*chunk)->info[idx];
+}
+
+
+static int
+in6ailist_export (struct in6ai_list *list,
+		  struct in6addrinfo **out_data, size_t *out_len)
+{
+  unsigned count = list->count;
+  *out_data = malloc (count * sizeof(struct in6addrinfo));
+  if (*out_data == NULL)
+    {
+      *out_len = 0;
+      return -1;
+    }
+
+  struct in6addrinfo *p = *out_data;
+  unsigned n;
+
+  n = count > IN6AI_FIXED_SIZE ? IN6AI_FIXED_SIZE : count;
+  memcpy (p, list->info, n * sizeof (struct in6addrinfo));
+  p += n;
+  count -= n;
+
+  struct in6ai_chunk *chunk = list->next;
+  while (n > 0)
+    {
+      n = count > IN6AI_CHUNK_SIZE ? IN6AI_CHUNK_SIZE : count;
+      memcpy (p, list->info, n * sizeof (struct in6addrinfo));
+      p += n;
+      count -= n;
+      chunk = chunk->next;
+    }
+
+  *out_len = list->count;
+  return 0;
+}
+
+
+static void
+in6ailist_cleanup (struct in6ai_list *list)
+{
+  struct in6ai_chunk *chunk = list->next;
+  while (chunk)
+    {
+      struct in6ai_chunk *next = chunk->next;
+      free (chunk);
+      chunk = next;
+    }
+}
+
 
 static int
 make_request (int fd, pid_t pid, bool *seen_ipv4, bool *seen_ipv6,
@@ -71,6 +170,9 @@ make_request (int fd, pid_t pid, bool *s
   memset (&nladdr, '\0', sizeof (nladdr));
   nladdr.nl_family = AF_NETLINK;
 
+  struct in6ai_list in6ai_list;
+  in6ailist_init (&in6ai_list);
+
 #ifdef PAGE_SIZE
   /* Help the compiler optimize out the malloc call if PAGE_SIZE
      is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
@@ -103,12 +205,6 @@ make_request (int fd, pid_t pid, bool *s
   *seen_ipv6 = false;
 
   bool done = false;
-  struct in6ailist
-  {
-    struct in6addrinfo info;
-    struct in6ailist *next;
-  } *in6ailist = NULL;
-  size_t in6ailistlen = 0;
 
   do
     {
@@ -181,28 +277,25 @@ make_request (int fd, pid_t pid, bool *s
 		    }
 		}
 
-	      struct in6ailist *newp = alloca (sizeof (*newp));
-	      newp->info.flags = (((ifam->ifa_flags
-				    & (IFA_F_DEPRECATED
-				       | IFA_F_OPTIMISTIC))
-				   ? in6ai_deprecated : 0)
-				  | ((ifam->ifa_flags
-				      & IFA_F_HOMEADDRESS)
-				     ? in6ai_homeaddress : 0));
-	      newp->info.prefixlen = ifam->ifa_prefixlen;
-	      newp->info.index = ifam->ifa_index;
+	      struct in6addrinfo *info = in6ailist_add (&in6ai_list);
+	      if (info == NULL)
+                goto out_fail;
+	      info->flags = (((ifam->ifa_flags
+			       & (IFA_F_DEPRECATED | IFA_F_OPTIMISTIC))
+			      ? in6ai_deprecated : 0)
+			     | (ifam->ifa_flags & IFA_F_HOMEADDRESS
+				? in6ai_homeaddress : 0));
+	      info->prefixlen = ifam->ifa_prefixlen;
+	      info->index = ifam->ifa_index;
 	      if (ifam->ifa_family == AF_INET)
 		{
-		  newp->info.addr[0] = 0;
-		  newp->info.addr[1] = 0;
-		  newp->info.addr[2] = htonl (0xffff);
-		  newp->info.addr[3] = *(const in_addr_t *) address;
+		  info->addr[0] = 0;
+		  info->addr[1] = 0;
+		  info->addr[2] = htonl (0xffff);
+		  info->addr[3] = *(const in_addr_t *) address;
 		}
 	      else
-		memcpy (newp->info.addr, address, sizeof (newp->info.addr));
-	      newp->next = in6ailist;
-	      in6ailist = newp;
-	      ++in6ailistlen;
+		memcpy (info->addr, address, sizeof (info->addr));
 	    }
 	  else if (nlmh->nlmsg_type == NLMSG_DONE)
 	    /* We found the end, leave the loop.  */
@@ -213,27 +306,19 @@ make_request (int fd, pid_t pid, bool *s
 
   close_not_cancel_no_status (fd);
 
-  if (*seen_ipv6 && in6ailist != NULL)
+  if (*seen_ipv6 && in6ai_list.count > 0)
     {
-      *in6ai = malloc (in6ailistlen * sizeof (**in6ai));
-      if (*in6ai == NULL)
-	goto out_fail;
-
-      *in6ailen = in6ailistlen;
-
-      do
-	{
-	  (*in6ai)[--in6ailistlen] = in6ailist->info;
-	  in6ailist = in6ailist->next;
-	}
-      while (in6ailist != NULL);
+      if (in6ailist_export (&in6ai_list, in6ai, in6ailen) < 0)
+        goto out_fail;
     }
 
+  in6ailist_cleanup (&in6ai_list);
   if (use_malloc)
     free (buf);
   return 0;
 
 out_fail:
+  in6ailist_cleanup (&in6ai_list);
   if (use_malloc)
     free (buf);
   return -1;
