Skip to content

Commit

Permalink
Try PATHEXT in which directly
Browse files Browse the repository at this point in the history
  • Loading branch information
peace-maker committed Jan 3, 2024
1 parent 214ccbc commit 1dd5aa4
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 24 deletions.
11 changes: 2 additions & 9 deletions pwnlib/tubes/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,8 +580,6 @@ def _validate(self, cwd, executable, argv, env):
if not isinstance(executable, str):
executable = executable.decode('utf-8')

pathexts = os.environ.get('PATHEXT', '').split(os.pathsep) if sys.platform == 'win32' else []
pathexts = [''] + pathexts
path = env and env.get(b'PATH')
if path:
path = path.decode()
Expand All @@ -593,15 +591,10 @@ def _validate(self, cwd, executable, argv, env):

# If there's no path component, it's in $PATH or relative to the
# target directory.
# Try all of the file extensions in $PATHEXT on Windows too.
#
# For example, 'sh'
elif os.path.sep not in executable and any(which(executable + pathext, path=path) for pathext in pathexts):
for pathext in pathexts:
resolved_path = which(executable + pathext, path=path)
if resolved_path:
executable = resolved_path
break
elif os.path.sep not in executable and which(executable, path=path):
executable = which(executable, path=path)

# Either there is a path component, or the binary is not in $PATH
# For example, 'foo/bar' or 'bar' with cwd=='foo'
Expand Down
40 changes: 25 additions & 15 deletions pwnlib/util/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def which(name, all = False, path=None):
Works as the system command ``which``; searches $PATH for ``name`` and
returns a full path if found.
Tries all of the file extensions in $PATHEXT on Windows too.
If `all` is :const:`True` the set of all found locations is returned, else
the first occurrence or :const:`None` is returned.
Expand All @@ -160,26 +161,35 @@ def which(name, all = False, path=None):
if os.path.sep in name:
return name

isroot = False if sys.platform == 'win32' else (os.getuid() == 0)
if sys.platform == 'win32':
pathexts = os.environ.get('PATHEXT', '').split(os.pathsep)
isroot = False
else:
pathexts = []
isroot = os.getuid() == 0
pathexts = [''] + pathexts
out = set()
try:
path = path or os.environ['PATH']
except KeyError:
log.exception('Environment variable $PATH is not set')
for p in path.split(os.pathsep):
p = os.path.join(p, name)
if os.access(p, os.X_OK):
st = os.stat(p)
if not stat.S_ISREG(st.st_mode):
continue
# work around this issue: https://bugs.python.org/issue9311
if isroot and not \
st.st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
continue
if all:
out.add(p)
else:
return p
for path_part in path.split(os.pathsep):
for ext in pathexts:
nameext = name + ext
p = os.path.join(path_part, nameext)
if os.access(p, os.X_OK):
st = os.stat(p)
if not stat.S_ISREG(st.st_mode):
continue
# work around this issue: https://bugs.python.org/issue9311
if isroot and not \
st.st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
continue
if all:
out.add(p)
break
else:
return p
if all:
return out
else:
Expand Down

0 comments on commit 1dd5aa4

Please sign in to comment.