Account for alloca use when collecting interface addresses (bug 16002)
authorAndreas Schwab <schwab@suse.de>
Mon, 24 Mar 2014 10:06:30 +0000 (11:06 +0100)
committerAndreas Schwab <schwab@suse.de>
Mon, 24 Mar 2014 15:05:13 +0000 (16:05 +0100)
To reproduce:

# ip li add name dummy0 type dummy
# site_id=$(head -c6 /dev/urandom | od -tx2 -An | tr ' ' ':')
# for ((i = 0; i < 65536; i++)) do
> ip ad ad $(printf fd80$site_id::%04x $i)/128 dev dummy0
> done
# (ulimit -s 900; getent ahosts localhost)
# ip li de dummy0

ChangeLog
NEWS
sysdeps/unix/sysv/linux/check_pf.c

index e9fdbe7..c2ccddf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-03-24  Andreas Schwab  <schwab@suse.de>
+
+       [BZ #16002]
+       * sysdeps/unix/sysv/linux/check_pf.c (make_request): Use
+       alloca_account and account alloca use for struct in6ailist.
+
 2014-03-24  Joseph Myers  <joseph@codesourcery.com>
 
        [BZ #16284]
diff --git a/NEWS b/NEWS
index 00a8bf4..9418390 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,9 +9,9 @@ Version 2.20
 
 * The following bugs are resolved with this release:
 
-  15347, 15804, 15894, 16284, 16447, 16532, 16545, 16574, 16600, 16609,
-  16610, 16611, 16613, 16623, 16632, 16639, 16642, 16649, 16670, 16674,
-  16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16731.
+  15347, 15804, 15894, 16002, 16284, 16447, 16532, 16545, 16574, 16600,
+  16609, 16610, 16611, 16613, 16623, 16632, 16639, 16642, 16649, 16670,
+  16674, 16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16731.
 
 * Running the testsuite no longer terminates as soon as a test fails.
   Instead, a file tests.sum (xtests.sum from "make xcheck") is generated,
index 5c8e75a..6d8468d 100644 (file)
@@ -139,9 +139,10 @@ make_request (int fd, pid_t pid)
 #endif
   bool use_malloc = false;
   char *buf;
+  size_t alloca_used = 0;
 
   if (__libc_use_alloca (buf_size))
-    buf = alloca (buf_size);
+    buf = alloca_account (buf_size, alloca_used);
   else
     {
       buf = malloc (buf_size);
@@ -163,6 +164,7 @@ make_request (int fd, pid_t pid)
   {
     struct in6addrinfo info;
     struct in6ailist *next;
+    bool use_malloc;
   } *in6ailist = NULL;
   size_t in6ailistlen = 0;
   bool seen_ipv4 = false;
@@ -239,7 +241,19 @@ make_request (int fd, pid_t pid)
                    }
                }
 
-             struct in6ailist *newp = alloca (sizeof (*newp));
+             struct in6ailist *newp;
+             if (__libc_use_alloca (alloca_used + sizeof (*newp)))
+               {
+                 newp = alloca_account (sizeof (*newp), alloca_used);
+                 newp->use_malloc = false;
+               }
+             else
+               {
+                 newp = malloc (sizeof (*newp));
+                 if (newp == NULL)
+                   goto out_fail;
+                 newp->use_malloc = true;
+               }
              newp->info.flags = (((ifam->ifa_flags
                                    & (IFA_F_DEPRECATED
                                       | IFA_F_OPTIMISTIC))
@@ -286,7 +300,10 @@ make_request (int fd, pid_t pid)
       do
        {
          result->in6ai[--in6ailistlen] = in6ailist->info;
-         in6ailist = in6ailist->next;
+         struct in6ailist *next = in6ailist->next;
+         if (in6ailist->use_malloc)
+           free (in6ailist);
+         in6ailist = next;
        }
       while (in6ailist != NULL);
     }
@@ -302,7 +319,14 @@ make_request (int fd, pid_t pid)
     free (buf);
   return result;
 
-out_fail:
+ out_fail:
+  while (in6ailist != NULL)
+    {
+      struct in6ailist *next = in6ailist->next;
+      if (in6ailist->use_malloc)
+       free (in6ailist);
+      in6ailist = next;
+    }
   if (use_malloc)
     free (buf);
   return NULL;