23

I'm not advocating that this would ever be a good idea, but I've found that you can crash Python (2.7 and 3.2 checked) by running eval on a large enough input string:

def kill_python(N):
    S = '+'.join((str(n) for n in xrange(N)))
    return eval(S)

On my computer S can be generated just fine, but for values of approximately N>74900, Python will fail with Segmentation fault (core dumped). Is there a limit to the length of string (or parse tree) that the interpreter can handle?

Note: I don't need to do this, to me this is a deeper question reflecting my ignorance of what goes on inside the box. I'd like to understand why Python fails here, and so catastrophically (why not throw an exception?)

Hooked
  • 84,485
  • 43
  • 192
  • 261
  • 7
    IIRC, the Python interpreter segfaulting is considered a bug in any situation, and shouldn't happen - this might be worth a [bug report](http://bugs.python.org/). – Gareth Latty Jul 24 '12 at 16:26
  • 4
    @Lattyware: In most situations, not all. But this one *should* be considered a bug. – Sven Marnach Jul 24 '12 at 16:27
  • Interestingly, `sum(xrange(75000))` seems to work just fine – inspectorG4dget Jul 24 '12 at 16:27
  • @SvenMarnach A few exceptions spring to mind (the most obvious being an extension module causing CPython to crash), but as this is core functionality, I think - as you say - it's probably a bug. – Gareth Latty Jul 24 '12 at 16:29
  • I just tested `N=749001` - It worked fine... as did 750000. – jmetz Jul 24 '12 at 16:29
  • I was able to reproduce this effect at `N = 74900` – Joel Cornett Jul 24 '12 at 16:30
  • @mutzmatron: The limit on my machine is also much higher than Hooked's value, but eventually it segfaults. – Sven Marnach Jul 24 '12 at 16:30
  • @mutzmatron I think it may be computer dependent. Try larger values of `N` and see if you can get it to crash - I looped my function until I found the fail value. – Hooked Jul 24 '12 at 16:30
  • The same thing happens using `exec`, or even when writing the string to a file and trying to run it. – Sven Marnach Jul 24 '12 at 16:31
  • Cheers @SvenMarnach - got it now too. – jmetz Jul 24 '12 at 16:32
  • Could it be that the resultant string from the `join` takes up more memory than the OP's computer has? – inspectorG4dget Jul 24 '12 at 16:38
  • 4
    This has been seen in the answer here too: http://stackoverflow.com/questions/5177432/segmentation-fault-in-pi-calculation-python – jmetz Jul 24 '12 at 16:38
  • @inspectorG4dget: When I ran the function, I used `print` to indicate where the segfault is occuring. The string formation doesn't cause the crash, it happens on the `eval` line. – Joel Cornett Jul 24 '12 at 16:50

1 Answers1

18

This issue is caused by a stack overflow in the CPython compiler. An easy way to reproduce the same issue is

>>> code = compile("1" + "+1" * 1000000, "", "eval")
Segmentation fault

which proves that the segfault is happening at the compile stage, not during evaluation. (Of course this is also easy to confirm with gdb.)

[Side note: For smaller expressions, the compiler would apply constant folding here anyway, so the only thing happening during the execution of the code is to load the result:

>>> code = compile("1" + "+1" * 1000, "", "eval")
>>> eval(code)
1001
>>> dis.dis(code)
  1           0 LOAD_CONST            1000 (1001)
              3 RETURN_VALUE        

End of side note.]

This issue is a known defect. The Python developers collected several ways to crash the Python interpreter in the directory Lib/test/crashers of the source distribution. The one corresponding to this issue is Lib/test/crashers/compiler_recursion.py.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Just for the reference, this seems to be fixed in Python 3.3+. The code raises `RecursionError: maximum recursion depth exceeded during compilation` now. – Vlad Frolov Apr 18 '17 at 15:01