调试C中的堆栈溢出?
我有一个示例程序,当使用fstack protector编译时,它会导致堆栈崩溃调试C中的堆栈溢出?,c,debugging,gdb,stack-overflow,C,Debugging,Gdb,Stack Overflow,我有一个示例程序,当使用fstack protector编译时,它会导致堆栈崩溃 #include <stdio.h> #include <stdint.h> int func(int* value) { uint8_t port = 1; *value = port; //Canary value changes at this point when seen in GDB return 1; } int main() { ui
#include <stdio.h>
#include <stdint.h>
int func(int* value)
{
uint8_t port = 1;
*value = port; //Canary value changes at this point when seen in GDB
return 1;
}
int main()
{
uint16_t index = 0;
int ret = func((int*)&index);
}
#包括
#包括
int func(int*值)
{
uint8_t端口=1;
*value=port;//当在GDB中看到时,金丝雀的值在此时发生变化
返回1;
}
int main()
{
uint16_t指数=0;
int ret=func((int*)和index);
}
我不明白这条线怎么了。需要任何类型转换吗?这是因为
int
和int16\t
的大小不同。int
的大小(通常)是32位(四个字节),而int16\u t
的大小是16位(两个字节)
因此,当您将int
写入int16\t
变量时,您写入的字节太多,导致(在这种情况下,将“粉碎”堆栈)
问题更具体地说是因为您使用指向
index
的指针调用函数,该指针是一个16位变量,但函数期望(并使用其参数)作为32位变量。您不应该在调用中进行转换,因为这会隐藏问题,但不会解决问题。只向函数内的解引用指针写入8位值并不重要,目标仍然是32位变量,编译器将在写入内存之前将8位值转换为32位值。这是因为int
和int16\t
的大小不同。int
的大小(通常)是32位(四个字节),而int16\u t
的大小是16位(两个字节)
因此,当您将int
写入int16\t
变量时,您写入的字节太多,导致(在这种情况下,将“粉碎”堆栈)
问题更具体地说是因为您使用指向
index
的指针调用函数,该指针是一个16位变量,但函数期望(并使用其参数)作为32位变量。您不应该在调用中进行转换,因为这会隐藏问题,但不会解决问题。只向函数内的解引用指针写入8位值并不重要,目标仍然是32位变量,编译器将在写入内存之前将8位值转换为32位值。由于索引的类型是uint16\u t
,因此只为其分配16位。通过将索引
的地址强制转换为int*
,可以假装您可以访问超过16位的数据,在大多数情况下是32位
在
您正试图在尚未分配的位中设置值。由于该行中使用了未经授权的内存,此后可能会发生任何事情。由于索引的类型是uint16\t
,因此只为其分配了16位。通过将索引
的地址强制转换为int*
,可以假装您可以访问超过16位的数据,在大多数情况下是32位
在
您正试图在尚未分配的位中设置值。由于该行使用了未经授权的内存,因此在此之后可能会发生任何事情。我认为在这行“*value=port;”,uint8\u t写入int。int在哪里写入u16?但他在哪里写入int到int16\u t?@IDK将指向int16\u t
的指针传递给函数,但函数需要指向int
的指针。这就是问题所在。我想你在电话中添加了类型转换只是因为你收到了警告?警告通常是你做了不该做的事情的标志,用类型转换隐藏它只是隐藏了问题,但并不能解决问题。@IDK:因为value
是int*
,所以uint8\u t
在存储之前会转换成int
。我现在明白了。谢谢!我认为在这行“*value=port;”,uint8\u t写入int。int在哪里写入u16?但他在哪里写入int到int16\u t?@IDK将指向int16\u t
的指针传递给函数,但函数需要指向int
的指针。这就是问题所在。我想你在电话中添加了类型转换只是因为你收到了警告?警告通常是你做了不该做的事情的标志,用类型转换隐藏它只是隐藏了问题,但并不能解决问题。@IDK:因为value
是int*
,所以uint8\u t
在存储之前会转换成int
。我现在明白了。谢谢!尽管我看到了这个问题的答案,但我无法重现任何错误。我确实做了gcc-fstack protector yourcode.c
。很抱歉,旗子是-fstack保护者allI也试过了。仍然编译得很好。而且跑得也很好,真奇怪。我被全旗扣杀了。看看gdb中的金丝雀值是否发生变化。这是一个关于如何通过无意义地四处抛投来击打自己脚的好例子。尽管我看到了这个问题的答案,但我无法重现任何错误。我做了gcc-fstack protector yourcode.c
。很抱歉,旗子是-fstack保护者allI也试过了。仍然编译得很好。而且跑得也很好,真奇怪。我被全旗扣杀了。看看gdb中的金丝雀值是否发生变化。这是另一个关于如何通过无意义的抛投射中自己脚的好例子。
*value = port;