]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-34812: subprocess._args_from_interpreter_flags(): add isolated (GH-10675) (GH...
authorVictor Stinner <vstinner@redhat.com>
Fri, 23 Nov 2018 18:02:26 +0000 (19:02 +0100)
committerGitHub <noreply@github.com>
Fri, 23 Nov 2018 18:02:26 +0000 (19:02 +0100)
The "-I" command line option (run Python in isolated mode) and -X
options (like -X faulthandler) are now also copied by the
multiprocessing and distutils modules when spawning child processes.
Previously, only -E and -s options (enabled by -I) were copied.

subprocess._args_from_interpreter_flags() now copies the -I flag
and options from sys._xoptions like -X dev.

(cherry picked from commit 9de363271519e0616f4a7b59427057c4810d3acc)

Lib/subprocess.py
Lib/test/test_support.py
Misc/NEWS.d/next/Security/2018-11-23-15-00-23.bpo-34812.84VQnb.rst [new file with mode: 0644]

index 290ae44f03d761be70fcc3e7f62338e7fc971a33..8c3fa1bf9c8efd3e1122f38510321827a8e2d605 100644 (file)
@@ -232,15 +232,13 @@ def _optim_args_from_interpreter_flags():
 
 def _args_from_interpreter_flags():
     """Return a list of command-line arguments reproducing the current
-    settings in sys.flags and sys.warnoptions."""
+    settings in sys.flags, sys.warnoptions and sys._xoptions."""
     flag_opt_map = {
         'debug': 'd',
         # 'inspect': 'i',
         # 'interactive': 'i',
         'dont_write_bytecode': 'B',
-        'no_user_site': 's',
         'no_site': 'S',
-        'ignore_environment': 'E',
         'verbose': 'v',
         'bytes_warning': 'b',
         'quiet': 'q',
@@ -251,8 +249,30 @@ def _args_from_interpreter_flags():
         v = getattr(sys.flags, flag)
         if v > 0:
             args.append('-' + opt * v)
+
+    if sys.flags.isolated:
+        args.append('-I')
+    else:
+        if sys.flags.ignore_environment:
+            args.append('-E')
+        if sys.flags.no_user_site:
+            args.append('-s')
+
     for opt in sys.warnoptions:
         args.append('-W' + opt)
+
+    # -X options
+    xoptions = getattr(sys, '_xoptions', {})
+    for opt in ('faulthandler', 'tracemalloc',
+                'showalloccount', 'showrefcount', 'utf8'):
+        if opt in xoptions:
+            value = xoptions[opt]
+            if value is True:
+                arg = opt
+            else:
+                arg = '%s=%s' % (opt, value)
+            args.extend(('-X', arg))
+
     return args
 
 
index 45cdc94393eb6493c8f966e30ac492e726d51c75..adc59b6229989c56983c0d416fb1dee770de508b 100644 (file)
@@ -1,13 +1,14 @@
+import errno
 import importlib
+import os
 import shutil
+import socket
 import stat
+import subprocess
 import sys
-import os
-import unittest
-import socket
 import tempfile
 import textwrap
-import errno
+import unittest
 from test import support
 from test.support import script_helper
 
@@ -394,6 +395,65 @@ class TestSupport(unittest.TestCase):
 
         self.assertRaises(AssertionError, support.check__all__, self, unittest)
 
+    def check_options(self, args, func, expected=None):
+        code = f'from test.support import {func}; print(repr({func}()))'
+        cmd = [sys.executable, *args, '-c', code]
+        env = {key: value for key, value in os.environ.items()
+               if not key.startswith('PYTHON')}
+        proc = subprocess.run(cmd,
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.DEVNULL,
+                              universal_newlines=True,
+                              env=env)
+        if expected is None:
+            expected = args
+        self.assertEqual(proc.stdout.rstrip(), repr(expected))
+        self.assertEqual(proc.returncode, 0)
+
+    def test_args_from_interpreter_flags(self):
+        # Test test.support.args_from_interpreter_flags()
+        for opts in (
+            # no option
+            [],
+            # single option
+            ['-B'],
+            ['-s'],
+            ['-S'],
+            ['-E'],
+            ['-v'],
+            ['-b'],
+            ['-q'],
+            ['-I'],
+            # same option multiple times
+            ['-bb'],
+            ['-vvv'],
+            # -W options
+            ['-Wignore'],
+            # -X options
+            ['-X', 'faulthandler'],
+            ['-X', 'showalloccount'],
+            ['-X', 'showrefcount'],
+            ['-X', 'tracemalloc'],
+            ['-X', 'tracemalloc=3'],
+        ):
+            with self.subTest(opts=opts):
+                self.check_options(opts, 'args_from_interpreter_flags')
+
+        self.check_options(['-I', '-E', '-s'], 'args_from_interpreter_flags',
+                           ['-I'])
+
+    def test_optim_args_from_interpreter_flags(self):
+        # Test test.support.optim_args_from_interpreter_flags()
+        for opts in (
+            # no option
+            [],
+            ['-O'],
+            ['-OO'],
+            ['-OOOO'],
+        ):
+            with self.subTest(opts=opts):
+                self.check_options(opts, 'optim_args_from_interpreter_flags')
+
     def test_match_test(self):
         class Test:
             def __init__(self, test_id):
@@ -485,7 +545,6 @@ class TestSupport(unittest.TestCase):
     # reap_threads
     # reap_children
     # strip_python_stderr
-    # args_from_interpreter_flags
     # can_symlink
     # skip_unless_symlink
     # SuppressCrashReport
diff --git a/Misc/NEWS.d/next/Security/2018-11-23-15-00-23.bpo-34812.84VQnb.rst b/Misc/NEWS.d/next/Security/2018-11-23-15-00-23.bpo-34812.84VQnb.rst
new file mode 100644 (file)
index 0000000..860404f
--- /dev/null
@@ -0,0 +1,4 @@
+The :option:`-I` command line option (run Python in isolated mode) is now
+also copied by the :mod:`multiprocessing` and :mod:`distutils` modules when
+spawning child processes. Previously, only :option:`-E` and :option:`-s` options
+(enabled by :option:`-I`) were copied.