diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2023-12-14 12:24:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-14 12:24:24 (GMT) |
commit | 1161c14e8c68296fc465cd48970b32be9bee012e (patch) | |
tree | 369e0252cf2cb96bedefb0c891b7fbe3b0120152 | |
parent | 12f0bbd6e08bcc1e7165f2641716f7685c1db35c (diff) | |
download | cpython-1161c14e8c68296fc465cd48970b32be9bee012e.zip cpython-1161c14e8c68296fc465cd48970b32be9bee012e.tar.gz cpython-1161c14e8c68296fc465cd48970b32be9bee012e.tar.bz2 |
gh-112716: Fix SystemError when __builtins__ is not a dict (GH-112770)
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.
-rw-r--r-- | Lib/test/test_builtin.py | 26 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst | 2 | ||||
-rw-r--r-- | Python/ceval.c | 4 |
3 files changed, 30 insertions, 2 deletions
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 5e66d58..e154927 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -837,6 +837,32 @@ class BuiltinTest(unittest.TestCase): self.assertRaisesRegex(NameError, "name 'superglobal' is not defined", 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): savestdout = sys.stdout sys.stdout = None # Whatever that cannot flush() diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst new file mode 100644 index 0000000..44d6326 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst @@ -0,0 +1,2 @@ +Fix SystemError in the ``import`` statement and in ``__reduce__()`` methods +of builtin types when ``__builtins__`` is not a dict. diff --git a/Python/ceval.c b/Python/ceval.c index d92ab92..8e0be70 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2417,7 +2417,7 @@ PyObject * _PyEval_GetBuiltin(PyObject *name) { PyObject *attr; - if (PyDict_GetItemRef(PyEval_GetBuiltins(), name, &attr) == 0) { + if (PyMapping_GetOptionalItem(PyEval_GetBuiltins(), name, &attr) == 0) { PyErr_SetObject(PyExc_AttributeError, name); } return attr; @@ -2570,7 +2570,7 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name, PyObject *fromlist, PyObject *level) { PyObject *import_func; - if (PyDict_GetItemRef(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) { + if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) { return NULL; } if (import_func == NULL) { |