使用signal、setjmp、longjmp进行Linux/Android C异常处理

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <signal.h>
 4 #include <setjmp.h>
 5 jmp_buf sigsegv_buf;
 6 
 7 
 8 void sigsegv_callback(int sig_num){
 9     printf("recieve a segment fault signal! [%d]\n", sig_num);
10     longjmp(sigsegv_buf, 1);
11     return;
12 }
13 void vulfunc(){
14     char dest[4];
15     printf("into vulfunc\n");
16     strcpy(dest, "deadbeefdeadbeefdeadbeefdeadbeef");
17     printf("%s\n", dest);
18     return;
19 }
20 
21 int main(){
22     bsd_signal(SIGSEGV, sigsegv_callback);
23     int res;
24     res = setjmp(sigsegv_buf);
25     if(res==0){
26         vulfunc();
27     }else if(res==1){
28         printf("recovered from segment fault!\n");
29     }
30     printf("end\n");
31     if(res!=0){
32         exit(0);
33     }
34     return 0;
35 }

一个缓冲区溢出函数,导致segment fault 出发异常后的捕获和处理。

  1. main函数中利用signal/bsd_signal函数注册异常处理函数 sigsegv_callback
  2. 用setjmp设置程序恢复点(保存寄存器状态)
  3. 调用vulfunc,发生溢出,导致segment fault
  4. 执行到sigsegv_callback
  5. 在sigsegv_callback中使用longjmp从保存的状态中恢复程序到setjmp的下一条指令,设置setjmp的返回值为非0
  6. setjmp返回的是longjmp中设置的非0值,从而跳转setjmp后面的另一分支。

在Android(native executable file和Java+jni )测试。

 

亦可参考:http://www.csl.mtu.edu/cs4411.ck/www/NOTES/non-local-goto/sig-1.html

posted on 2015-01-21 10:31  rainduck  阅读(1144)  评论(0编辑  收藏  举报

导航