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

无法复现缓冲区溢出覆盖相邻变量的技术问询

缓冲区溢出复现问题排查与解决

问题描述

拿到一段用于演示缓冲区溢出的C++代码,需要先复现错误再修正,但输入超过20个字符时,程序仍返回完整输入,且account_number输出正常,未出现预期的覆盖异常。已关闭基本运行时检查和随机基址,但仍无法复现。

原代码如下:

#include <iomanip>
#include <iostream>

int main()
{
  std::cout << "Buffer Overflow Example" << std::endl;

  const std::string account_number = "CharlieBrown42";
  char user_input[20];
  std::cout << "Enter a value: ";
  std::cin >> user_input;

  std::cout << "You entered: " << user_input << std::endl;
  std::cout << "Account Number = " << account_number << std::endl;
}

核心原因分析

  1. std::string存储特性:std::string默认采用小字符串优化(SSO),但当字符串长度超过阈值(通常15-20字节)时,底层数据会存储在堆上,栈上仅保留指针、长度和容量成员。栈上的user_input溢出只会破坏这些栈上成员,不会直接覆盖字符串内容,因此输出可能仍正常。
  2. 编译器栈保护机制:默认开启的栈保护(如VS的/GS标志)会在栈变量间插入随机保护字节,阻止溢出直接覆盖其他变量。
  3. 编译器优化影响布局:优化选项会调整栈变量的存储位置,两个变量不一定按代码声明顺序紧邻存放。
  4. 内存对齐间隙:默认的结构成员对齐规则会在变量间产生内存间隙,溢出内容可能先填充间隙,未触及目标变量。

复现所需的设置调整(针对Visual Studio)

  • 关闭栈保护:项目属性 → C/C++ → 代码生成 → 启用安全检查,设置为禁用(/GS-)
  • 禁用编译器优化:项目属性 → C/C++ → 优化 → 优化,设置为禁用(/Od)
  • 关闭数据执行保护(DEP):项目属性 → 链接器 → 高级 → 数据执行保护,设置为否(/NXCOMPAT:NO)
  • 强制1字节对齐:项目属性 → C/C++ → 代码生成 → 结构成员对齐,设置为1字节(/Zp1),消除变量间的对齐间隙
  • 关闭随机基址:已完成,保持设置为否(/DYNAMICBASE:NO)

代码修改建议

将std::string改为栈上的字符数组,确保目标变量和user_input都在栈上紧邻存储,更容易观察溢出效果:

#include <iomanip>
#include <iostream>

int main()
{
  std::cout << "Buffer Overflow Example" << std::endl;

  const char account_number[] = "CharlieBrown42";
  char user_input[20];
  std::cout << "Enter a value: ";
  std::cin >> user_input;

  std::cout << "You entered: " << user_input << std::endl;
  std::cout << "Account Number = " << account_number << std::endl;
}

修改后,输入超过20个字符时,溢出内容会直接覆盖account_number的栈内存,导致其输出异常,即可复现缓冲区溢出效果。

内容的提问来源于stack exchange,提问作者Tom H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:05:32