enthought / enthought/traits

Recursive "DelegatesTo" causes stack overflow.

Open
#204 0 comments 0 reactions 0 assignees View on GitHub
type: bug
Dominant language
Python
Stars
462
Forks
90
PR merge metrics
No merged PRs in 30d

Description

Found in a moment of stupidity:

```
(Canopy 64bit) taniyama:Desktop mdickinson$ python
Enthought Canopy Python 2.7.6 | 64-bit | (default, Jun 4 2014, 16:42:26)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from traits.api import *
>>> class RecursiveDelegate(HasTraits):
... xmax = DelegatesTo('xmax')
...
>>> RecursiveDelegate()
Segmentation fault: 11
```

The same effect can be achieved with a mutually recursive definition:

```
(Canopy 64bit) taniyama:Desktop mdickinson$ python
Enthought Canopy Python 2.7.6 | 64-bit | (default, Jun 4 2014, 16:42:26)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from traits.api import *
>>> class MutuallyRecursiveDelegates(HasTraits):
... foo = DelegatesTo('bar')
... bar = DelegatesTo('foo')
...
>>> MutuallyRecursiveDelegates()
Segmentation fault: 11
```

The crash report that OS X generates clearly shows the recursion and resulting stack overflow in `ctraits`:

```
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 org.python.python 0x000000010005768b lookdict_string + 27
1 ctraits.so 0x00000001005ed1a4 Py2to3_GetAttrDictValue + 228
2 ctraits.so 0x00000001005ee45f has_traits_getattro + 47
3 ctraits.so 0x00000001005ee75d getattr_delegate + 349
4 ctraits.so 0x00000001005ee75d getattr_delegate + 349
5 ctraits.so 0x00000001005ee75d getattr_delegate + 349
6 ctraits.so 0x00000001005ee75d getattr_delegate + 349
7 ctraits.so 0x00000001005ee75d getattr_delegate + 349
8 ctraits.so 0x00000001005ee75d getattr_delegate + 349
9 ctraits.so 0x00000001005ee75d getattr_delegate + 349
10 ctraits.so 0x00000001005ee75d getattr_delegate + 349
11 ctraits.so 0x00000001005ee75d getattr_delegate + 349
12 ctraits.so 0x00000001005ee75d getattr_delegate + 349
[...]
509 ctraits.so 0x00000001005ee75d getattr_delegate + 349
510 ctraits.so 0x00000001005ee75d getattr_delegate + 349
511 ctraits.so 0x00000001005ee75d getattr_delegate + 349
```

It's probably difficult to catch this at definition time, but we could probably keep track of the recursion level within `ctraits`, and bomb out with a Python `RuntimeError` when we reach the interpreter recursion limit.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.