gpt4 book ai didi

c - 缓冲区溢出段错误

转载 作者:行者123 更新时间:2023-11-30 21:35:27 24 4
gpt4 key购买 nike

我在运行此 C 代码时遇到问题。当我这样做时,我遇到段错误和“返回”错误 return 0xdeadbeef;

大家有什么建议吗?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int lame(unsigned int size, unsigned int value){

unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));

return 1;
}

void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}

main(unsigned int argc, char ** argv){
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);

if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}

return 0xdeadbeef;
}

最佳答案

我说过“几乎每一行代码都至少有一个错误”,现在我将列出它们。如果我在某行上没有任何注释,则该行上没有错误,但您还需要阅读正确的代码格式和样式。

int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}

如果 size 大于 4,则 memcpy 行上的未定义行为。由于 size 取自用户输入,因此该程序包含一个缓冲区溢出漏洞,尽管可能很难利用。 (您需要阅读“Smashing the Stack for Fun and Profit 。”)

此函数没有外部可见的副作用。编译器可能并且很可能会删除除return 1之外的所有代码

始终返回相同常量值的函数应重构为返回void。不在当前文件外部使用的函数应声明为静态

void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}

printf 的这种用法可以用 puts 代替。不在当前文件外部使用的函数应声明为静态

main(unsigned int argc, char ** argv){

main 的第一个参数必须为 int 类型,而不是 unsigned int。缺少返回类型(必须是 int,而不是 void);许多编译器会容忍这一点(将其视为隐式返回 int),以向后兼容 C89 之前的代码,但这仍然是错误的。

unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);

sizevalue 都应为 unsigned long,以便与 strtoul 返回的内容保持一致。

如果命令行参数少于两个,则会出现未定义的行为。

需要检查对 strtoul 的两次调用是否失败。这一点很重要;阅读EXAMPLES section of the OpenBSD manpage for strtoul了解如何正确地做到这一点。

但是,使用 strtoul 而不是 atoi(您无法检查失败)或 sscanf 的属性code> (在整数溢出时有未定义的行为)。

if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}

编译器可以并且将会确定 lame 始终返回 1,并优化对 awesome 的调用。 (事实上​​,它有权优化除上述 printf 之外的所有内容,因为所有控制流路径要么触发未定义的行为,要么到达此 printf code>,并且没有其他外部可见的效果。我手边的编译器并不是那么聪明,但它们确实删除了 if-then-else 以及 中的所有代码蹩脚。)

printf 的这种用法也可以用 puts 代替。

当你不再称自己是跛子时,你的跛子就会自动减少 23%。

return 0xdeadbeef;

main返回的值是有意义的。 0 表示整个程序成功,任何其他值表示某种失败。除非您打算指示失败,否则始终返回 0。并且,只有[0, 127]范围内的值才能被父进程跨平台可靠接收; 0xdeadbeef 已经出局了。

在您的屏幕截图中,main 返回了 void,而不是缺少返回类型;加上带有值的 return 语句应该会导致程序无法编译。不过,您的编译器可能会在 main 中容忍它。

关于c - 缓冲区溢出段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33900698/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com