Skip to content

Commit 1161c14

Browse files
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.
1 parent 12f0bbd commit 1161c14

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

Lib/test/test_builtin.py

+26
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,32 @@ class customdict(dict): # this one should not do anything fancy
837837
self.assertRaisesRegex(NameError, "name 'superglobal' is not defined",
838838
exec, code, {'__builtins__': customdict()})
839839

840+
def test_eval_builtins_mapping(self):
841+
code = compile("superglobal", "test", "eval")
842+
# works correctly
843+
ns = {'__builtins__': types.MappingProxyType({'superglobal': 1})}
844+
self.assertEqual(eval(code, ns), 1)
845+
# custom builtins mapping is missing key
846+
ns = {'__builtins__': types.MappingProxyType({})}
847+
self.assertRaisesRegex(NameError, "name 'superglobal' is not defined",
848+
eval, code, ns)
849+
850+
def test_exec_builtins_mapping_import(self):
851+
code = compile("import foo.bar", "test", "exec")
852+
ns = {'__builtins__': types.MappingProxyType({})}
853+
self.assertRaisesRegex(ImportError, "__import__ not found", exec, code, ns)
854+
ns = {'__builtins__': types.MappingProxyType({'__import__': lambda *args: args})}
855+
exec(code, ns)
856+
self.assertEqual(ns['foo'], ('foo.bar', ns, ns, None, 0))
857+
858+
def test_eval_builtins_mapping_reduce(self):
859+
# list_iterator.__reduce__() calls _PyEval_GetBuiltin("iter")
860+
code = compile("x.__reduce__()", "test", "eval")
861+
ns = {'__builtins__': types.MappingProxyType({}), 'x': iter([1, 2])}
862+
self.assertRaisesRegex(AttributeError, "iter", eval, code, ns)
863+
ns = {'__builtins__': types.MappingProxyType({'iter': iter}), 'x': iter([1, 2])}
864+
self.assertEqual(eval(code, ns), (iter, ([1, 2],), 0))
865+
840866
def test_exec_redirected(self):
841867
savestdout = sys.stdout
842868
sys.stdout = None # Whatever that cannot flush()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix SystemError in the ``import`` statement and in ``__reduce__()`` methods
2+
of builtin types when ``__builtins__`` is not a dict.

Python/ceval.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2417,7 +2417,7 @@ PyObject *
24172417
_PyEval_GetBuiltin(PyObject *name)
24182418
{
24192419
PyObject *attr;
2420-
if (PyDict_GetItemRef(PyEval_GetBuiltins(), name, &attr) == 0) {
2420+
if (PyMapping_GetOptionalItem(PyEval_GetBuiltins(), name, &attr) == 0) {
24212421
PyErr_SetObject(PyExc_AttributeError, name);
24222422
}
24232423
return attr;
@@ -2570,7 +2570,7 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
25702570
PyObject *name, PyObject *fromlist, PyObject *level)
25712571
{
25722572
PyObject *import_func;
2573-
if (PyDict_GetItemRef(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) {
2573+
if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) {
25742574
return NULL;
25752575
}
25762576
if (import_func == NULL) {

0 commit comments

Comments
 (0)