Skip to content

Commit

Permalink
venv: prepend interpreter directive to argument list
Browse files Browse the repository at this point in the history
When preparing virtual environments in a file container which has
large length, the system might not be able to invoke shebang scripts
which define interpreters beyond system limits (e.x. Linux as a
limit of 128; BINPRM_BUF_SIZE [1]). This method can be used to check
if the executable is a script containing a shebang line [2]. If so,
extract the interpreter (and possible optional argument) and prepend
the values to the provided argument list. tox will only attempt to
read an interpreter directive of a maximum size of 2048 bytes to
limit excessive reading and support UNIX systems which may support a
longer interpret length.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/include/uapi/linux/binfmts.h?h=linux-4.16.y#n19
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/fs/binfmt_script.c?h=linux-4.16.y#n24

Signed-off-by: James Knight <[email protected]>
  • Loading branch information
jdknight committed May 10, 2018
1 parent ba51cfc commit e913dd3
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions tox/venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@ def _pcall(self, args, cwd, venv=True, testcommand=False,

cwd.ensure(dir=1)
args[0] = self.getcommandpath(args[0], venv, cwd)
if sys.platform != 'win32' and 'TOX_LIMITED_SHEBANG' in os.environ:
args = prepend_shebang_interpreter(args)
env = self._getenv(testcommand=testcommand)
bindir = str(self.envconfig.envbindir)
env['PATH'] = p = os.pathsep.join([bindir, os.environ["PATH"]])
Expand All @@ -415,6 +417,30 @@ def getdigest(path):
return path.computehash()


def prepend_shebang_interpreter(args):
# prepend interpreter directive (if any) to argument list
#
# When preparing virtual environments in a file container which has large
# length, the system might not be able to invoke shebang scripts which
# define interpreters beyond system limits (e.x. Linux as a limit of 128;
# BINPRM_BUF_SIZE). This method can be used to check if the executable is
# a script containing a shebang line. If so, extract the interpreter (and
# possible optional argument) and prepend the values to the provided
# argument list. tox will only attempt to read an interpreter directive of
# a maximum size of 2048 bytes to limit excessive reading and support UNIX
# systems which may support a longer interpret length.
try:
with open(args[0], 'rb') as f:
if f.read(1) == b'#' and f.read(1) == b'!':
MAXINTERP = 2048
interp = f.readline(MAXINTERP).rstrip()
interp_args = interp.split(None, 1)[:2]
return interp_args + args
except IOError:
pass
return args


@tox.hookimpl
def tox_testenv_create(venv, action):
config_interpreter = venv.getsupportedinterpreter()
Expand Down

0 comments on commit e913dd3

Please sign in to comment.