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
type_new() removes __qualname__ from the input dictionary #58303
Comments
The C function type_new() creates a copy the dictionary for __dict__ and modifies the copy... except for __qualname__: it does modify the input dictionary before the copy. def f(): pass
d = {'__qualname__': 42, '__new__': f}
assert d['__new__'] is f
assert '__qualname__' in d
Enum = type.__new__(type, 'Enum', (), d)
assert d['__new__'] is f
assert '__qualname__' in d I don't know if it is expected. If not, the copy should be done before. |
I get a segfault with Python 3.3.0a0 (default:31784350f849, Feb 23 2012, 11:07:41)
[GCC 4.5.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'__qualname__':'XXX'}
>>> T = type('foo', (), d)
>>> d
Segmentation fault On Windows I also get a crash. Wierdly, if I replace 'XXX' by 'foo', Python 3.3.0a0 (default:31784350f849, Feb 23 2012, 11:07:41)
[GCC 4.5.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'__qualname__':'foo'}
>>> T = type('foo', (), d)
>>> d
{} |
Here is a patch. |
I can reproduce the segfault on F16: Python 3.3.0a0 (default:3828d93fd330, Feb 23 2012, 13:49:57)
[GCC 4.4.6] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'__qualname__':'XXX'}
[66934 refs]
>>> T = type('foo', (), d)
[66956 refs]
>>> T
python: Objects/unicodeobject.c:301: _PyUnicode_CheckConsistency: Assertion `((((((PyObject*)(op))->ob_type))->tp_flags & ((1L<<28))) != 0)' failed.
Aborted (core dumped) The patch looks mostly OK, but I can still segfault the interpreter by using a '__qualname__' of 'None': Python 3.3.0a0 (default:3828d93fd330+, Feb 23 2012, 13:55:57)
[GCC 4.4.6] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'__qualname__':'XXX'}
[67128 refs]
>>> T = type('foo', (), d)
[67156 refs]
>>> T
<class '__main__.XXX'>
[67161 refs]
>>> d = {'__qualname__': None}
[67161 refs]
>>> T = type('foo', (), d)
[67185 refs]
>>> T
python: Objects/unicodeobject.c:301: _PyUnicode_CheckConsistency: Assertion `((((((PyObject*)(op))->ob_type))->tp_flags & ((1L<<28))) != 0)' failed.
Aborted (core dumped) Try this additional unit test: d = {'__qualname__': None}
tp = type('foo', (), d)
self.assertEqual(tp.__qualname__, None)
self.assertEqual(tp.__dict__['__qualname__'], None)
self.assertEqual(d, {'__qualname__': None})
self.assertTrue(repr(tp)) |
Oh, I also wrote a patch :-) My patch fixes this issue but also many memory leaks in error cases.
I can reproduce the crash, but only with Python compiled in release mode (not with Python compiled in debug mode). |
haypo, I can reproduce the segfault using the 'None' test case on your patch as well. |
I merged the two patches (qualname_dict.patch and type_new.patch) and added a fix for non-string __qualname__ => type_new-2.patch. |
The change in error handling makes this a bit harder to review, but it otherwise looks OK if this is the intended behavior. I am not sure that it is. The original version:
Why (1) was done I don't know. (2) is obviously a bug. The patched version:
The deletion and unitiliazed slot problems are gone, but I am not sure if (2) is needed. Just fixing (1) and (3) seems more reasonable to me. |
New changeset b83ae75beaca by Victor Stinner in branch 'default': |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: