diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | elf/dl-load.c | 60 | ||||
-rw-r--r-- | elf/rtld.c | 55 | ||||
-rw-r--r-- | sysdeps/generic/dl-environ.c | 35 |
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; } |