about summary refs log tree commit diff
path: root/elf/dl-sysdep.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-07-31 13:33:18 +0000
committerJakub Jelinek <jakub@redhat.com>2007-07-31 13:33:18 +0000
commit32c075e1f01849e161724bbd400ba77244e482cc (patch)
tree5f083a3f352104f32bb6c902d57fa3f294bd8d4d /elf/dl-sysdep.c
parentd6220e9ee38c1c9285221b023346201ec5f511b3 (diff)
downloadglibc-32c075e1f01849e161724bbd400ba77244e482cc.tar.gz
glibc-32c075e1f01849e161724bbd400ba77244e482cc.tar.xz
glibc-32c075e1f01849e161724bbd400ba77244e482cc.zip
.
Diffstat (limited to 'elf/dl-sysdep.c')
-rw-r--r--elf/dl-sysdep.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index d06ce1754e..68e08f480a 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -1,5 +1,5 @@
 /* Operating system support for run-time dynamic linker.  Generic Unix version.
-   Copyright (C) 1995-1998, 2000-2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -405,8 +405,25 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
     }
 #endif
 
+#ifdef USE_TLS
   /* For TLS enabled builds always add 'tls'.  */
   ++cnt;
+#else
+  if (cnt == 0)
+    {
+      /* If we no have platform name and no important capability we only
+	 have the base directory to search.  */
+      result = (struct r_strlenpair *) malloc (sizeof (*result));
+      if (result == NULL)
+	goto no_memory;
+
+      result[0].str = (char *) result;	/* Does not really matter.  */
+      result[0].len = 0;
+
+      *sz = 1;
+      return result;
+    }
+#endif
 
   /* Create temporary data structure to generate result table.  */
   temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
@@ -448,11 +465,11 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
       temp[m].len = platform_len;
       ++m;
     }
-
+#ifdef USE_TLS
   temp[m].str = "tls";
   temp[m].len = 3;
   ++m;
-
+#endif
   assert (m == cnt);
 
   /* Determine the total size of all strings together.  */
@@ -460,9 +477,21 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
     total = temp[0].len + 1;
   else
     {
-      total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
-      for (n = 1; n + 1 < cnt; ++n)
-	total += (1UL << (cnt - 3)) * (temp[n].len + 1);
+      total = temp[0].len + temp[cnt - 1].len + 2;
+      if (cnt > 2)
+	{
+	  total <<= 1;
+	  for (n = 1; n + 1 < cnt; ++n)
+	    total += temp[n].len + 1;
+	  if (cnt > 3
+	      && (cnt >= sizeof (size_t) * 8
+		  || total + (sizeof (*result) << 3)
+		     >= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
+	    _dl_signal_error (ENOMEM, NULL, NULL,
+			      N_("cannot create capability list"));
+
+	  total <<= cnt - 3;
+	}
     }
 
   /* The result structure: we use a very compressed way to store the
@@ -470,8 +499,13 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
   *sz = 1 << cnt;
   result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
   if (result == NULL)
-    _dl_signal_error (ENOMEM, NULL, NULL,
-		      N_("cannot create capability list"));
+    {
+#ifndef USE_TLS
+    no_memory:
+#endif
+      _dl_signal_error (ENOMEM, NULL, NULL,
+			N_("cannot create capability list"));
+    }
 
   if (cnt == 1)
     {