libsigsegv 和响应堆栈溢出 [英] libsigsegv and responding to a stack overflow

查看:37
本文介绍了libsigsegv 和响应堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We are attempting to test student code, and in an effort to automate the process, we'd like to detect if a student's code overflows the stack.

我使用 libsigsegv 库及其相应的 stackoverflow_install_handler 取得了一些成功.它运行得非常好,直到学生的代码两次爆栈.

I've met with some success using the libsigsegv library and its corresponding stackoverflow_install_handler. It works brilliantly, until the student's code blows the stack twice.

例如,下面是一些示例输出:

For example, here's some sample output:

[# ~]$ ledit ./interpreter
-> (use solution)
-> (fun 1 2)

*** Stack overflow detected ***
-> (fun 1 2)
Signal -10
[# ~]

最初的* Stack overflow detected *"是理想的输出.在第二次炸毁堆栈后,我得到的只是一个无用的信号 -10",程序停止执行.我想再次查看检测到堆栈溢出的消息,并让代码继续执行.

The initial "* Stack overflow detected *" is the desirable output. After blowing the stack for the second time, all I get is an unhelpful "Signal -10" and the program stops execution. I'd like to see the stack overflow detected message again, and let the code continue execution.

在我的堆栈溢出处理程序中,我只是将溢出检测消息打印到 stderr 并在解释器中长跳转回等待输入状态".

In my stack overflow handler, I'm just printing the overflow detection message to stderr and long jumping back to an "awaiting input state" in the interpreter.

感谢您的帮助!

编辑

根据以下 caf 的建议,我们添加了对 sigsegv_leave_handler() 的调用,如下所示:

As per caf's suggestion below, we've added a call to sigsegv_leave_handler() like so:

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, "
*** Stack overflow detected ***
");                        
 fflush(stderr);                                                                
 sigsegv_leave_handler(continuation, NULL, NULL, NULL);                         
}  

但是,输出还是一样的.

However, the output is still the same.

推荐答案

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

Simply longjmping away from a stack overflow isn't necessarily enough. I haven't seen the source code for the interpreter you're embedding this into, but my hunch is that the stack overflow leaves some internal interpreter state corrupted that may result in another crash. In particular, note that the signal you're getting is SIGBUS (10), not SIGSEGV (11).

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

Imagine the following scenario: You're just short of a stack overflow when the interpreter calls malloc. Malloc alters some internal data, then calls a helper function. A stack overflow occurs, and you longjmp back to the interpreter main loop. Your malloc pool is now corrupted, and there's nothing you can do about it.

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

I would recommend terminating and restarting the interpreter when the stack overflow is detected. Alternately, figure out exactly how interpreter state is getting corrupted, and arrange for it to be less of a problem (this can be quite hard!). You could also use explicit stack depth checking in the interpreter rather than trapping SIGSEGV; this would allow you to handle the error at a safe point, before SIGSEGV forces the issue.

这篇关于libsigsegv 和响应堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆