我该如何使Python 3.5崩溃?

12
我们在我们的应用程序中使用嵌入式CPython作为脚本语言。我们在启动时修改sys.path以确保我们不执行来自我们应用程序之外的代码,但是一个在PYTHONPATH中有sitecustomize.py的用户会导致在我们有机会修复sys.path之前执行代码,并且我们认为他们的代码有一个硬错误(不是异常,site.py将捕获并优雅处理异常)。
我相信正确的修复方法是在初始化Python之前从环境中简单清除PYTHONPATH变量,但是我无法正确测试它,因为我无法重新创建这个问题。
我找到的最简单的方法是使用ctypes写入内存,例如:
import ctypes
p = (ctypes.c_char).from_address(0)
while True:
  p[0] = 0
  p = p + 1

然而在Python 3.5中,它不允许我写入c_char类型,会给出错误提示 "TypeError: 'c_char' object does not support item assignment"

我已经尝试了一些在 https://wiki.python.org/moin/CrashingPython 上提供的方法,但都没有成功。

是否有一种可靠的方法可以从纯Python代码中使python 3.5崩溃?


你应该创建一个指向 c_char指针 并对其进行索引。 - user2357112
你尝试过在 http://svn.python.org/view/python/trunk/Lib/test/crashers/ 上的所有示例吗?我还没有3.5的访问权限,但是有几个似乎在repl.it上运行时会崩溃,它们分别是:nasty_eq_vs_dict.py,mutation_inside_cyclegc.py和gc_inspection.py。 - chickity china chinese chicken
谢谢,@user2357112。我以前没有使用过ctypes,只是复制和粘贴代码,但现在我仔细看了一下,这显然对我来说非常有道理。 - alvion
7个回答

8

这是一种简单的崩溃Python的方法:

def crash():
    try:
        crash()
    except:
        crash()

crash()

1
在Python 3.11.3中,这似乎导致Python卡住,而不是崩溃。 - spelufo

7

有很多通过ctypes的方法。例如,您的代码已经得到了纠正:

p = ctypes.pointer(ctypes.c_char.from_address(5))
p[0] = b'x'

如果您不想使用ctypes,您可以在dict.__repr__实现中触发C堆栈溢出:

x = {}
for i in range(1000000):
    x = {1: x}
repr(x)

这可能会在未来的Python版本中得到修复,但目前它应该会引起严重崩溃。
此外,还有构建自己的字节码对象的方法,因为Python几乎没有做任何事情来确保它正在执行的字节码是有意义的。

4
您可以使用以下方法:
exec(type((lambda: 0).__code__)(0, 0, 0, 0, 0, 0, b'\x053', (), (), (), '', '', 0, b''))

这将创建字节码,开始一个永远不会结束的 finally 语句,从而导致解释器崩溃。


1

简而言之,将代码行上置入0/0即可触发崩溃。此时会出现 ZeroDivisionError(除数为0) 错误。

我认为这是最简单的强制崩溃的方法。


例外并不意味着崩溃。 - undefined

1

这对我来说看起来不错,虽然我没有测试过。user2357112的答案对我有用,代码更容易理解。谢谢你的回答。 - alvion

0
西部最快的崩溃(至少在3.10和3.11上工作):
__import__("sys").setrecursionlimit(500000000)
def i():i()
i()

就像等了一秒钟,突然间窗口关闭了。
它将递归限制增加到500000000,定义了一个递归函数,并运行它。如果真的运行成功的话,会花费很长时间,但是这个数值实在太大了,所以窗口关闭了。

这只是导致了一个“RecursionError: maximum recursion depth exceeded”的错误。这并不是一个崩溃。而且你可以通过使用raise RecursionError("maximum recursion depth exceeded")来更快地解决这个问题。 - undefined

-3

我通常只使用Python 2.7,但我相信只要我正确理解您的问题,同样的方法仍然适用于此。如果您想强制退出Python程序,那么我知道的最简单的方法是引发SystemExit异常。以下是一个相当简单的示例:

for i in range (0, 10):
    if (i == 6): #Stop the program at 6 just.. because
        raise SystemExit
    print(i)

5
这不会导致Python崩溃。这与简单地调用“sys.exit()”没有任何区别。 - ekhumoro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接