Skip to content

Commit

Permalink
pythongh-112716: Fix SystemError when __builtins__ is not a dict (pyt…
Browse files Browse the repository at this point in the history
…honGH-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.
  • Loading branch information
serhiy-storchaka authored Dec 14, 2023
1 parent 12f0bbd commit 1161c14
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
26 changes: 26 additions & 0 deletions Lib/test/test_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,32 @@ class customdict(dict): # this one should not do anything fancy
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()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix SystemError in the ``import`` statement and in ``__reduce__()`` methods
of builtin types when ``__builtins__`` is not a dict.
4 changes: 2 additions & 2 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 1161c14

Please sign in to comment.