gh-104621: Check for Incompatible Extensions in import_find_extension() (gh-107184)
This fixes a bug where incompatible modules could still be imported if attempted multiple times.
This commit is contained in:
parent
b72947a8d2
commit
75c974f535
@ -12,7 +12,7 @@ def import_singlephase():
|
|||||||
try:
|
try:
|
||||||
import _testsinglephase
|
import _testsinglephase
|
||||||
except ImportError:
|
except ImportError:
|
||||||
sys.modules.pop('_testsinglephase')
|
sys.modules.pop('_testsinglephase', None)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
del sys.modules['_testsinglephase']
|
del sys.modules['_testsinglephase']
|
||||||
|
@ -97,7 +97,6 @@ def require_frozen(module, *, skip=True):
|
|||||||
def require_pure_python(module, *, skip=False):
|
def require_pure_python(module, *, skip=False):
|
||||||
_require_loader(module, SourceFileLoader, skip)
|
_require_loader(module, SourceFileLoader, skip)
|
||||||
|
|
||||||
|
|
||||||
def remove_files(name):
|
def remove_files(name):
|
||||||
for f in (name + ".py",
|
for f in (name + ".py",
|
||||||
name + ".pyc",
|
name + ".pyc",
|
||||||
@ -147,19 +146,34 @@ def _ready_to_import(name=None, source=""):
|
|||||||
del sys.modules[name]
|
del sys.modules[name]
|
||||||
|
|
||||||
|
|
||||||
def requires_subinterpreters(meth):
|
if _testsinglephase is not None:
|
||||||
"""Decorator to skip a test if subinterpreters are not supported."""
|
def restore__testsinglephase(*, _orig=_testsinglephase):
|
||||||
return unittest.skipIf(_interpreters is None,
|
# We started with the module imported and want to restore
|
||||||
'subinterpreters required')(meth)
|
# it to its nominal state.
|
||||||
|
_orig._clear_globals()
|
||||||
|
_testinternalcapi.clear_extension('_testsinglephase', _orig.__file__)
|
||||||
|
import _testsinglephase
|
||||||
|
|
||||||
|
|
||||||
def requires_singlephase_init(meth):
|
def requires_singlephase_init(meth):
|
||||||
"""Decorator to skip if single-phase init modules are not supported."""
|
"""Decorator to skip if single-phase init modules are not supported."""
|
||||||
|
if not isinstance(meth, type):
|
||||||
|
def meth(self, _meth=meth):
|
||||||
|
try:
|
||||||
|
return _meth(self)
|
||||||
|
finally:
|
||||||
|
restore__testsinglephase()
|
||||||
meth = cpython_only(meth)
|
meth = cpython_only(meth)
|
||||||
return unittest.skipIf(_testsinglephase is None,
|
return unittest.skipIf(_testsinglephase is None,
|
||||||
'test requires _testsinglephase module')(meth)
|
'test requires _testsinglephase module')(meth)
|
||||||
|
|
||||||
|
|
||||||
|
def requires_subinterpreters(meth):
|
||||||
|
"""Decorator to skip a test if subinterpreters are not supported."""
|
||||||
|
return unittest.skipIf(_interpreters is None,
|
||||||
|
'subinterpreters required')(meth)
|
||||||
|
|
||||||
|
|
||||||
class ModuleSnapshot(types.SimpleNamespace):
|
class ModuleSnapshot(types.SimpleNamespace):
|
||||||
"""A representation of a module for testing.
|
"""A representation of a module for testing.
|
||||||
|
|
||||||
@ -1962,6 +1976,20 @@ class SubinterpImportTests(unittest.TestCase):
|
|||||||
with self.subTest(f'{module}: strict, fresh'):
|
with self.subTest(f'{module}: strict, fresh'):
|
||||||
self.check_compatible_fresh(module, strict=True, isolated=True)
|
self.check_compatible_fresh(module, strict=True, isolated=True)
|
||||||
|
|
||||||
|
@requires_subinterpreters
|
||||||
|
@requires_singlephase_init
|
||||||
|
def test_disallowed_reimport(self):
|
||||||
|
# See https://github.com/python/cpython/issues/104621.
|
||||||
|
script = textwrap.dedent('''
|
||||||
|
import _testsinglephase
|
||||||
|
print(_testsinglephase)
|
||||||
|
''')
|
||||||
|
interpid = _interpreters.create()
|
||||||
|
with self.assertRaises(_interpreters.RunFailedError):
|
||||||
|
_interpreters.run_string(interpid, script)
|
||||||
|
with self.assertRaises(_interpreters.RunFailedError):
|
||||||
|
_interpreters.run_string(interpid, script)
|
||||||
|
|
||||||
|
|
||||||
class TestSinglePhaseSnapshot(ModuleSnapshot):
|
class TestSinglePhaseSnapshot(ModuleSnapshot):
|
||||||
|
|
||||||
@ -2017,6 +2045,10 @@ class SinglephaseInitTests(unittest.TestCase):
|
|||||||
# Start fresh.
|
# Start fresh.
|
||||||
cls.clean_up()
|
cls.clean_up()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
restore__testsinglephase()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# Clean up the module.
|
# Clean up the module.
|
||||||
self.clean_up()
|
self.clean_up()
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Unsupported modules now always fail to be imported.
|
@ -1215,6 +1215,15 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* It may have been successfully imported previously
|
||||||
|
in an interpreter that allows legacy modules
|
||||||
|
but is not allowed in the current interpreter. */
|
||||||
|
const char *name_buf = PyUnicode_AsUTF8(name);
|
||||||
|
assert(name_buf != NULL);
|
||||||
|
if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *mod, *mdict;
|
PyObject *mod, *mdict;
|
||||||
PyObject *modules = MODULES(tstate->interp);
|
PyObject *modules = MODULES(tstate->interp);
|
||||||
|
|
||||||
@ -3704,16 +3713,8 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
|
|||||||
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
mod = import_find_extension(tstate, name, path);
|
mod = import_find_extension(tstate, name, path);
|
||||||
if (mod != NULL) {
|
if (mod != NULL || _PyErr_Occurred(tstate)) {
|
||||||
const char *name_buf = PyUnicode_AsUTF8(name);
|
assert(mod == NULL || !_PyErr_Occurred(tstate));
|
||||||
assert(name_buf != NULL);
|
|
||||||
if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) {
|
|
||||||
Py_DECREF(mod);
|
|
||||||
mod = NULL;
|
|
||||||
}
|
|
||||||
goto finally;
|
|
||||||
}
|
|
||||||
else if (PyErr_Occurred()) {
|
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user