[Python-checkins] cpython: Close #15386: There was a loophole that meant importlib.machinery and imp would

nick.coghlan python-checkins at python.org
Fri Jul 20 15:40:20 CEST 2012


http://hg.python.org/cpython/rev/4431dc4bb770
changeset:   78195:4431dc4bb770
user:        Nick Coghlan <ncoghlan at gmail.com>
date:        Fri Jul 20 23:40:09 2012 +1000
summary:
  Close #15386: There was a loophole that meant importlib.machinery and imp would sometimes reference an uninitialised copy of importlib._bootstrap

files:
  Lib/importlib/__init__.py |  13 +++++++++++--
  Lib/pkgutil.py            |   2 +-
  Lib/runpy.py              |   2 +-
  Lib/test/regrtest.py      |   3 +++
  Lib/test/test_import.py   |  12 +++++++++++-
  5 files changed, 27 insertions(+), 5 deletions(-)


diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py
--- a/Lib/importlib/__init__.py
+++ b/Lib/importlib/__init__.py
@@ -2,14 +2,21 @@
 __all__ = ['__import__', 'import_module', 'invalidate_caches']
 
 # Bootstrap help #####################################################
-import imp
+
+# Until bootstrapping is complete, DO NOT import any modules that attempt
+# to import importlib._bootstrap (directly or indirectly). Since this
+# partially initialised package would be present in sys.modules, those
+# modules would get an uninitialised copy of the source version, instead
+# of a fully initialised version (either the frozen one or the one
+# initialised below if the frozen one is not available).
+import _imp  # Just the builtin component, NOT the full Python module
 import sys
 
 try:
     import _frozen_importlib as _bootstrap
 except ImportError:
     from . import _bootstrap
-    _bootstrap._setup(sys, imp)
+    _bootstrap._setup(sys, _imp)
 else:
     # importlib._bootstrap is the built-in import, ensure we don't create
     # a second copy of the module.
@@ -22,6 +29,8 @@
 _w_long = _bootstrap._w_long
 _r_long = _bootstrap._r_long
 
+# Fully bootstrapped at this point, import whatever you like, circular
+# dependencies and startup overhead minimisation permitting :)
 
 # Public API #########################################################
 
diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py
--- a/Lib/pkgutil.py
+++ b/Lib/pkgutil.py
@@ -2,8 +2,8 @@
 
 import os
 import sys
+import importlib
 import imp
-import importlib
 import os.path
 from warnings import warn
 from types import ModuleType
diff --git a/Lib/runpy.py b/Lib/runpy.py
--- a/Lib/runpy.py
+++ b/Lib/runpy.py
@@ -12,8 +12,8 @@
 
 import os
 import sys
+import importlib.machinery # importlib first so we can test #15386 via -m
 import imp
-import importlib.machinery
 from pkgutil import read_code, get_loader, get_importer
 
 __all__ = [
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -165,6 +165,9 @@
 option '-uall,-gui'.
 """
 
+# We import importlib *ASAP* in order to test #15386
+import importlib
+
 import builtins
 import faulthandler
 import getopt
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -1,8 +1,9 @@
+# We import importlib *ASAP* in order to test #15386
+import importlib
 import builtins
 import imp
 from importlib.test.import_ import test_suite as importlib_import_test_suite
 from importlib.test.import_ import util as importlib_util
-import importlib
 import marshal
 import os
 import platform
@@ -777,6 +778,15 @@
         self.assertEqual(mod.__package__, 'importlib')
         self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__)
 
+    def test_there_can_be_only_one(self):
+        # Issue #15386 revealed a tricky loophole in the bootstrapping
+        # This test is technically redundant, since the bug caused importing
+        # this test module to crash completely, but it helps prove the point
+        from importlib import machinery
+        mod = sys.modules['_frozen_importlib']
+        self.assertIs(machinery.FileFinder, mod.FileFinder)
+        self.assertIs(imp.new_module, mod.new_module)
+
 
 class ImportTracebackTests(unittest.TestCase):
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list