[issue41909] Segfault on __getattr__ infinite recursion on certain attribute accesses

Serhiy Storchaka report at bugs.python.org
Sat Oct 3 04:08:54 EDT 2020


Serhiy Storchaka <storchaka+cpython at gmail.com> added the comment:

Interesting, when lookup any attribute you will get a RecursionError, but this is one of only two places where the recursion check is disabled (the other one is in interning strings).

You get a crash also when call isinstance(1, instance) or issubclass(int, instance). This is the same bug.

The implementation of issubclass() calls PyObject_IsSubclass() which calls object_issubclass() which calls recursive_issubclass() which calls check_class() which calls abstract_get_bases() which looks up attribute "__bases__" which leads to infinite recursion in __getattr__().

#125278 0x000055555576116d in abstract_get_bases (cls=cls at entry=0x7fffeabcee10) at Objects/abstract.c:2340
#125279 0x00005555557611f1 in check_class (cls=cls at entry=0x7fffeabcee10, error=error at entry=0x55555585c828 "issubclass() arg 1 must be a class") at Objects/abstract.c:2396
#125280 0x00005555557619bf in recursive_issubclass (derived=derived at entry=0x7fffeabcee10, cls=cls at entry=0x555555946220 <PyLong_Type>) at Objects/abstract.c:2524
#125281 0x0000555555761daf in object_issubclass (tstate=<optimized out>, derived=0x7fffeabcee10, cls=0x555555946220 <PyLong_Type>) at Objects/abstract.c:2550
#125282 0x0000555555765ea1 in PyObject_IsSubclass (derived=<optimized out>, cls=<optimized out>) at Objects/abstract.c:2600
#125283 0x00005555557b78f3 in builtin_issubclass_impl (module=module at entry=0x7fffeae21d70, cls=<optimized out>, class_or_tuple=<optimized out>) at Python/bltinmodule.c:2511
#125284 0x00005555557b794d in builtin_issubclass (module=0x7fffeae21d70, args=0x7fffead0e388, nargs=<optimized out>) at Python/clinic/bltinmodule.c.h:828

The problem is that in abstract_get_bases() the recursion check is disabled by using macros Py_ALLOW_RECURSION/Py_END_ALLOW_RECURSION (added in 5b222135f8d2492713994f2cb003980e87ce6a72). I do not know why it was necessary. Currently tests are passed if enable recursion check, and this fixes this issue.

It is worth to mention that attribute __bases__ is looked up to support non-types in issubclass() and isinstance(). Originally it was added in issue464992 to support Zope extension ExtensionClass. I tested that the current code of ExtensionClass does not need it. So we could simplify the code and avoid recursion by just using tp_bases. But this needs wider discussion.

----------
nosy: +gvanrossum, loewis, nascheme, serhiy.storchaka
versions: +Python 3.10, Python 3.8, Python 3.9

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue41909>
_______________________________________


More information about the Python-bugs-list mailing list