This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Three argument type() super call sets __name__ but not __qualname__
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.3, Python 3.4
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: barry, iritkatriel, ncoghlan, pitrou, zkrynicki
Priority: normal Keywords:

Created on 2013-12-04 22:06 by zkrynicki, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue-19888.py32.py zkrynicki, 2013-12-04 22:06 3.2 test program
issue-19888.py27.py zkrynicki, 2013-12-04 22:10 2.7 test program
qualname-19888.py barry, 2013-12-06 01:18
Messages (14)
msg205250 - (view) Author: Zygmunt Krynicki (zkrynicki) Date: 2013-12-04 22:06
It seems that a particular code sequence causes memory corruption (but not a crash so far) in the interpreter. I've attached a test case that fails assertion on python3.2 (tested on current amd64 12.04 builds) and works on python3.3 (tested on current amd64 14.04 builds and i386 fedora 19 builds).

The attached test program shows how the bug is actually triggered by using a for loop to iterate over key, value in namespace.items() inside a metaclass __new__() method that does nothing else apart from that.
msg205251 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-12-04 22:08
Note that just iterating over namespace doesn't trigger the problem, e.g. instead of 

    for name, value in namespace.items(): pass

using

    list(namespace.items())

seems to work.
msg205252 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-12-04 22:10
Also seems to be triggered on 2.7 (with appropriate syntax adjustments in bug.py)
msg205253 - (view) Author: Zygmunt Krynicki (zkrynicki) Date: 2013-12-04 22:10
2.7 test program
msg205254 - (view) Author: Zygmunt Krynicki (zkrynicki) Date: 2013-12-04 22:20
Experimenting with a few modifications lead to the following observations:

1) objects with short names (defined inside the Obj class) tend to be ignored and don't trigger the bug
2) Longer names tend to trigger the bug, ordering is not deterministic
3) Calling __new__ before iterating over namespace makes the problem go away, it seems to be related to the for loop more than to anything else
msg205255 - (view) Author: Zygmunt Krynicki (zkrynicki) Date: 2013-12-04 22:22
This is not a bug, name spills out of for ... loop and then gets passed to __new__
msg205257 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-12-04 22:28
D'oh! Should have looked closer. ;)
msg205260 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-12-04 23:01
At best, this is an undocumented (afaict) change in behavior in 3.3.  Let's boil it down:

-----snip snip-----
class Type(type):
    def __new__(mcls, name, bases, namespace):
        return super().__new__(mcls, 'foo', bases, namespace)

class Obj(metaclass=Type):
    def __init__(self, **kwargs):
        pass

print(repr(Obj))
-----snip snip-----

In <= 3.2, this prints <class '__main__.foo'>

In >= 3.3 this prints <class '__main__.Obj'>

So, clearly this is a change in behavior.  Was it intended?  If so, it's undocumented - I can find no mention of it in Misc/NEWS or What's New in 3.3.  I suspect it is unintended.
msg205265 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-12-05 00:28
Barry: that's because __name__ is 'foo' while __qualname__ is 'Obj'.

I'm gonna close the bug, since it's invalid.
msg205266 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-12-05 00:29
(you can open a new issue for the __name__ / __qualname__ discrepancy, though)
msg205342 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-12-06 01:17
I don't see the value in opening a new bug.  Now that we understand what's going on, let's just repurpose and retitle this one.

Run qualname-19888.py with Python 3.3 and you'll get:

Obj.__name__ foo
Obj.__qualname__ Obj
repr(Obj) <class '__main__.Obj'>

And with 3.2:

Obj.__name__ foo
repr(Obj) <class '__main__.foo'>

The primary discrepancy (and relevant visible regression) is in the repr of Obj.
msg205417 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-12-07 00:12
Ok, then it's no security issue at all :)
msg205426 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2013-12-07 00:52
Oops, correct!
msg408029 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-12-08 15:57
This is about documenting a difference between 3.2 and 3.3, so I'm assuming it's no longer relevant.
History
Date User Action Args
2022-04-11 14:57:55adminsetgithub: 64087
2021-12-13 19:22:07iritkatrielsetstatus: pending -> closed
stage: resolved
2021-12-08 15:57:27iritkatrielsetstatus: open -> pending

nosy: + iritkatriel
messages: + msg408029

resolution: out of date
2013-12-07 00:52:23barrysetmessages: + msg205426
2013-12-07 00:12:01pitrousettype: security -> behavior
messages: + msg205417
2013-12-06 01:18:15barrysetfiles: + qualname-19888.py
2013-12-06 01:17:57barrysetstatus: closed -> open


title: type.__new__() name argument is ignored -> Three argument type() super call sets __name__ but not __qualname__
nosy: + ncoghlan
versions: - Python 2.7, Python 3.2
messages: + msg205342
resolution: not a bug -> (no value)
2013-12-05 01:59:52benjamin.petersonsetstatus: open -> closed
2013-12-05 00:29:15pitrousetmessages: + msg205266
2013-12-05 00:28:32pitrousetresolution: not a bug

messages: + msg205265
nosy: + pitrou
2013-12-05 00:24:34pitrousetversions: + Python 2.7, Python 3.2
2013-12-04 23:01:17barrysetversions: + Python 3.3, Python 3.4, - Python 2.7, Python 3.2
2013-12-04 23:01:11barrysetmessages: + msg205260
2013-12-04 22:58:15barrysetstatus: closed -> open
resolution: not a bug -> (no value)
2013-12-04 22:58:05barrysettitle: possible memory corruption caused by for-loop iteration over namespace.items() in a metaclass defining __new__ -> type.__new__() name argument is ignored
2013-12-04 22:28:13barrysetmessages: + msg205257
2013-12-04 22:24:06zkrynickisetstatus: open -> closed
resolution: not a bug
2013-12-04 22:22:25zkrynickisetmessages: + msg205255
2013-12-04 22:20:26zkrynickisetmessages: + msg205254
2013-12-04 22:10:55zkrynickisetfiles: + issue-19888.py27.py

messages: + msg205253
2013-12-04 22:10:17barrysetmessages: + msg205252
versions: + Python 2.7
2013-12-04 22:08:22barrysetmessages: + msg205251
2013-12-04 22:06:52barrysetnosy: + barry
2013-12-04 22:06:07zkrynickicreate