Skip to content

Commit

Permalink
minted (30oct24)
Browse files Browse the repository at this point in the history
git-svn-id: svn://tug.org/texlive/trunk/Build/source@72709 c570f23f-e606-0410-a88d-b1316a301751
  • Loading branch information
kberry committed Oct 30, 2024
1 parent da46330 commit eb771e7
Showing 1 changed file with 83 additions and 75 deletions.
158 changes: 83 additions & 75 deletions texk/texlive/linked_scripts/minted/latexminted.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,11 @@
'''


__version__ = '0.1.0'
__version__ = '0.3.0'


import os
import pathlib
import platform
import shutil
import subprocess
import sys
Expand Down Expand Up @@ -140,7 +139,12 @@ def is_resolved(self) -> bool:
prohibited_path_roots.add(env_var_path)
prohibited_path_roots.add(env_var_path.resolve())

did_init_prohibited_path_roots = False
def is_permitted_executable_path(executable_path, executable_path_resolved):
global did_init_prohibited_path_roots
if not did_init_prohibited_path_roots:
did_init_prohibited_path_roots = True
init_prohibited_path_roots()
if not executable_path_resolved.is_resolved():
raise Exception('Second argument must be resolved path')
if any(e.is_relative_to(p) or p.is_relative_to(e)
Expand All @@ -154,76 +158,80 @@ def is_permitted_executable_path(executable_path, executable_path_resolved):
# https://github.com/gpoore/latexrestricted/blob/main/latexrestricted/_latex_config.py
env_SELFAUTOLOC = os.getenv('SELFAUTOLOC')
env_TEXSYSTEM = os.getenv('TEXSYSTEM')
if not env_TEXMFOUTPUT and env_SELFAUTOLOC and (not env_TEXSYSTEM or env_TEXSYSTEM.lower() != 'miktex'):
if platform.system() == 'Windows':
# Under Windows, shell escape executables will often be launched with
# the TeX Live `runscript.exe` executable wrapper. This overwrites
# `SELFAUTOLOC` from TeX with the location of the wrapper, so
# `SELFAUTOLOC` may not be correct.
which_tlmgr = shutil.which('tlmgr') # No `.exe`; likely `.bat`
if not which_tlmgr:
sys.exit('Failed to find TeX Live "tlmgr" executable on PATH')
which_tlmgr_resolved = Path(which_tlmgr).resolve()
texlive_bin_path = which_tlmgr_resolved.parent
# Make sure executable is *.exe, not *.bat or *.cmd:
# https://docs.python.org/3/library/subprocess.html#security-considerations
which_kpsewhich = shutil.which('kpsewhich.exe', path=str(texlive_bin_path))
if not which_kpsewhich:
sys.exit('Failed to find a TeX Live "tlmgr" executable with accompanying "kpsewhich" executable on PATH')
which_kpsewhich_path = Path(which_kpsewhich)
which_kpsewhich_resolved = which_kpsewhich_path.resolve()
if not texlive_bin_path == which_kpsewhich_resolved.parent:
sys.exit(' '.join([
'"tlmgr" executable from PATH resolved to "{}" '.format(which_tlmgr_resolved.as_posix()),
'while "kpsewhich" resolved to "{}";'.format(which_kpsewhich_resolved.as_posix()),
'"tlmgr" and "kpsewhich" should be in the same location',
]))
if not which_kpsewhich_resolved.name.lower().endswith('.exe'):
sys.exit(' '.join([
'Executable "kpsewhich" resolved to "{}",'.format(which_kpsewhich_resolved.as_posix()),
'but *.exe is required',
]))
else:
which_kpsewhich = shutil.which('kpsewhich', path=env_SELFAUTOLOC)
if not which_kpsewhich:
sys.exit(' '.join([
'Environment variable SELFAUTOLOC has value "{}",'.format(env_SELFAUTOLOC),
'but a "kpsewhich" executable was not found at that location',
]))
which_kpsewhich_path = Path(which_kpsewhich)
which_kpsewhich_resolved = which_kpsewhich_path.resolve()
if not is_permitted_executable_path(which_kpsewhich_path, which_kpsewhich_resolved):
# As in the latexrestricted case, this doesn't initially check for the
# TeX Live scenario where `TEXMFOUTPUT` is set in a `texmf.cnf` config
# file to a location that includes the `kpsewhich` executable. There
# isn't a good way to get the value of `TEXMFOUTPUT` without running
# `kpsewhich` in that case.
sys.exit(
'Executable "kpsewhich" is located under the current directory, TEXMFOUTPUT, or '
'TEXMF_OUTPUT_DIRECTORY, or one of these locations is under the same directory as the executable'
)
kpsewhich_cmd = [which_kpsewhich_resolved.as_posix(), '--var-value', 'TEXMFOUTPUT']
try:
kpsewhich_proc = subprocess.run(kpsewhich_cmd, shell=False, capture_output=True)
except PermissionError:
sys.exit('Insufficient permission to run "{}"'.format(which_kpsewhich_resolved.as_posix()))
kpsewhich_TEXMFOUTPUT = kpsewhich_proc.stdout.decode(sys.stdout.encoding) or None
if kpsewhich_TEXMFOUTPUT:
kpsewhich_TEXMFOUTPUT_path = Path(kpsewhich_TEXMFOUTPUT)
prohibited_path_roots.add(kpsewhich_TEXMFOUTPUT_path)
prohibited_path_roots.add(kpsewhich_TEXMFOUTPUT_path.resolve())
if not is_permitted_executable_path(which_kpsewhich_path, which_kpsewhich_resolved):
# It is now possible to check for the TeX Live scenario where
# `TEXMFOUTPUT` is set in a `texmf.cnf` config file to a location that
# includes the `kpsewhich` executable. Giving an error message after
# already running `kpsewhich` isn't ideal, but there isn't a good
# alternative. As in the latexrestricted case, the impact on overall
# security is negligible because an unsafe value of `TEXMFOUTPUT`
# means that all TeX-related executables are potentially compromised.
sys.exit(
'Executable "kpsewhich" is located under the current directory, TEXMFOUTPUT, or '
'TEXMF_OUTPUT_DIRECTORY, or one of these locations is under the same directory as the executable'
)
def init_prohibited_path_roots():
if not env_TEXMFOUTPUT and env_SELFAUTOLOC and (not env_TEXSYSTEM or env_TEXSYSTEM.lower() != 'miktex'):
if sys.platform == 'win32':
# Under Windows, shell escape executables will often be launched
# with the TeX Live `runscript.exe` executable wrapper. This
# overwrites `SELFAUTOLOC` from TeX with the location of the
# wrapper, so `SELFAUTOLOC` may not be correct.
which_tlmgr = shutil.which('tlmgr') # No `.exe`; likely `.bat`
if not which_tlmgr:
sys.exit('Failed to find TeX Live "tlmgr" executable on PATH')
which_tlmgr_resolved = Path(which_tlmgr).resolve()
texlive_bin_path = which_tlmgr_resolved.parent
# Make sure executable is *.exe, not *.bat or *.cmd:
# https://docs.python.org/3/library/subprocess.html#security-considerations
which_kpsewhich = shutil.which('kpsewhich.exe', path=str(texlive_bin_path))
if not which_kpsewhich:
sys.exit(
'Failed to find a TeX Live "tlmgr" executable with accompanying "kpsewhich" executable on PATH'
)
which_kpsewhich_path = Path(which_kpsewhich)
which_kpsewhich_resolved = which_kpsewhich_path.resolve()
if not texlive_bin_path == which_kpsewhich_resolved.parent:
sys.exit(' '.join([
'"tlmgr" executable from PATH resolved to "{}" '.format(which_tlmgr_resolved.as_posix()),
'while "kpsewhich" resolved to "{}";'.format(which_kpsewhich_resolved.as_posix()),
'"tlmgr" and "kpsewhich" should be in the same location',
]))
if not which_kpsewhich_resolved.name.lower().endswith('.exe'):
sys.exit(' '.join([
'Executable "kpsewhich" resolved to "{}",'.format(which_kpsewhich_resolved.as_posix()),
'but *.exe is required',
]))
else:
which_kpsewhich = shutil.which('kpsewhich', path=env_SELFAUTOLOC)
if not which_kpsewhich:
sys.exit(' '.join([
'Environment variable SELFAUTOLOC has value "{}",'.format(env_SELFAUTOLOC),
'but a "kpsewhich" executable was not found at that location',
]))
which_kpsewhich_path = Path(which_kpsewhich)
which_kpsewhich_resolved = which_kpsewhich_path.resolve()
if not is_permitted_executable_path(which_kpsewhich_path, which_kpsewhich_resolved):
# As in the latexrestricted case, this doesn't initially check for
# the TeX Live scenario where `TEXMFOUTPUT` is set in a
# `texmf.cnf` config file to a location that includes the
# `kpsewhich` executable. There isn't a good way to get the value
# of `TEXMFOUTPUT` without running `kpsewhich` in that case.
sys.exit(
'Executable "kpsewhich" is located under the current directory, TEXMFOUTPUT, or '
'TEXMF_OUTPUT_DIRECTORY, or one of these locations is under the same directory as the executable'
)
kpsewhich_cmd = [which_kpsewhich_resolved.as_posix(), '--var-value', 'TEXMFOUTPUT']
try:
kpsewhich_proc = subprocess.run(kpsewhich_cmd, shell=False, capture_output=True)
except PermissionError:
sys.exit('Insufficient permission to run "{}"'.format(which_kpsewhich_resolved.as_posix()))
kpsewhich_TEXMFOUTPUT = kpsewhich_proc.stdout.strip().decode(sys.stdout.encoding) or None
if kpsewhich_TEXMFOUTPUT:
kpsewhich_TEXMFOUTPUT_path = Path(kpsewhich_TEXMFOUTPUT)
prohibited_path_roots.add(kpsewhich_TEXMFOUTPUT_path)
prohibited_path_roots.add(kpsewhich_TEXMFOUTPUT_path.resolve())
if not is_permitted_executable_path(which_kpsewhich_path, which_kpsewhich_resolved):
# It is now possible to check for the TeX Live scenario where
# `TEXMFOUTPUT` is set in a `texmf.cnf` config file to a location
# that includes the `kpsewhich` executable. Giving an error
# message after already running `kpsewhich` isn't ideal, but there
# isn't a good alternative. As in the latexrestricted case, the
# impact on overall security is negligible because an unsafe value
# of `TEXMFOUTPUT` means that all TeX-related executables are
# potentially compromised.
sys.exit(
'Executable "kpsewhich" is located under the current directory, TEXMFOUTPUT, or '
'TEXMF_OUTPUT_DIRECTORY, or one of these locations is under the same directory as the executable'
)



Expand All @@ -232,7 +240,7 @@ def is_permitted_executable_path(executable_path, executable_path_resolved):
# relaunch this script with that Python version in a subprocess.
if sys.version_info[:2] < (3, 8):
for minor_version in range(13, 7, -1):
if platform.system() == 'Windows':
if sys.platform == 'win32':
# Batch files must be prohibited:
# https://docs.python.org/3/library/subprocess.html#security-considerations
which_python = shutil.which('python3.{}.exe'.format(minor_version))
Expand All @@ -241,7 +249,7 @@ def is_permitted_executable_path(executable_path, executable_path_resolved):
if which_python:
which_python_path = Path(which_python)
which_python_resolved = which_python_path.resolve()
if platform.system() == 'Windows' and not which_python_resolved.name.lower().endswith('.exe'):
if sys.platform == 'win32' and not which_python_resolved.name.lower().endswith('.exe'):
continue
if is_permitted_executable_path(which_python_path, which_python_resolved):
python_cmd = [which_python_resolved.as_posix(), __file__] + sys.argv[1:]
Expand Down Expand Up @@ -282,7 +290,7 @@ def is_permitted_executable_path(executable_path, executable_path_resolved):
# endless recursion of subprocesses in the event that a `latexminted`
# executable *inside* a TeX installation somehow manages to pass the tests for
# an executable *outside* a TeX installation.
if platform.system() == 'Windows' and not os.getenv('LATEXMINTED_SUBPROCESS'):
if sys.platform == 'win32' and not os.getenv('LATEXMINTED_SUBPROCESS'):
os.environ['LATEXMINTED_SUBPROCESS'] = '1'
fallback_path_search = True
if env_SELFAUTOLOC:
Expand Down

0 comments on commit eb771e7

Please sign in to comment.