缓冲区溢出会改变它正在覆盖的变量的数据类型吗?[关闭]


8

说我有一个C字符数组char buf[15]。说变量int set_me = 0的数据紧接在之后的位置char buf[15]。如果我溢出buf与串"aaabbbcccdddeee\xef\xbe\xad\xde",将set_me的数据类型的变化从一个整数的字符阵列?


3
取决于谁在解释数据。最后一切都是二进制的。因此,按照您的解释方式,它可以是有效的整数值或引起强制转换错误
GaneshR。18年

Answers:


33

没有。

变量的“数据类型”仅在源代码中相关(甚至在某些语言中也是如此)。它告诉编译器如何处理变量。

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


变量在硬件中不存在。在硬件中,您具有内存位置以及对其进行操作的指令。

变量可以看作是内存位置数据的视图 —如果斜视并看一下同一块内存(不同类型的不同变量引用同一位置),则相同的二进制值可能具有不同的含义。

例如,字节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|
+-------------+--------------------------------------------------------+

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


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

2 x86实际上是little-endian,这意味着您向后解释构成较大值的字节。因此,在x86上,您将拥有0xDEADBEEF签名-559038737或未签名的属性3735928559


因此0xdeadbeef,在x86架构上,它将比其十进制形式占用更少的内存空间3735928559
达里恩·施普林格

2
@DarienSpringer都占用4个字节的内存—它们是相同的4字节序列。它们在内存中是相同的。如果需要,您可以将其全部视为内存的基数2(二进制)。然后,当您显示它们(转换为字符串以输出)时,您可以选择要显示的底数-十六进制为16,十进制为10。字符串表示形式存储在不同的存储位置,并且可以使用不同的数量内存(因为每个字符是一个单独的字节)。该字符串 0xDEADBEEF以形式存储在内存中0x30 0x78 0x44 0x45 0x41 0x44 0x42 0x45 0x45 0x46
鲍勃

5
@DarienSpringer换句话说,无论数字是什么底数,数字都是相同的数字。十六进制是查看二进制文件的便捷(紧凑)方式。从物理上来说,它是二进制的。人类喜欢小数,因此我们更经常将数字显示为小数。但是,直到进入显示步骤,所有数值运算(加,减,乘等)都对内存中的相同二进制数据起作用。
鲍勃

1
“你可以看到,INT的存储位置现在是0xEFBEADDE”鸡蛋里挑骨头:我知道你不打算这样,但它听起来像你说的INT所在内存位置0xEFBEADDE。也许改写一下。否则,这是一个绝妙的答案-我特别喜欢“观察”类比和“斜眼”的想法:)
轨道轻轨赛

@LightnessRacesinOrbit好点。编辑。
鲍勃

2

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.