From 9f2cc06ec7bc3aca2ec62bb179fa208d2390cfae Mon Sep 17 00:00:00 2001 From: Peter Willendrup Date: Mon, 15 Jan 2024 11:11:44 +0100 Subject: [PATCH] Apply use of shlex.split (and avoid shell=true) in all tools --- tools/Python/mccodelib/cflags.py | 4 ++-- tools/Python/mccodelib/pipetools.py | 6 +++-- tools/Python/mccodelib/pqtgfrontend.py | 5 +++-- tools/Python/mccodelib/utils.py | 10 ++++----- tools/Python/mcdisplay/webgl/mcdisplay.py | 6 +++-- tools/Python/mcdoc/mcdoc.py | 16 ++++++++------ tools/Python/mcgui/mcgui.py | 27 +++++++++-------------- tools/Python/mcplot/svg/mcplot.py | 3 ++- tools/Python/mcrun/mccode.py | 2 +- 9 files changed, 40 insertions(+), 39 deletions(-) diff --git a/tools/Python/mccodelib/cflags.py b/tools/Python/mccodelib/cflags.py index a4c5a55037..943ae73b33 100644 --- a/tools/Python/mccodelib/cflags.py +++ b/tools/Python/mccodelib/cflags.py @@ -3,6 +3,7 @@ ''' import os import subprocess +import shlex import pathlib from . import mccode_config @@ -77,8 +78,7 @@ def evalfct_cmd(s): if verbose: print(f" --> launching cmd: {cmd}") returncode = 1 - with subprocess.Popen( cmd, - shell=True, + with subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE ) as proc: output = proc.communicate()[0] diff --git a/tools/Python/mccodelib/pipetools.py b/tools/Python/mccodelib/pipetools.py index 1acbdea002..91dae4ce19 100644 --- a/tools/Python/mccodelib/pipetools.py +++ b/tools/Python/mccodelib/pipetools.py @@ -4,6 +4,8 @@ ''' import re import subprocess +import shlex + from subprocess import Popen, PIPE from threading import Thread, Event import os @@ -248,13 +250,13 @@ def run(self): # os.setsid defineds a fresh process group so that the calling Python survives when the # simulation is potentially terminated. if not os.name == 'nt': - process = Popen(self.cmd, shell=True, preexec_fn=os.setsid, universal_newlines=True, + process = Popen(shlex.split(self.cmd), preexec_fn=os.setsid, universal_newlines=True, stdout=PIPE, stderr=PIPE, stdin=PIPE ) else: - process = Popen(self.cmd, shell=True, universal_newlines=True, + process = Popen(shlex.split(self.cmd), universal_newlines=True, stdout=PIPE, stderr=PIPE, stdin=PIPE diff --git a/tools/Python/mccodelib/pqtgfrontend.py b/tools/Python/mccodelib/pqtgfrontend.py index a544632067..ee5dbad6b9 100644 --- a/tools/Python/mccodelib/pqtgfrontend.py +++ b/tools/Python/mccodelib/pqtgfrontend.py @@ -5,6 +5,7 @@ import sys import math import subprocess +import shlex import numpy as np import PyQt5 @@ -309,8 +310,8 @@ def sortalpha(data): prefix = "mc" else: prefix = "mx" - subprocess.Popen(prefix+'plot-pyqtgraph %s' % - os.path.join(sourcedir, s), shell=True, cwd=os.getcwd()) + subprocess.Popen(shlex.split(prefix+'plot-pyqtgraph %s' % + os.path.join(sourcedir, s)), cwd=os.getcwd()) def clear_window_and_handlers(self): diff --git a/tools/Python/mccodelib/utils.py b/tools/Python/mccodelib/utils.py index 9b3f609758..a036a9bdff 100644 --- a/tools/Python/mccodelib/utils.py +++ b/tools/Python/mccodelib/utils.py @@ -5,6 +5,7 @@ import os from os.path import splitext, join import subprocess +import shlex from datetime import datetime ''' @@ -743,11 +744,10 @@ def run_subtool_noread(cmd, cwd=None): if not cwd: cwd = os.getcwd() try: - process = subprocess.Popen(cmd, + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, - shell=True, universal_newlines=True, cwd=cwd) process.communicate() @@ -771,11 +771,10 @@ def call_if_not_none(fct, *args): try: # open the process with all bells & whistles - process = subprocess.Popen(cmd, + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, - shell=True, universal_newlines=True, cwd=cwd) # flush until EOF @@ -803,11 +802,10 @@ def call_if_not_none(fct, *args): cwd = os.getcwd() # open the process with all bells & whistles - process = subprocess.Popen(cmd, + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, - shell=True, universal_newlines=True, cwd=cwd) diff --git a/tools/Python/mcdisplay/webgl/mcdisplay.py b/tools/Python/mcdisplay/webgl/mcdisplay.py index bf4dd9b456..2f28d40d0a 100755 --- a/tools/Python/mcdisplay/webgl/mcdisplay.py +++ b/tools/Python/mcdisplay/webgl/mcdisplay.py @@ -7,6 +7,8 @@ import logging import json import subprocess +import shlex + from pathlib import Path sys.path.append(str(Path(__file__).resolve().parent.parent.parent)) @@ -23,7 +25,7 @@ def __init__(self, templatefile, campos, box, html_filename, invcanvas): self.campos = campos self.box = box self.html_filename = html_filename - self.invcanvas = invcanvas + self.invcanvas = invcanvase def write(self): # load and modify @@ -143,7 +145,7 @@ def copy(a, b): # open a web-browser in a cross-platform way try: - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], html_filepath), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], html_filepath)) except Exception as e: raise Exception('Os-specific open browser: %s' % e.__str__()) diff --git a/tools/Python/mcdoc/mcdoc.py b/tools/Python/mcdoc/mcdoc.py index 3825dec4d3..21ef10737f 100644 --- a/tools/Python/mcdoc/mcdoc.py +++ b/tools/Python/mcdoc/mcdoc.py @@ -15,6 +15,8 @@ import os import re import subprocess +import shlex + from datetime import datetime from os.path import join, basename @@ -917,22 +919,22 @@ def main(args): if args.dir==None and args.install==False and args.searchterm==None and args.manual==False and args.comps==False and args.web==False: ''' browse system docs and exit ''' - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join(usedir,mccode_config.get_mccode_prefix()+'doc.html')), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join(usedir,mccode_config.get_mccode_prefix()+'doc.html')))) quit() elif args.manual == True: ''' open manual and exit ''' - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join(usedir,'doc','manuals',mccode_config.configuration['MCCODE']+'-manual.pdf')), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join(usedir,'doc','manuals',mccode_config.configuration['MCCODE']+'-manual.pdf')))) quit() elif args.comps == True: ''' open component manual and exit ''' - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join(usedir,'doc','manuals',mccode_config.configuration['MCCODE']+'-components.pdf')), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join(usedir,'doc','manuals',mccode_config.configuration['MCCODE']+'-components.pdf')))) quit() elif args.web == True: ''' open website and exit ''' - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], 'https://www.'+mccode_config.configuration['MCCODE']+'.org'), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], 'https://www.'+mccode_config.configuration['MCCODE']+'.org'))) quit() elif args.install == True: @@ -995,13 +997,13 @@ def main(args): info = InstrParser(f).parse() info.filepath = os.path.abspath(f) write_doc_files_or_continue([], [info], [], [f]) - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], f_html), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], f_html))) elif comp: f_html = os.path.splitext(f)[0] + ".html" info = CompParser(f).parse() info.filepath = os.path.abspath(f) write_doc_files_or_continue([info], [], [f], []) - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], f_html), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], f_html))) quit() # there were multiple matches - fall back to general search term mode else: @@ -1031,7 +1033,7 @@ def main(args): print('writing local overview doc file... %s' % mcdoc_html_filepath) write_file(mcdoc_html_filepath, text) - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join('.',mccode_config.get_mccode_prefix()+'doc.html')), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], os.path.join('.',mccode_config.get_mccode_prefix()+'doc.html')))) if __name__ == '__main__': diff --git a/tools/Python/mcgui/mcgui.py b/tools/Python/mcgui/mcgui.py index 6b62c6e388..3d99db7054 100755 --- a/tools/Python/mcgui/mcgui.py +++ b/tools/Python/mcgui/mcgui.py @@ -12,6 +12,8 @@ import time import re import pathlib +import shlex + from PyQt5 import QtCore, QtWidgets import PyQt5 try: @@ -78,13 +80,10 @@ def run(self, *args, **kwargs): if self.cmd == '': raise Exception("McRunQThread: Set cmd before running 'start'") - # open a subprocess with shell=True, otherwise stdout will be buffered and thus - # not readable live - process = subprocess.Popen(self.cmd, + process = subprocess.Popen(shlex.split(self.cmd), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, - shell=True, universal_newlines=True, cwd=self.cwd) @@ -251,10 +250,9 @@ def compileAsync(self, mpi, thread_exc_signal): cmd = mccode_config.configuration["MCRUN"] + ' -c --mpi=1 ' + nf + ' -n0 ' else: cmd = mccode_config.configuration["MCRUN"] + ' -c ' + nf + ' -n0 ' - process = subprocess.Popen(cmd, + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=True, universal_newlines=True, cwd=os.path.dirname(self.__instrFile)) self.__emitter.status('Compiling instrument via ' + mccode_config.configuration["MCRUN"]) @@ -431,7 +429,7 @@ def run(self, fixed_params, params, inspect=None): else: self.__emitter.message(runstr, gui=True) self.__emitter.status('Started simulation/trace in background shell...') - subprocess.Popen(runstr, shell=True) + subprocess.Popen(shlex.split(runstr)) def __runFinished(self, process_returncode): self.__fireSimStateUpdate() @@ -457,10 +455,9 @@ def __init__(self): # Print MCCODE version info in main window cmd = mccode_config.configuration["MCCODE"] + ' -v ' - process = subprocess.Popen(cmd, + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=True, universal_newlines=True) (stdoutdata, stderrdata) = process.communicate() @@ -750,7 +747,6 @@ def handleHelpAbout(self): process = subprocess.Popen(mccode_config.configuration["MCCODE"] +' -v', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - shell=True, universal_newlines=True) # synchronous (stdoutdata, stderrdata) = process.communicate() @@ -764,10 +760,9 @@ def handleEditInstrument(self): def handleEditExtInstrument(self): instr = self.state.getInstrumentFile() - process = subprocess.Popen(mccode_config.configuration["EDITOR"] + ' ' + os.path.basename(str(instr)), + process = subprocess.Popen(shlex.split(mccode_config.configuration["EDITOR"] + ' ' + os.path.basename(str(instr))), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - shell=True, universal_newlines=True) self.emitter.status("Editing instrument: " + os.path.basename(str(instr))) @@ -858,14 +853,14 @@ def handleMcdoc(self): cmd='%sdoc' % mccode_config.get_mccode_prefix() if sys.platform == "win32": cmd='start ' + cmd + '.bat' - subprocess.Popen(cmd, shell=True) + subprocess.Popen(shlex.split(cmd)) def handleMcdocCurrentInstr(self): cmd='%sdoc' % mccode_config.get_mccode_prefix() if sys.platform == "win32": cmd ='start ' + cmd + '.bat' cmd = cmd + ' %s' % self.state.getInstrumentFile() - subprocess.Popen(cmd, shell=True) + subprocess.Popen(shlex.split(cmd)) def handleEnvironment(self): terminal = mccode_config.configuration["TERMINAL"] @@ -875,7 +870,7 @@ def handleEnvironment(self): else: scriptfile = 'start ' + mccode_config.configuration["MCCODE_LIB_DIR"] + '\\..\\bin\\mccodego.bat' - subprocess.Popen(terminal + ' ' + scriptfile, shell=True) + subprocess.Popen(shlex.split(terminal + ' ' + scriptfile)) def handleDefault(self): reply = QtWidgets.QMessageBox.question(self.view.mw, @@ -883,7 +878,7 @@ def handleDefault(self): 'Do you want to make the current ' + mccode_config.configuration["MCCODE"] + ' the system default?'), if reply == QtWidgets.QMessageBox.Yes: - subprocess.Popen(mccode_config.configuration["MCCODE"] +'-postinst set_mccode_default', shell=True) + subprocess.Popen(shlex.split(mccode_config.configuration["MCCODE"] +'-postinst set_mccode_default')) ''' Connect UI and state callbacks diff --git a/tools/Python/mcplot/svg/mcplot.py b/tools/Python/mcplot/svg/mcplot.py index ad29c2cdb3..fe000eccd5 100644 --- a/tools/Python/mcplot/svg/mcplot.py +++ b/tools/Python/mcplot/svg/mcplot.py @@ -11,6 +11,7 @@ import base64 import json import subprocess +import shlex sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) @@ -212,7 +213,7 @@ def get_params_str_2D(data): def browse(html_filepath): # open a web-browser in a cross-platform way try: - subprocess.Popen('%s %s' % (mccode_config.configuration['BROWSER'], html_filepath), shell=True) + subprocess.Popen(shlex.split('%s %s' % (mccode_config.configuration['BROWSER'], html_filepath))) except Exception as e: raise Exception('Os-specific open browser: %s' % e.__str__()) diff --git a/tools/Python/mcrun/mccode.py b/tools/Python/mcrun/mccode.py index d2ca92914d..2b92c9dde2 100755 --- a/tools/Python/mcrun/mccode.py +++ b/tools/Python/mcrun/mccode.py @@ -65,7 +65,7 @@ def run(self, args=None, pipe=False): command = self.executable + " " + " ".join(args) LOG.debug(f'CMD: {command}') try: - proc = run(command, shell=True, check=True, text=True, capture_output=pipe) + proc = run(shlex.split(command), check=True, text=True, capture_output=pipe) LOG.debug(f"CMD: {self.executable} finished") except CalledProcessError as err: LOG.info(f"call to {self.executable} failed with {err}")