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 和响应堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章

什么是堆栈溢出?

怎么解决 LINUX 堆栈溢出内存的问题

怎么防止堆栈溢出

堆栈溢出一般是由啥原因导致的?

vb 堆栈溢出

缓冲区溢出(vs)缓冲区溢出(vs)堆栈溢出[重复]