不能强制缓冲区溢出到另一个变量

问题描述 投票:0回答:2

这是家庭作业。我得到了一个 c++ 文件,该文件应该演示缓冲区溢出错误,我需要更正该错误。不幸的是,我无法重现开始时的错误。两个局部变量彼此紧挨着声明,大概是因为当字符数组的值太大时,溢出将进入下一个变量,现在将显示不正确。

这是给我的代码(删除了一些注释):

#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;
}

但是,当我在提示符中输入超过 20 个字符时,它仍然会返回我输入的完整字符串,然后返回

account_number
的正确值。我的理解是我输入的额外字符应该渗入
account_number
.

在项目属性下,我已经尝试关闭基本运行时检查(在 C/C++->代码生成下)并且我已经关闭了随机基地址(在链接器->高级下)。我是否需要更改其他一些设置才能产生更可预测的缓冲区溢出?

c++ visual-studio-2022 buffer-overflow
2个回答
0
投票

编译器可以做各种优化,也不能保证两个局部变量在堆栈上以确定的顺序排列。此外,

std::string
为其堆上的内容分配内存,除非使用小字符串优化。后者取决于操作系统和 CPU 架构(特别是 32 位或 64 位 CPU)。

正如 Alan Birtles 所提到的,自 C++20 以来,

operator<<
重载将看到您正在读取固定大小的数组,并且不会导致它越界写入。

编译器也可以决定没有任何东西可以合法地覆盖

const
字符串
account_number
,所以它不能在堆栈上为它生成局部变量,而是将字符串存储在二进制文件的常量数据部分中。


0
投票

实现此目的的一种方法是将缓冲区放在结构中并在其后放置一个“幻数”:

struct ProtectedBuffer
{
    char buffer[20];
    unsigned magicNumber = 1234;

    bool overflow() {magicNumber != 1234;}
};

这样,缓冲区的任何溢出都会渗入可以检测到的固定幻数。

© www.soinside.com 2019 - 2024. All rights reserved.