mirror of
https://github.com/python/cpython.git
synced 2025-07-08 03:45:36 +00:00
[3.11] gh-112716: Fix SystemError when __builtins__ is not a dict (GH-112770) (GH-113105)
It was raised in two cases:
* in the import statement when looking up __import__
* in pickling some builtin type when looking up built-ins iter, getattr, etc.
(cherry picked from commit 1161c14e8c
)
This commit is contained in:
parent
08ff6fa23d
commit
d4234937a1
3 changed files with 33 additions and 9 deletions
|
@ -798,6 +798,32 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertRaisesRegex(NameError, "name 'superglobal' is not defined",
|
self.assertRaisesRegex(NameError, "name 'superglobal' is not defined",
|
||||||
exec, code, {'__builtins__': customdict()})
|
exec, code, {'__builtins__': customdict()})
|
||||||
|
|
||||||
|
def test_eval_builtins_mapping(self):
|
||||||
|
code = compile("superglobal", "test", "eval")
|
||||||
|
# works correctly
|
||||||
|
ns = {'__builtins__': types.MappingProxyType({'superglobal': 1})}
|
||||||
|
self.assertEqual(eval(code, ns), 1)
|
||||||
|
# custom builtins mapping is missing key
|
||||||
|
ns = {'__builtins__': types.MappingProxyType({})}
|
||||||
|
self.assertRaisesRegex(NameError, "name 'superglobal' is not defined",
|
||||||
|
eval, code, ns)
|
||||||
|
|
||||||
|
def test_exec_builtins_mapping_import(self):
|
||||||
|
code = compile("import foo.bar", "test", "exec")
|
||||||
|
ns = {'__builtins__': types.MappingProxyType({})}
|
||||||
|
self.assertRaisesRegex(ImportError, "__import__ not found", exec, code, ns)
|
||||||
|
ns = {'__builtins__': types.MappingProxyType({'__import__': lambda *args: args})}
|
||||||
|
exec(code, ns)
|
||||||
|
self.assertEqual(ns['foo'], ('foo.bar', ns, ns, None, 0))
|
||||||
|
|
||||||
|
def test_eval_builtins_mapping_reduce(self):
|
||||||
|
# list_iterator.__reduce__() calls _PyEval_GetBuiltin("iter")
|
||||||
|
code = compile("x.__reduce__()", "test", "eval")
|
||||||
|
ns = {'__builtins__': types.MappingProxyType({}), 'x': iter([1, 2])}
|
||||||
|
self.assertRaisesRegex(AttributeError, "iter", eval, code, ns)
|
||||||
|
ns = {'__builtins__': types.MappingProxyType({'iter': iter}), 'x': iter([1, 2])}
|
||||||
|
self.assertEqual(eval(code, ns), (iter, ([1, 2],), 0))
|
||||||
|
|
||||||
def test_exec_redirected(self):
|
def test_exec_redirected(self):
|
||||||
savestdout = sys.stdout
|
savestdout = sys.stdout
|
||||||
sys.stdout = None # Whatever that cannot flush()
|
sys.stdout = None # Whatever that cannot flush()
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix SystemError in the ``import`` statement and in ``__reduce__()`` methods
|
||||||
|
of builtin types when ``__builtins__`` is not a dict.
|
|
@ -7153,11 +7153,8 @@ PyObject *
|
||||||
_PyEval_GetBuiltin(PyObject *name)
|
_PyEval_GetBuiltin(PyObject *name)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
PyObject *attr = PyDict_GetItemWithError(PyEval_GetBuiltins(), name);
|
PyObject *attr = PyObject_GetItem(PyEval_GetBuiltins(), name);
|
||||||
if (attr) {
|
if (attr == NULL && _PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||||
Py_INCREF(attr);
|
|
||||||
}
|
|
||||||
else if (!_PyErr_Occurred(tstate)) {
|
|
||||||
_PyErr_SetObject(tstate, PyExc_AttributeError, name);
|
_PyErr_SetObject(tstate, PyExc_AttributeError, name);
|
||||||
}
|
}
|
||||||
return attr;
|
return attr;
|
||||||
|
@ -7407,9 +7404,9 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
PyObject *import_func, *res;
|
PyObject *import_func, *res;
|
||||||
PyObject* stack[5];
|
PyObject* stack[5];
|
||||||
|
|
||||||
import_func = _PyDict_GetItemWithError(frame->f_builtins, &_Py_ID(__import__));
|
import_func = PyObject_GetItem(frame->f_builtins, &_Py_ID(__import__));
|
||||||
if (import_func == NULL) {
|
if (import_func == NULL) {
|
||||||
if (!_PyErr_Occurred(tstate)) {
|
if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||||
_PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found");
|
_PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found");
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -7417,6 +7414,7 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
PyObject *locals = frame->f_locals;
|
PyObject *locals = frame->f_locals;
|
||||||
/* Fast path for not overloaded __import__. */
|
/* Fast path for not overloaded __import__. */
|
||||||
if (import_func == tstate->interp->import_func) {
|
if (import_func == tstate->interp->import_func) {
|
||||||
|
Py_DECREF(import_func);
|
||||||
int ilevel = _PyLong_AsInt(level);
|
int ilevel = _PyLong_AsInt(level);
|
||||||
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -7430,8 +7428,6 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(import_func);
|
|
||||||
|
|
||||||
stack[0] = name;
|
stack[0] = name;
|
||||||
stack[1] = frame->f_globals;
|
stack[1] = frame->f_globals;
|
||||||
stack[2] = locals == NULL ? Py_None : locals;
|
stack[2] = locals == NULL ? Py_None : locals;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue