缓冲区溢出是否会改变其覆盖的变量的数据类型?

缓冲区溢出是否会改变其覆盖的变量的数据类型?

假设我有一个 C 字符数组char buf[15]。假设变量int set_me = 0的数据直接存储在之后的内存位置中char buf[15]。如果我buf使用字符串溢出"aaabbbcccdddeee\xef\xbe\xad\xde"set_me那么的数据类型是否会从整数变为字符数组?

答案1

不。

变量的“数据类型”只与源代码有关(甚至只在某些语言中才与源代码有关)。它告诉编译器如何处理变量。

这些高级数据类型本身并不存在于已编译的(本机)代码中。它们可以影响编译器生成的指令,但指令本身并不关心数据是字符还是数字。


变量不存在于硬件中。在硬件中,您拥有内存位置和对其执行操作的指令。

变量可以看作看法内存位置上的数据——如果你眯着眼睛,以稍有不同的方式查看同一个内存(指向同一位置的不同类型的不同变量),相同的二进制值可能具有不同的含义。

例如,字节 0x41 可以被解释为 UTF-8 编码的字符A。它也可以被解释为单字节整数65。它也可以被解释为多字节整数或浮点数中的一个字节,或多字节字符编码中的一个字节。它可能是位集0b1000001。所有这些都来自同一内存位置中的同一字节。在 C 语言中,你可以通过以下方式看到这种效果铸件这些不同类型

当出现“缓冲区溢出”时,您执行的操作超出了编译器或语言的预期范围。但是,就硬件而言1,您正在将字节(无论是单个还是多个)写入内存位置。内存位置没有“类型”。事实上,硬件甚至不知道代码中任何特定的字节集构成数组或缓冲区。

无论您下次在代码中访问该内存位置,指令都会按照最初定义的方式运行。例如,如果他们期望那里有一个数字,他们将对数据的任何字节采取行动仿佛他们是一个数字。


使用您的示例,假设您的int是一个有符号的 4 字节(32 位)整数:

+-------------+--------------------------------------------+-----------+
| Source code |                  char[15]                  |    int    |
+-------------+--------------------------------------------------------+
| Memory      |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+

您可以看到,假设采用大端系统2int ,则的内存位置现在包含。这是有符号的 32 位 int 。现在,如果您将同一内存解释为无符号 int ( ) ,则它将改为。对于内存中完全相同的数据,其含义完全取决于您如何看待它。0xEFBEADDE-272716322uint4022250974


1有一些机制可以阻止您写入受保护的内存区域,如果您尝试这样做,会导致程序崩溃。

2 x86 实际上是小端字节序,这意味着您要反向解释组成较大值的字节。因此在 x86 上,您将得到0xDEADBEEF,给出有符号-559038737或无符号3735928559

答案2

从 C 的角度来看,答案是“谁知道?这是未定义的行为”。

类型是 C 语言的概念,而不是硬件。但是,如果您的程序有未定义行为,则 C 规则不适用,这是 C 标准中未定义行为的字面意思。缓冲区溢出就是其中一种形式。

我最初写的是“C 规则不再适用”,但实际上未定义行为具有追溯力。C 规则不适用于将来会出现未定义行为的程序。

相关内容