]> granicus.if.org Git - python/commitdiff
Issue #16400: Add command line option for isolated mode.
authorChristian Heimes <christian@cheimes.de>
Sat, 10 Aug 2013 14:36:18 +0000 (16:36 +0200)
committerChristian Heimes <christian@cheimes.de>
Sat, 10 Aug 2013 14:36:18 +0000 (16:36 +0200)
 -I

    Run Python in isolated mode. This also implies -E and -s. In isolated mode
    sys.path contains neither the script’s directory nor the user’s
    site-packages directory. All PYTHON* environment variables are ignored,
    too. Further restrictions may be imposed to prevent the user from
    injecting malicious code.

Doc/c-api/init.rst
Doc/using/cmdline.rst
Doc/whatsnew/3.4.rst
Include/pydebug.h
Lib/test/test_cmd_line.py
Lib/test/test_sys.py
Misc/NEWS
Misc/python.man
Modules/main.c
Python/pythonrun.c
Python/sysmodule.c

index 6f847d94e16a24fc032807c5de14e62cb6ba3be6..32007d55a9e26b6d56cd5e39be48eb39a70e015c 100644 (file)
@@ -329,7 +329,11 @@ Process-wide parameters
 
 .. c:function:: void PySys_SetArgv(int argc, wchar_t **argv)
 
-   This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set to 1.
+   This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set
+   to 1 unless the :program:`python` interpreter was started with the
+   :option:`-I`.
+
+   .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`.
 
 
 .. c:function:: void Py_SetPythonHome(wchar_t *home)
index a7273bcfee6da752f885365339a0e74a5493cade..c14f6c76e002dec743dd3c9639e040e54732e08a 100644 (file)
@@ -24,7 +24,7 @@ Command line
 
 When invoking Python, you may specify any of these options::
 
-    python [-bBdEhiOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
+    python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
 
 The most common use case is, of course, a simple invocation of a script::
 
@@ -175,6 +175,8 @@ Generic options
        Python 3.0
 
 
+.. _using-on-misc-options:
+
 Miscellaneous options
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -213,6 +215,17 @@ Miscellaneous options
    raises an exception.  See also :envvar:`PYTHONINSPECT`.
 
 
+.. cmdoption:: -I
+
+   Run Python in isolated mode. This also implies -E and -s.
+   In isolated mode :data:`sys.path` contains neither the script's directory nor
+   the user's site-packages directory. All :envvar:`PYTHON*` environment
+   variables are ignored, too. Further restrictions may be imposed to prevent
+   the user from injecting malicious code.
+
+   .. versionadded:: 3.4
+
+
 .. cmdoption:: -O
 
    Turn on basic optimizations.  This changes the filename extension for
@@ -398,7 +411,7 @@ Environment variables
 ---------------------
 
 These environment variables influence Python's behavior, they are processed
-before the command-line switches other than -E.  It is customary that
+before the command-line switches other than -E or -I.  It is customary that
 command-line switches override environmental variables where there is a
 conflict.
 
index 6011f8e30cbc97d43339e3ea1f92243534ccab06..0333c111301152d09a893c753380ced04ba43c98 100644 (file)
@@ -107,7 +107,8 @@ Significantly Improved Library Modules:
 
 Security improvements:
 
-* None yet.
+* command line option for :ref:`isolated mode <using-on-misc-options>`,
+  :issue:`16499`.
 
 Please read on for a comprehensive list of user-facing changes.
 
index 97c2f8c425703d30fa39c5106328b772d1030f3d..8fe98183f9efcf40762aa3202adccbbbcae0ed04 100644 (file)
@@ -20,6 +20,7 @@ PyAPI_DATA(int) Py_DontWriteBytecodeFlag;
 PyAPI_DATA(int) Py_NoUserSiteDirectory;
 PyAPI_DATA(int) Py_UnbufferedStdioFlag;
 PyAPI_DATA(int) Py_HashRandomizationFlag;
+PyAPI_DATA(int) Py_IsolatedFlag;
 
 /* this is a wrapper around getenv() that pays attention to
    Py_IgnoreEnvironmentFlag.  It should be used for getting variables like
index 3fa8ade4668aa19c6ad87e07a930d6a5f98eb182..efe45469ebcc9327be71e34eacd45cc965174c63 100644 (file)
@@ -4,6 +4,7 @@
 
 import test.support, unittest
 import os
+import shutil
 import sys
 import subprocess
 import tempfile
@@ -439,6 +440,31 @@ class CmdLineTest(unittest.TestCase):
         self.assertEqual(b'', out)
 
 
+    def test_isolatedmode(self):
+        self.verify_valid_flag('-I')
+        self.verify_valid_flag('-IEs')
+        rc, out, err = assert_python_ok('-I', '-c',
+            'from sys import flags as f; '
+            'print(f.no_user_site, f.ignore_environment, f.isolated)',
+            # dummyvar to prevent extranous -E
+            dummyvar="")
+        self.assertEqual(out.strip(), b'1 1 1')
+        with test.support.temp_cwd() as tmpdir:
+            fake = os.path.join(tmpdir, "uuid.py")
+            main = os.path.join(tmpdir, "main.py")
+            with open(fake, "w") as f:
+                f.write("raise RuntimeError('isolated mode test')\n")
+            with open(main, "w") as f:
+                f.write("import uuid\n")
+                f.write("print('ok')\n")
+            self.assertRaises(subprocess.CalledProcessError,
+                              subprocess.check_output,
+                              [sys.executable, main], cwd=tmpdir,
+                              stderr=subprocess.DEVNULL)
+            out = subprocess.check_output([sys.executable, "-I", main],
+                                          cwd=tmpdir)
+            self.assertEqual(out.strip(), b"ok")
+
 def test_main():
     test.support.run_unittest(CmdLineTest)
     test.support.reap_children()
index e31bbc2215ed033c1b97b90e754b047f5dda8906..65cb8ef2affe2fa1d876275812c53b5e2861f5c2 100644 (file)
@@ -515,7 +515,7 @@ class SysModuleTest(unittest.TestCase):
         attrs = ("debug",
                  "inspect", "interactive", "optimize", "dont_write_bytecode",
                  "no_user_site", "no_site", "ignore_environment", "verbose",
-                 "bytes_warning", "quiet", "hash_randomization")
+                 "bytes_warning", "quiet", "hash_randomization", "isolated")
         for attr in attrs:
             self.assertTrue(hasattr(sys.flags, attr), attr)
             self.assertEqual(type(getattr(sys.flags, attr)), int, attr)
index b0e392f8ea0fe1e002fcb572640884d017ec38d9..e7efb036582bb284b731ead86a2a134229a34422 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ Projected Release date: 2013-09-08
 Core and Builtins
 -----------------
 
+- Issue #16400: Add command line option for isolated mode.
+
 - Issue #15301: Parsing fd, uid, and gid parameters for builtins
   in Modules/posixmodule.c is now far more robust.
 
index bcb3ec87233b63e3cce8f4f7b1ff481f6803f97d..52aedee5bf0b9748180c90b994bf5b42c7825cc2 100644 (file)
@@ -26,11 +26,14 @@ python \- an interpreted, interactive, object-oriented programming language
 .B \-i
 ]
 [
-.B \-m
-.I module-name
+.B \-I
 ]
 .br
        [
+.B \-m
+.I module-name
+]
+[
 .B \-q
 ]
 [
@@ -139,6 +142,13 @@ command.  It does not read the $PYTHONSTARTUP file.  This can be
 useful to inspect global variables or a stack trace when a script
 raises an exception.
 .TP
+.B \-I
+Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-S\fP. In
+isolated mode sys.path contains neither the script’s directory nor the user’s
+site-packages directory. All PYTHON* environment variables are ignored, too.
+Further restrictions may be imposed to prevent the user from injecting
+malicious code.
+.TP
 .BI "\-m " module-name
 Searches 
 .I sys.path 
index 435bd1bfcb26b45c9c6fcce6650d0ad0a9ea2c59..25190b8e7faac535269f4afac56bdf9b643979e9 100644 (file)
@@ -43,7 +43,7 @@ static wchar_t **orig_argv;
 static int  orig_argc;
 
 /* command line options */
-#define BASE_OPTS L"bBc:dEhiJm:OqRsStuvVW:xX:?"
+#define BASE_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?"
 
 #define PROGRAM_OPTS BASE_OPTS
 
@@ -65,6 +65,7 @@ Options and arguments (and corresponding environment variables):\n\
 static char *usage_2 = "\
 -i     : inspect interactively after running script; forces a prompt even\n\
          if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
+-I     : isolate Python from the user's environment (implies -E and -s)\n\
 -m mod : run library module as a script (terminates option list)\n\
 -O     : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
 -OO    : remove doc-strings in addition to the -O optimizations\n\
@@ -426,6 +427,12 @@ Py_Main(int argc, wchar_t **argv)
             Py_InteractiveFlag++;
             break;
 
+        case 'I':
+            Py_IsolatedFlag++;
+            Py_NoUserSiteDirectory++;
+            Py_IgnoreEnvironmentFlag++;
+            break;
+
         /* case 'J': reserved for Jython */
 
         case 'O':
index 86c32068297d5580a37964cfe5eda24d23c8c72c..b0bc54964719fa256ab467e161958d6d76b5d99b 100644 (file)
@@ -112,6 +112,7 @@ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
 int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
 int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
 int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
+int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
 
 PyThreadState *_Py_Finalizing = NULL;
 
index 754bcfe654180488289666275bce0641ac23f785..72004f8a14ae2a7fa0ad892073f8a4876096d24b 100644 (file)
@@ -1369,6 +1369,7 @@ static PyStructSequence_Field flags_fields[] = {
     {"bytes_warning",           "-b"},
     {"quiet",                   "-q"},
     {"hash_randomization",      "-R"},
+    {"isolated",                "-I"},
     {0}
 };
 
@@ -1376,7 +1377,7 @@ static PyStructSequence_Desc flags_desc = {
     "sys.flags",        /* name */
     flags__doc__,       /* doc */
     flags_fields,       /* fields */
-    12
+    13
 };
 
 static PyObject*
@@ -1406,6 +1407,7 @@ make_flags(void)
     SetFlag(Py_BytesWarningFlag);
     SetFlag(Py_QuietFlag);
     SetFlag(Py_HashRandomizationFlag);
+    SetFlag(Py_IsolatedFlag);
 #undef SetFlag
 
     if (PyErr_Occurred()) {
@@ -1944,7 +1946,7 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
 void
 PySys_SetArgv(int argc, wchar_t **argv)
 {
-    PySys_SetArgvEx(argc, argv, 1);
+    PySys_SetArgvEx(argc, argv, Py_IsolatedFlag == 0);
 }
 
 /* Reimplementation of PyFile_WriteString() no calling indirectly