简体   繁体   English

缓冲区溢出的分段错误

[英]segmentation fault on buffer overflow

I am having trouble to run this c code.我无法运行此 c 代码。 When I do i get segmentation fault and an error with 'return' return 0xdeadbeef;当我这样做时,我遇到分段错误和“返回”错误返回 0xdeadbeef;

Anyone have any suggestions?有人有什么建议吗?

#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;
}

I said that there was "at least one bug on almost every line of your code" and now I will list them.我说过“你的代码几乎每一行都至少有一个错误”,现在我将列出它们。 If I don't have any comments on a line, there are no bugs on that line, but you also need to read up on proper code formatting and style.如果我对某行没有任何注释,则该行没有错误,但您还需要阅读正确的代码格式和样式。

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;
}

Undefined behavior on the memcpy line if size is larger than 4. Since size is taken from user input, this program contains a buffer overflow vulnerability, albeit one that might be hard to exploit.如果size大于 4,则memcpy行上的未定义行为。由于size取自用户输入,因此该程序包含一个缓冲区溢出漏洞,尽管可能难以利用。 (You need to read " Smashing the Stack for Fun and Profit .") (您需要阅读“为了乐趣和利润而粉碎堆栈”。)

This function has no externally visible side effects.此功能没有外部可见的副作用。 The compiler may, and probably will, delete all of its code except the return 1 .编译器可能并且可能会删除除return 1之外的所有代码

Functions that always return the same constant value should be refactored to return void .始终返回相同常量值的函数应该重构为返回void Functions that are not used outside the current file should be declared static .在当前文件之外未使用的函数应声明为static

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

This use of printf can be replaced by puts . printf这种用法可以替换为puts Functions that are not used outside the current file should be declared static .在当前文件之外未使用的函数应声明为static

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

The first argument to main must have type int , not unsigned int . main的第一个参数必须是int类型,而不是unsigned int The return type (which must be int , not void ) is missing;缺少返回类型(必须是int ,而不是void ); many compilers will tolerate this (treating it as implicitly returning int ) for backward compatibility with pre-C89 code, but it's still Wrong.为了与 C8​​9 之前的代码向后兼容,许多编译器会容忍这种情况(将其视为隐式返回int ),但它仍然是错误的。

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

Both size and value should be unsigned long for consistency with what strtoul returns. sizevalue都应该是unsigned long以与strtoul返回的内容保持一致。

Undefined behavior if there are fewer than two command-line arguments.如果命令行参数少于两个,则未定义行为。

Need to check both calls to strtoul for failure.需要检查对strtoul两次调用是否失败。 This is nontrivial;这很重要; read the EXAMPLES section of the OpenBSD manpage for strtoul to learn how to do it correctly .阅读strtoul的 OpenBSD 联机帮助页示例部分,以了解如何正确执行此操作。

However, props for using strtoul rather than atoi (which you can't check for failure) or sscanf (which has undefined behavior on integer overflow).但是,使用strtoul而不是atoi (您无法检查失败)或sscanf (在整数溢出时具有未定义的行为)的道具。

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

The compiler can and will determine that lame always returns 1, and optimize out the call to awesome .编译器可以并且将会确定lame总是返回 1,并优化对awesome的调用。 (In fact, it would be entitled to optimize out everything but the above printf , as all control flow paths either trigger undefined behavior or they reach this printf , and there are no other externally visible effects. The compilers I have readily to hand are not quite that clever, but they do remove the if-then-else and all the code inside lame .) (实际上,它有权优化除上述printf之外的所有内容,因为所有控制流路径要么触发未定义的行为,要么到达此printf ,并且没有其他外部可见的影响。我很容易掌握的编译器不是非常聪明,但他们确实删除了 if-then-else 和lame所有代码。)

This use of printf can also be replaced by puts . printf这种用法也可以替换为puts

You will automatically become 23% less lame the moment you stop calling yourself lame.一旦你不再称自己为跛脚,你就会自动减少 23% 的跛脚。

return 0xdeadbeef;

The value returned by main is meaningful. main返回的值是有意义的。 0 means success of the overall program, any other value means some sort of failure. 0 表示整个程序的成功,任何其他值都表示某种失败。 Always return 0 unless you intend to indicate failure.除非您打算指示失败,否则始终返回 0。 Also, only values in the range [0, 127] can be reliably received by the parent process cross-platform;此外,父进程跨平台只能可靠地接收范围 [0, 127] 中的值; 0xdeadbeef is Right Out. 0xdeadbeef是正确的。

In your screenshot, main returned void instead of having a missing return type;在您的屏幕截图中, main返回void而不是缺少返回类型; that plus a return statement with a value should have caused the program to fail to compile .加上带有值的return语句应该会导致程序无法编译 Your compiler might tolerate it in main , though.不过,您的编译器可能会在main容忍它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM