summary refs log tree commit diff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c60
1 files changed, 36 insertions, 24 deletions
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
 	{