vapier      14/03/21 05:27:21

  Modified:             scanelf.c
  Log:
  rewrite which() so that it works and does not break $PATH
  
  we were walking the $PATH in reverse which it should have been forwards.  we 
were also modifying the pointer we got back from getenv() which meant any time 
we ran external code, $PATH would be truncated.  finally, we never actually 
checked the first element -- we would bail before we got a chance.

Revision  Changes    Path
1.264                pax-utils/scanelf.c

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo-projects/pax-utils/scanelf.c?rev=1.264&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo-projects/pax-utils/scanelf.c?rev=1.264&content-type=text/plain
diff : 
http://sources.gentoo.org/viewvc.cgi/gentoo-projects/pax-utils/scanelf.c?r1=1.263&r2=1.264

Index: scanelf.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v
retrieving revision 1.263
retrieving revision 1.264
diff -u -r1.263 -r1.264
--- scanelf.c   20 Mar 2014 08:08:37 -0000      1.263
+++ scanelf.c   21 Mar 2014 05:27:21 -0000      1.264
@@ -1,13 +1,13 @@
 /*
  * Copyright 2003-2012 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.263 
2014/03/20 08:08:37 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.264 
2014/03/21 05:27:21 vapier Exp $
  *
  * Copyright 2003-2012 Ned Ludd        - <so...@gentoo.org>
  * Copyright 2004-2012 Mike Frysinger  - <vap...@gentoo.org>
  */
 
-static const char rcsid[] = "$Id: scanelf.c,v 1.263 2014/03/20 08:08:37 vapier 
Exp $";
+static const char rcsid[] = "$Id: scanelf.c,v 1.264 2014/03/21 05:27:21 vapier 
Exp $";
 const char argv0[] = "scanelf";
 
 #include "paxinc.h"
@@ -70,26 +70,66 @@
 static size_t ldcache_size = 0;
 static unsigned long setpax = 0UL;
 
-static int has_objdump = 0;
+static const char *objdump;
 
 /* find the path to a file by name */
-static int bin_in_path(const char *fname)
+static const char *which(const char *fname, const char *envvar)
 {
-       char fullpath[__PAX_UTILS_PATH_MAX];
-       char *path, *p;
+       size_t path_len, fname_len;
+       const char *env_path;
+       char *path, *p, *ep;
+
+       p = getenv(envvar);
+       if (p)
+               return p;
 
-       path = getenv("PATH");
-       if (!path)
-               return 0;
+       env_path = getenv("PATH");
+       if (!env_path)
+               return NULL;
 
-       while ((p = strrchr(path, ':')) != NULL) {
-               snprintf(fullpath, sizeof(fullpath), "%s/%s", p + 1, fname);
-               *p = 0;
-               if (access(fullpath, R_OK) != -1)
-                       return 1;
+       /* Create a copy of the $PATH that we can safely modify.
+        * Make it a little bigger so we can append "/fname".
+        * We do this twice -- once for a perm copy, and once for
+        * room at the end of the last element. */
+       path_len = strlen(env_path);
+       fname_len = strlen(fname);
+       path = xmalloc(path_len + (fname_len * 2) + 2 + 2);
+       memcpy(path, env_path, path_len + 1);
+
+       p = path + path_len + 1 + fname_len + 1;
+       *p = '/';
+       memcpy(p + 1, fname, fname_len + 1);
+
+       /* Repoint fname to the copy in the env string as it has
+        * the leading slash which we can include in a single memcpy.
+        * Increase the fname len to include the '/' and '\0'. */
+       fname = p;
+       fname_len += 2;
+
+       p = path;
+       while (p) {
+               ep = strchr(p, ':');
+               /* Append the /foo path to the current element. */
+               if (ep)
+                       memcpy(ep, fname, fname_len);
+               else
+                       memcpy(path + path_len, fname, fname_len);
+
+               if (access(p, R_OK) != -1)
+                       return p;
+
+               p = ep;
+               if (ep) {
+                       /* If not the last element, restore the chunk we 
clobbered. */
+                       size_t offset = ep - path;
+                       size_t restore = min(path_len - offset, fname_len);
+                       memcpy(ep, env_path + offset, restore);
+                       ++p;
+               }
        }
 
-       return 0;
+       free(path);
+       return NULL;
 }
 
 static FILE *fopenat_r(int dir_fd, const char *path)
@@ -570,17 +610,18 @@
                        } else \
                                printf("(optimized out)"); \
                        printf(" [0x%lX]\n", (unsigned long)offset_tmp); \
-                       if (be_verbose && has_objdump) { \
+                       if (be_verbose && objdump) { \
                                Elf ## B ## _Addr end_addr = offset_tmp + 
EGET(func->st_size); \
                                char *sysbuf; \
                                size_t syslen; \
-                               const char sysfmt[] = "objdump -r -R -d -w -l 
--start-address=0x%lX --stop-address=0x%lX %s | grep --color -i -C 3 
'.*[[:space:]]%lX:[[:space:]]*R_.*'\n"; \
-                               syslen = sizeof(sysfmt) + strlen(elf->filename) 
+ 3 * sizeof(unsigned long) + 1; \
+                               const char sysfmt[] = "%s -r -R -d -w -l 
--start-address=0x%lX --stop-address=0x%lX %s | grep --color -i -C 3 
'.*[[:space:]]%lX:[[:space:]]*R_.*'\n"; \
+                               syslen = sizeof(sysfmt) + strlen(objdump) + 
strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \
                                sysbuf = xmalloc(syslen); \
                                if (end_addr < r_offset) \
                                        /* not uncommon when things are 
optimized out */ \
                                        end_addr = r_offset + 0x100; \
                                snprintf(sysbuf, syslen, sysfmt, \
+                                       objdump, \
                                        (unsigned long)offset_tmp, \
                                        (unsigned long)end_addr, \
                                        elf->filename, \
@@ -2230,7 +2271,7 @@
                }
        }
        if (show_textrels && be_verbose)
-               has_objdump = bin_in_path("objdump");
+               objdump = which("objdump", "OBJDUMP");
        /* precompile all the regexes */
        if (g_match) {
                regex_t preg;




Reply via email to