libsigsegv 和响应堆栈溢出
Posted
技术标签:
【中文标题】libsigsegv 和响应堆栈溢出【英文标题】:libsigsegv and responding to a stack overflow 【发布时间】:2011-06-28 04:20:18 【问题描述】:我们正在尝试测试学生代码,并且为了自动化该过程,我们想检测学生的代码是否溢出堆栈。
我使用 libsigsegv 库及其相应的 ***_install_handler 取得了一些成功。它运行得非常好,直到学生的代码两次爆栈。
例如,下面是一些示例输出:
[# ~]$ ledit ./interpreter
-> (use solution)
-> (fun 1 2)
*** Stack overflow detected ***
-> (fun 1 2)
Signal -10
[# ~]
最初的“* Stack overflow detected *”是理想的输出。在第二次炸毁堆栈后,我得到的只是一个无用的“信号 -10”,程序停止执行。我想再次查看检测到堆栈溢出的消息,并让代码继续执行。
在我的堆栈溢出处理程序中,我只是将溢出检测消息打印到 stderr 并在解释器中长跳转回“等待输入状态”。
感谢您的帮助!
编辑
根据以下 caf 的建议,我们添加了对 sigsegv_leave_handler() 的调用,如下所示:
static void continuation(void *arg1, void *arg2, void *arg3)
(void)(arg1);
(void)(arg2);
(void)(arg3);
siglongjmp(errorjmp, 1);
static void handler(int emergency, ***_context_t context)
(void)emergency;
(void)context;
fprintf(stderr, "\n*** Stack overflow detected ***\n");
fflush(stderr);
sigsegv_leave_handler(continuation, NULL, NULL, NULL);
但是,输出还是一样的。
【问题讨论】:
+1 只是为了使用流行语 +1 用于尝试使用 *** 检测堆栈溢出 【参考方案1】:简单地远离堆栈溢出是不够的。我还没有看到您要嵌入的解释器的源代码,但我的直觉是堆栈溢出会导致某些内部解释器状态损坏,这可能会导致另一次崩溃。特别要注意,您收到的信号是 SIGBUS (10),而不是 SIGSEGV (11)。
想象一下这样的场景:当解释器调用malloc
时,你只是缺少堆栈溢出。 Malloc 更改一些内部数据,然后调用辅助函数。发生堆栈溢出,您 longjmp 回到解释器主循环。您的 malloc 池现已损坏,您无能为力。
我建议在检测到堆栈溢出时终止并重新启动解释器。或者,弄清楚解释器状态是如何被破坏的,并安排它减少问题(这可能非常困难!)。您还可以在解释器中使用显式堆栈深度检查,而不是捕获 SIGSEGV;这将允许您在 SIGSEGV 强制问题之前在安全点处理错误。
【讨论】:
【参考方案2】:您是否遵循libsigsegv documentation 中的这一警告?
...处理程序必须确保恢复 正常的信号掩码(因为很多 处理程序时信号被阻塞 被执行),并且还必须调用
sigsegv_leave_handler()
转让 控制;那么只有它可以longjmp 离开。
【讨论】:
感谢您的建议---我们试过了,结果还是一样。我已经修改了我原来的问题以反映这一点。 (如果我在这里没有遵循 *** 约定,我深表歉意,这是我第一次在这里提交问题。)【参考方案3】:尝试更密切地关注 libsigsegv 包中的示例代码 tests/***1.c。此示例代码确实支持连续捕获两个连续的堆栈溢出。特别是:
在延续中使用 longjmp,而不是 siglongjmp。 在调用 sigsegv_leave_handler 之前调用 sigprocmask。【讨论】:
鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。 好吧,我确实说过这是 libsigsegv 包中的示例代码。我总结了该链接中最重要的两点。你还想要什么?以上是关于libsigsegv 和响应堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章