【问题标题】:libsigsegv and responding to a stack overflowlibsigsegv 和响应堆栈溢出
【发布时间】:2011-06-28 04:20:18
【问题描述】:

我们正在尝试测试学生代码,并且为了自动化该过程,我们想检测学生的代码是否溢出堆栈。

我使用 libsigsegv 库及其相应的 stackoverflow_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, stackoverflow_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 用于尝试使用 stackoverflow 检测堆栈溢出

标签: c stack-overflow signals segmentation-fault


【解决方案1】:

简单地远离堆栈溢出是不够的。我还没有看到您要嵌入的解释器的源代码,但我的直觉是堆栈溢出会导致某些内部解释器状态损坏,这可能会导致另一次崩溃。特别要注意,您收到的信号是 SIGBUS (10),而不是 SIGSEGV (11)。

想象一下这样的场景:当解释器调用malloc时,你只是缺少堆栈溢出。 Malloc 更改一些内部数据,然后调用辅助函数。发生堆栈溢出,您 longjmp 回到解释器主循环。您的 malloc 池现已损坏,您无能为力。

我建议在检测到堆栈溢出时终止并重新启动解释器。或者,弄清楚解释器状态是如何被破坏的,并安排它减少问题(这可能非常困难!)。您还可以在解释器中使用显式堆栈深度检查,而不是捕获 SIGSEGV;这将允许您在 SIGSEGV 强制问题之前在安全点处理错误。

【讨论】:

    【解决方案2】:

    您是否遵循libsigsegv documentation 中的这一警告?

    ...处理程序必须确保恢复 正常的信号掩码(因为很多 处理程序时信号被阻塞 被执行),并且还必须调用 sigsegv_leave_handler()转让 控制;那么只有它可以longjmp 离开。

    【讨论】:

    • 感谢您的建议---我们试过了,结果还是一样。我已经修改了我原来的问题以反映这一点。 (如果我在这里没有遵循 Stackoverflow 约定,我深表歉意,这是我第一次在这里提交问题。)
    【解决方案3】:

    尝试更密切地关注 libsigsegv 包中的示例代码 tests/stackoverflow1.c。此示例代码确实支持连续捕获两个连续的堆栈溢出。特别是:

    • 在延续中使用 longjmp,而不是 siglongjmp。
    • 在调用 sigsegv_leave_handler 之前调用 sigprocmask。

    【讨论】:

    • 鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。
    • 好吧,我确实说过这是 libsigsegv 包中的示例代码。我总结了该链接中最重要的两点。你还想要什么?
    猜你喜欢
    • 2019-05-18
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2012-12-20
    • 2011-03-02
    相关资源
    最近更新 更多