简体   繁体   English

程序不会因堆溢出而崩溃

[英]Program do not crash on heap overflow

I have written following program:我编写了以下程序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(int argc, char *argv[]){
  char *input;
  input = (char*)malloc(16);
  printf("input is : %s\n", input);
}

When I run this as:当我将其运行为:

./test `python -c 'print "A"*5000'`

it does not crash.它不会崩溃。 It rather prints data.而是打印数据。

When I use free(input) after printf , it crashes.当我在printf之后使用free(input) ,它崩溃了。

Why does this happen?为什么会发生这种情况?

The code shown ignores its command line arguments:显示的代码忽略其命令行参数:

int main(int argc, char *argv[]){
  char *input;
  input = (char*)malloc(16);
  printf("input is : %s\n", input);
}

It shouldn't matter what the Python script provides. Python 脚本提供什么无关紧要。 However, your printf() is printing uninitialized data;但是,您的printf()正在打印未初始化的数据; that leads to undefined behaviour.这会导致未定义的行为。 If the printf() doesn't crash and there is a free(input);如果printf()没有崩溃并且有一个free(input); call after the printf() , then the free() shouldn't crash.printf()之后调用,那么free()不应该崩溃。

If you missed out a copy operation and intended to show something like this, then the rules are different:如果您错过了复制操作并打算显示类似内容,那么规则就不同了:

int main(int argc, char *argv[]){
  char *input;
  input = (char*)malloc(16);
  strcpy(input, argv[1]);
  printf("input is : %s\n", input);
  free(input);
  return 0;
}

Now you are not checking that argv[1] is not a null pointer before you use it — that could cause a crash.现在您在使用argv[1]之前没有检查它是否不是空指针——这可能会导致崩溃。 And you are trampling way out of bounds of the allocated memory if you pass 5000 characters in argv[1] .如果您在argv[1]传递 5000 个字符,那么您就是在超出分配的内存范围。 Something will probably trigger a crash;有些事情可能会引发崩溃; it isn't defined what will cause the crash.它没有定义什么会导致崩溃。 The strcpy() may fail; strcpy()可能会失败; the printf() probably won't fail if the copy doesn't (but that isn't guaranteed);如果副本没有失败, printf()可能不会失败(但这不能保证); the free() will probably fail because you trampled out of bounds (but even that isn't guaranteed). free()可能会失败,因为你踩到了界外(但即使这样也不能保证)。 Such are the wonders of 'undefined behaviour';这就是“未定义行为”的奇迹; anything could happen and it is valid behaviour.任何事情都可能发生,这是有效的行为。

Why does this happen?为什么会发生这种情况?

Buffer overflow (in this case heap overflow ) doesn't cause immediately crash.缓冲区溢出(在这种情况下是堆溢出)不会立即导致崩溃。 Writing outside of bounds of allocated memory causes undefined behavior - anything might happen;在分配的内存范围之外写入会导致未定义的行为- 任何事情都可能发生; even it can work correctly.即使它可以正常工作。

Is there a reliable way to create crash without having free()有没有一种可靠的方法可以在没有 free() 的情况下创建崩溃

If you don't even initialize pointer input and dereference it (read or write there), most likely you will get a SEGFAULT, but it's still 'only' undefined behavior.如果您甚至不初始化指针input并取消引用它(在那里读取或写入),很可能您会得到一个 SEGFAULT,但它仍然是“仅”未定义的行为。

From C99 draft standard来自C99 标准草案

Possible undefined behavior ranges from ignoring the situation completely with unpredictable results , to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).可能的未定义行为范围从完全忽略情况并产生不可预测的结果,在翻译或程序执行期间以环境特征的文件化方式(有或没有发出诊断消息),到终止翻译或执行(发出诊断消息)。


But be be careful要小心

An overflow may result in data corruption or unexpected behavior by any process which uses the affected memory area .溢出可能会导致数据损坏或任何使用受影响内存区域的进程出现意外行为。 On operating systems without memory protection, this could be any process on the system .在没有内存保护的操作系统上,这可以是系统上的任何进程。

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

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