Skip to content

gh-112716: Fix SystemError when __builtins__ is not a dict #112770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 14, 2023

Conversation

serhiy-storchaka
Copy link
Member

@serhiy-storchaka serhiy-storchaka commented Dec 5, 2023

Copy link
Member

@Eclips4 Eclips4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

self.assertEqual(ns['foo'], ('foo.bar', ns, ns, None, 0))

def test_eval_builtins_mapping_reduce(self):
code = compile("iter([1, 2]).__reduce__()", "test", "eval")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test name is misleading. The test is more about getting a built-in function from custom builtins module (namespace), no?

I suggest testing that the code works as example. Such as:

code = compile("x = str(123)", "test", "exec")
ns = {}
globals = {'__builtins__': types.MappingProxyType({'str': str})}
exec(code, globals, ns)
self.assertEqual(ns['x'], "123")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's testing __reduce__ on a list iterator specifically because the implementation of __reduce__ accesses PyEval_GetBuiltins. Your test wouldn't do that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code already calls directly iter() explicitly. So it's not obvious if the expected error comes from this direct iter() call, or from the __reduce__() method call.

At least, it would be worth it to add a comment to explain these implementation details which are non obvious to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point, might be better to pass iter([1, 2]) as one of the entries in the builtins.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -2568,7 +2568,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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth adding a fast path for the case where PyDict_CheckExact(builtins)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyMapping_GetOptionalItem() already has a fast path for PyDict_CheckExact.

Backports will be more complicated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyMapping_GetOptionalItem() has a fast-path for PyDict_CheckExact(). IMO it's enough.

@@ -832,6 +832,31 @@ class customdict(dict): # this one should not do anything fancy
self.assertRaisesRegex(NameError, "name 'superglobal' is not defined",
exec, code, {'__builtins__': customdict()})

def test_exec_builtins_mapping(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add some test cases where the builtins are a subclass of dict, ensuring that an overridden __getitem__ gets used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is covered by test_exec_globals_error_on_get.

Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I just suggested to enhance test_exec_builtins_mapping() to ensure that "superglobal" value is correct.

def test_exec_builtins_mapping(self):
code = compile("superglobal", "test", "exec")
# works correctly
exec(code, {'__builtins__': types.MappingProxyType({'superglobal': 1})})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I wrote previously, I would prefer to check for the expected superglobal value here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to change also existing tests?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm only proposing to change this test.

@serhiy-storchaka serhiy-storchaka merged commit 1161c14 into python:main Dec 14, 2023
@miss-islington-app
Copy link

Thanks @serhiy-storchaka for the PR 🌮🎉.. I'm working now to backport this PR to: 3.11, 3.12.
🐍🍒⛏🤖

@serhiy-storchaka serhiy-storchaka deleted the builtins-mapping branch December 14, 2023 12:24
@miss-islington-app
Copy link

Sorry, @serhiy-storchaka, I could not cleanly backport this to 3.12 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker 1161c14e8c68296fc465cd48970b32be9bee012e 3.12

@miss-islington-app
Copy link

Sorry, @serhiy-storchaka, I could not cleanly backport this to 3.11 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker 1161c14e8c68296fc465cd48970b32be9bee012e 3.11

serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this pull request Dec 14, 2023
…ct (pythonGH-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.
(cherry picked from commit 1161c14)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
@bedevere-app
Copy link

bedevere-app bot commented Dec 14, 2023

GH-113103 is a backport of this pull request to the 3.12 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.12 only security fixes label Dec 14, 2023
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this pull request Dec 14, 2023
…ct (pythonGH-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.
(cherry picked from commit 1161c14)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
@bedevere-app
Copy link

bedevere-app bot commented Dec 14, 2023

GH-113105 is a backport of this pull request to the 3.11 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.11 only security fixes label Dec 14, 2023
@serhiy-storchaka serhiy-storchaka removed their assignment Dec 14, 2023
serhiy-storchaka added a commit that referenced this pull request Dec 14, 2023
…-112770) (GH-113103)

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 1161c14)
serhiy-storchaka added a commit that referenced this pull request Dec 14, 2023
…-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 1161c14)
corona10 pushed a commit to corona10/cpython that referenced this pull request Dec 15, 2023
…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.
aisk pushed a commit to aisk/cpython that referenced this pull request Feb 11, 2024
…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.
Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants