C++;3台机器上的缓冲区溢出不同 我正在测试C++中的简单缓冲区溢出。该示例是一个测试,如果检查不到位,恶意用户可能会使用缓冲区溢出覆盖变量

C++;3台机器上的缓冲区溢出不同 我正在测试C++中的简单缓冲区溢出。该示例是一个测试,如果检查不到位,恶意用户可能会使用缓冲区溢出覆盖变量,c++,compiler-construction,buffer-overflow,C++,Compiler Construction,Buffer Overflow,该示例先定义一个缓冲区,然后定义一个变量,这意味着应该为缓冲区分配空间,然后为变量分配空间。该示例从cin读取长度为5的缓冲区,然后检查admin变量是否设置为0以外的值,如果设置为0,则用户从概念上获得了admin访问权 #include <iostream> using namespace std; int main() { char buffer[5]; int admin = 0; cin>>buffer; if(strcmp(

该示例先定义一个缓冲区,然后定义一个变量,这意味着应该为缓冲区分配空间,然后为变量分配空间。该示例从
cin
读取长度为5的缓冲区,然后检查admin变量是否设置为0以外的值,如果设置为0,则用户从概念上获得了admin访问权

#include <iostream>
using namespace std;

int main()
{
    char buffer[5];
    int admin = 0;

    cin>>buffer;
    if(strcmp(buffer,"in") == 0)
    {
        admin = 1;
        cout<<"Correct"<<endl;
    }
    if(admin != 0)
        cout << "Access" << endl;
    return 0;
}
#包括
使用名称空间std;
int main()
{
字符缓冲区[5];
int admin=0;
cin>>缓冲液;
if(strcmp(缓冲区,“in”)==0)
{
admin=1;

正如你所发现的,未定义的行为是未定义的。试图解释它通常不会产生太大的效果


在这种情况下,几乎可以肯定这是由于堆栈的排列和由编译器/系统之间不同的局部变量插入的填充字节造成的。

您应该检查反汇编。从这里您将看到发生了什么

一般来说,有两件事需要考虑:

  • 编译器为对齐堆栈变量而进行的填充

  • 编译器对堆栈变量的相对位置

  • 第一点:数组
    char缓冲区[5]
    将被填充,因此
    int admin;
    将在堆栈上正确对齐。我希望它在x86x64上通常被填充到8个字节,并覆盖9个符号。但编译器可能会根据它认为合适的方式进行不同的操作。尽管如此,Windows和Linux机器似乎都是x86(32位)

    第二点:编译器不需要按照声明的顺序在堆栈上放置堆栈变量。在Windows和第一台Linux机器上,编译器确实会放置
    char缓冲区[5]在第二台Linux机器上,编译器选择将其按相反的顺序放置,因此在写入超出分配给
    字符缓冲区[5];
    的空间后,您将损坏
    main()
    调用方的堆栈帧,而不是溢出到
    int admin;


    这是一个无耻的链接,指向我自己对一个类似问题的答案-。

    谢谢,这正是我要找的。因为我认为char数组将接收5字节,int之后将有4字节。然后当溢出发生时,它将进入int的空间。我还读到,分配在char数组所在的单词中工作然后将如您所述为8字节。@user2715411那么,当“输入”缓冲区大于堆栈变量(数组)时发生溢出是完全正确的它是被复制到的。它只是内部的事情需要考虑,例如堆栈对齐、填充、变量放置——所有这些都将表现为稍微不同的行为(不同长度的溢出或堆栈损坏)。除此之外,这就是你所描述的。抱歉,但这不应该是“未定义的行为”。,编译器是一个程序,因此在编译程序时应该遵循一组定义的步骤。如果OP所说的是真的,那么两台可能都运行gcc的linux机器应该以相同的方式交付相同的可执行文件results@Chaosekie这种语言明确地为编译器在不同的机器上做不同的事情提供了回旋余地在同一台机器上进行不同的编译。你能给出一个定义在哪里的参考吗?似乎OP在3台不同的机器上得到了一致的结果(他花了时间也计算了溢出所需的字符数)我从来没有想到Windows和Linux机器之间的行为会有任何相似之处。Linux系统之间的差异可以通过构成程序或操作系统版本的元素的体系结构差异(内存映射)或版本控制来解释。。。