You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

缓冲区溢出测试程序执行后出现Segmentation Fault的原因咨询

关于缓冲区溢出后出现Segmentation Fault的原因分析

先梳理下你提供的测试代码和现象:

测试代码(buffer.c)

#include<stdio.h> 
#include<stdlib.h>
#include<string.h> 

int pass(char password[]) { 
    int auth=0; 
    char p[16]; 
    strcpy(p,password); 
    if(strcmp(p,"Hello")==0) { 
        auth=1; 
    } 
    return auth; 
} 

void main(int argc,char *argv[]) { 
    if(pass(argv[1])) { 
        printf("----ACCESS GRANTED----\n"); 
    } else { 
        printf("----ACCESS DENIED----\n"); 
    } 
} 
//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
// aaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

测试结果

  1. 正常输入的预期结果:
gcc -g buffer.c 
./a.out Hello 
----ACCESS GRANTED---- 

(此结果符合预期。)

  1. 输入较长字符串触发缓冲区溢出,绕过验证:
./a.out aaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
----ACCESS GRANTED---- 

(表明发生了缓冲区溢出。)

  1. 输入更长字符串后出现段错误:
./a.out aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
----ACCESS GRANTED---- 
Segmentation fault

为什么会出现Segmentation Fault?

这要从栈内存的布局和函数调用的栈帧结构说起:

在pass函数的栈帧里,局部变量的布局大概是这样的(具体顺序可能因编译器和架构略有不同,但核心逻辑一致):

  • 首先是char p[16],占16字节的栈空间
  • 接下来是int auth,占4字节(32位架构)或8字节(64位架构)的栈空间
  • 再往下是函数的返回地址(保存着pass函数执行完后要回到main函数的哪个位置继续执行),还有栈基址指针等关键数据

当你输入的字符串长度超过16字节时:

  • 前16字节填满p数组
  • 接下来的字节会覆盖auth变量的值,把原本的0改成非0值(比如全是'a'的话,对应的ASCII值是0x61,属于非0),所以pass函数返回1,main函数输出ACCESS GRANTED
  • 但当输入的字符串长度继续增加,超过p+auth的总长度后,就会继续覆盖栈上更靠后的返回地址。当pass函数执行完毕,要跳转到返回地址指向的位置时,这个地址已经被你输入的无效数据(比如0x61616161这类无意义的地址)覆盖了,而这个地址通常不属于程序的合法内存空间,CPU尝试访问这个无效地址时,就会触发操作系统的内存保护机制,抛出Segmentation Fault(段错误)。

简单来说:短的超长输入只是篡改了auth变量让验证通过,但更长的输入篡改了函数的返回地址,导致程序执行到了非法内存区域,触发段错误。

内容的提问来源于stack exchange,提问作者Aaryan BHAGAT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:41:47