fix ldso reserved library name handling
authorSzabolcs Nagy <nsz@port70.net>
Tue, 1 Nov 2016 01:49:09 +0000 (02:49 +0100)
committerRich Felker <dalias@aerifal.cx>
Mon, 7 Nov 2016 17:00:32 +0000 (12:00 -0500)
If a DT_NEEDED entry was the prefix of a reserved library name
(up to the first dot) then it was incorrectly treated as a libc
reserved name.

e.g. libp.so dependency was not loaded as it matched libpthread
reserved name.

ldso/dynlink.c

index d11776d..acb73bc 100644 (file)
@@ -906,27 +906,27 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
        /* Catch and block attempts to reload the implementation itself */
        if (name[0]=='l' && name[1]=='i' && name[2]=='b') {
                static const char reserved[] =
-                       "c\0pthread\0rt\0m\0dl\0util\0xnet\0";
-               const char *rp;
-               char *z = strchr(name, '.');
-               if (z) {
-                       size_t l = z-name;
-                       for (rp=reserved; *rp && strncmp(name+3, rp, l-3); rp+=strlen(rp)+1);
-                       if (*rp) {
-                               if (ldd_mode) {
-                                       /* Track which names have been resolved
-                                        * and only report each one once. */
-                                       static unsigned reported;
-                                       unsigned mask = 1U<<(rp-reserved);
-                                       if (!(reported & mask)) {
-                                               reported |= mask;
-                                               dprintf(1, "\t%s => %s (%p)\n",
-                                                       name, ldso.name,
-                                                       ldso.base);
-                                       }
+                       "c.pthread.rt.m.dl.util.xnet.";
+               const char *rp, *next;
+               for (rp=reserved; *rp; rp=next) {
+                       next = strchr(rp, '.') + 1;
+                       if (strncmp(name+3, rp, next-rp) == 0)
+                               break;
+               }
+               if (*rp) {
+                       if (ldd_mode) {
+                               /* Track which names have been resolved
+                                * and only report each one once. */
+                               static unsigned reported;
+                               unsigned mask = 1U<<(rp-reserved);
+                               if (!(reported & mask)) {
+                                       reported |= mask;
+                                       dprintf(1, "\t%s => %s (%p)\n",
+                                               name, ldso.name,
+                                               ldso.base);
                                }
-                               is_self = 1;
                        }
+                       is_self = 1;
                }
        }
        if (!strcmp(name, ldso.name)) is_self = 1;