summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--elf/dl-load.c60
-rw-r--r--elf/rtld.c55
-rw-r--r--sysdeps/generic/dl-environ.c35
4 files changed, 100 insertions, 62 deletions
diff --git a/ChangeLog b/ChangeLog
index cfedf5d48a..8632fbac12 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2002-02-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/generic/dl-environ.c (unsetenv): Optimize.  Don't use
+	strncmp.
+	* elf/dl-load.c (is_dst): Optimize.  Don't call strncmp twice.
+	* elf/rtld.c (process_dl_debug): Optimize. Avoid calls to strncmp,
+	strspn, and strcspn.
+	(process_envvars): Don't use strcspn.
+
+	* elf/dl-load.c (_dl_dst_count): Fix possible endless loop.
+	(_dl_dst_substitute): Likewise.
+
 2002-02-01  Ulrich Drepper  <drepper@redhat.com>
 
 	* elf/do-rel.h (elf_dynamic_do_rel): Help the compiler recognize
diff --git a/elf/dl-load.c b/elf/dl-load.c
index cd568d2261..ebaccfc000 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libintl.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -147,22 +148,38 @@ local_strdup (const char *s)
 
 
 static size_t
-is_dst (const char *start, const char *name, const char *str, size_t cmplen,
+is_dst (const char *start, const char *name, const char *str,
 	int is_path, int secure)
 {
   size_t len;
+  bool is_curly = false;
 
-  if (strncmp (name, str, cmplen) == 0)
-    len = cmplen + 1;
-  else if (strncmp (name, str + 1, cmplen - 2) == 0
-	   && (name[cmplen - 2] == '\0' || name[cmplen - 2] == '/'
-	       || (is_path && name[cmplen - 2] == ':')))
-    len = cmplen - 1;
-  else
+  if (name[0] == '{')
+    {
+      is_curly = true;
+      ++name;
+    }
+
+  len = 0;
+  while (name[len] == str[len] && name[len] != '\0')
+    ++len;
+
+  if (is_curly)
+    {
+      if (name[len] != '}')
+	return 0;
+
+      /* Point again at the beginning of the name.  */
+      --name;
+      /* Skip over closing curly brace and adjust for the --name.  */
+      len += 2;
+    }
+  else if (name[len] != '\0' && name[len] != '/'
+	   && (!is_path || name[len] != ':'))
     return 0;
 
   if (__builtin_expect (secure, 0)
-      && ((name[len - 1] != '\0' && (!is_path || name[len - 1] != ':'))
+      && ((name[len] != '\0' && (!is_path || name[len] != ':'))
 	  || (name != start + 1 && (!is_path || name[-2] != ':'))))
     return 0;
 
@@ -178,17 +195,14 @@ _dl_dst_count (const char *name, int is_path)
 
   do
     {
-      size_t len = 1;
+      size_t len;
 
       /* $ORIGIN is not expanded for SUID/GUID programs (except if it
-	 is $ORIGIN alone) and it must always appear first in path.
-
-	 Note that it is no bug that the string in the second and
-	 fourth `strncmp' call is longer than the sequence which is
-	 actually tested.  */
-      if ((len = is_dst (start, name + 1, "{ORIGIN}", 8, is_path,
+	 is $ORIGIN alone) and it must always appear first in path.  */
+      ++name;
+      if ((len = is_dst (start, name, "ORIGIN", is_path,
 			 __libc_enable_secure)) != 0
-	  || ((len = is_dst (start, name + 1, "{PLATFORM}", 10, is_path, 0))
+	  || ((len = is_dst (start, name, "PLATFORM", is_path, 0))
 	      != 0))
 	++cnt;
 
@@ -218,15 +232,13 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
       if (__builtin_expect (*name == '$', 0))
 	{
 	  const char *repl = NULL;
-	  size_t len = 1;
+	  size_t len;
 
-	  /* Note that it is no bug that the string in the second and
-	     fourth `strncmp' call is longer than the sequence which
-	     is actually tested.  */
-	  if ((len = is_dst (start, name + 1, "{ORIGIN}", 8, is_path,
+	  ++name;
+	  if ((len = is_dst (start, name, "ORIGIN", is_path,
 			     __libc_enable_secure)) != 0)
 	    repl = l->l_origin;
-	  else if ((len = is_dst (start, name + 1, "{PLATFORM}", 10, is_path,
+	  else if ((len = is_dst (start, name, "PLATFORM", is_path,
 				  0)) != 0)
 	    repl = GL(dl_platform);
 
@@ -246,7 +258,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
 	    }
 	  else
 	    /* No DST we recognize.  */
-	    *wp++ = *name++;
+	    *wp++ = '$';
 	}
       else
 	{
diff --git a/elf/rtld.c b/elf/rtld.c
index 58d61e70c4..1efe38bc80 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1286,49 +1286,50 @@ process_dl_debug (const char *dl_debug)
      is correctly handled in the LD_DEBUG_HELP code below.  */
   static const struct
   {
-    const char name[11];
+    unsigned char len;
+    const char name[10];
     const char helptext[41];
     unsigned short int mask;
   } debopts[] =
     {
-      { "libs", "display library search paths",
+#define LEN_AND_STR(str) sizeof (str) - 1, str
+      { LEN_AND_STR ("libs"), "display library search paths",
 	DL_DEBUG_LIBS | DL_DEBUG_IMPCALLS },
-      { "reloc", "display relocation processing",
+      { LEN_AND_STR ("reloc"), "display relocation processing",
 	DL_DEBUG_RELOC | DL_DEBUG_IMPCALLS },
-      { "files", "display progress for input file",
+      { LEN_AND_STR ("files"), "display progress for input file",
 	DL_DEBUG_FILES | DL_DEBUG_IMPCALLS },
-      { "symbols", "display symbol table processing",
+      { LEN_AND_STR ("symbols"), "display symbol table processing",
 	DL_DEBUG_SYMBOLS | DL_DEBUG_IMPCALLS },
-      { "bindings", "display information about symbol binding",
+      { LEN_AND_STR ("bindings"), "display information about symbol binding",
 	DL_DEBUG_BINDINGS | DL_DEBUG_IMPCALLS },
-      { "versions", "display version dependencies",
+      { LEN_AND_STR ("versions"), "display version dependencies",
 	DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
-      { "all", "all previous options combined",
+      { LEN_AND_STR ("all"), "all previous options combined",
 	DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
 	| DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
-      { "statistics", "display relocation statistics",
+      { LEN_AND_STR ("statistics"), "display relocation statistics",
 	DL_DEBUG_STATISTICS },
-      { "help", "display this help message and exit",
+      { LEN_AND_STR ("help"), "display this help message and exit",
 	DL_DEBUG_HELP },
     };
 #define ndebopts (sizeof (debopts) / sizeof (debopts[0]))
-  size_t len;
 
-#define separators " ,:"
-  do
+  /* Skip separating white spaces and commas.  */
+  while (*dl_debug != '\0')
     {
-      len = 0;
-      /* Skip separating white spaces and commas.  */
-      dl_debug += strspn (dl_debug, separators);
-      if (*dl_debug != '\0')
+      if (*dl_debug != ' ' && *dl_debug != ',' && *dl_debug != ':')
 	{
 	  size_t cnt;
+	  size_t len = 1;
 
-	  len = strcspn (dl_debug, separators);
+	  while (dl_debug[len] != '\0' && dl_debug[len] != ' '
+		 && dl_debug[len] != ',' && dl_debug[len] != ':')
+	    ++len;
 
 	  for (cnt = 0; cnt < ndebopts; ++cnt)
-	    if (strncmp (dl_debug, debopts[cnt].name, len) == 0
-		&& debopts[cnt].name[len] == '\0')
+	    if (debopts[cnt].len == len
+		&& memcmp (dl_debug, debopts[cnt].name, len) == 0)
 	      {
 		GL(dl_debug_mask) |= debopts[cnt].mask;
 		any_debug = 1;
@@ -1342,11 +1343,14 @@ process_dl_debug (const char *dl_debug)
 	      char *copy = strndupa (dl_debug, len);
 	      _dl_error_printf ("\
 warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy);
-	      break;
-	  }
+	    }
+
+	  dl_debug += len;
+	  continue;
 	}
+
+      ++dl_debug;
     }
-  while (*(dl_debug += len) != '\0');
 
   if (GL(dl_debug_mask) & DL_DEBUG_HELP)
     {
@@ -1387,7 +1391,10 @@ process_envvars (enum mode *modep)
 
   while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
     {
-      size_t len = strcspn (envline, "=");
+      size_t len = 0;
+
+      while (envline[len] != '\0' && envline[len] != '=')
+	++len;
 
       if (envline[len] != '=')
 	/* This is a "LD_" variable at the end of the string without
diff --git a/sysdeps/generic/dl-environ.c b/sysdeps/generic/dl-environ.c
index 7a3da0c4b5..e13bb5d792 100644
--- a/sysdeps/generic/dl-environ.c
+++ b/sysdeps/generic/dl-environ.c
@@ -1,5 +1,5 @@
 /* Environment handling for dynamic loader.
-   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000, 2001, 2002 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
@@ -53,23 +53,30 @@ _dl_next_ld_env_entry (char ***position)
 int
 unsetenv (const char *name)
 {
-  const size_t len = strlen (name);
   char **ep;
 
   ep = __environ;
   while (*ep != NULL)
-    if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
-      {
-	/* Found it.  Remove this pointer by moving later ones back.  */
-	char **dp = ep;
-
-	do
-	  dp[0] = dp[1];
-	while (*dp++);
-	/* Continue the loop in case NAME appears again.  */
-      }
-    else
-      ++ep;
+    {
+      size_t cnt;
+
+      while ((*ep)[cnt] == name[cnt] && name[cnt] != '\0')
+	++cnt;
+
+      if ((*ep)[cnt] == '=')
+	{
+	  /* Found it.  Remove this pointer by moving later ones to
+	     the front.  */
+	  char **dp = ep;
+
+	  do
+	    dp[0] = dp[1];
+	  while (*dp++);
+	  /* Continue the loop in case NAME appears again.  */
+	}
+      else
+	++ep;
+    }
 
   return 0;
 }