访问超出其边界的数组(在C语言中)有多危险?有时会发生这样的情况:我从数组外部读取数据(我现在知道我访问了程序的其他部分使用的内存,甚至超出了这个范围),或者我试图将一个值设置为数组外部的索引。程序有时会崩溃,但有时只是运行,只会给出意想不到的结果。

现在我想知道的是,这到底有多危险?如果它损坏了我的程序,那也不算太坏。另一方面,如果它破坏了我程序之外的东西,因为我设法访问了一些完全不相关的内存,那么我想这是非常糟糕的。 我读过很多“任何事情都可能发生”,“细分市场可能是最不坏的问题”,“你的硬盘可能变成粉红色,独角兽可能在你的窗户下唱歌”,这些都很好,但真正的危险是什么?

我的问题:

Can reading values from way outside the array damage anything apart from my program? I would imagine just looking at things does not change anything, or would it for instance change the 'last time opened' attribute of a file I happened to reach? Can setting values way out outside of the array damage anything apart from my program? From this Stack Overflow question I gather that it is possible to access any memory location, that there is no safety guarantee. I now run my small programs from within XCode. Does that provide some extra protection around my program where it cannot reach outside its own memory? Can it harm XCode? Any recommendations on how to run my inherently buggy code safely?

我使用OSX 10.7, Xcode 4.6。


当前回答

Objective-C中的nsarray被分配一个特定的内存块。超过数组的边界意味着您将访问没有分配给数组的内存。这意味着:

This memory can have any value. There's no way of knowing if the data is valid based on your data type. This memory may contain sensitive information such as private keys or other user credentials. The memory address may be invalid or protected. The memory can have a changing value because it's being accessed by another program or thread. Other things use memory address space, such as memory-mapped ports. Writing data to unknown memory address can crash your program, overwrite OS memory space, and generally cause the sun to implode.

从程序的角度来看,您总是想知道代码何时超出了数组的边界。这可能导致返回未知值,导致应用程序崩溃或提供无效数据。

其他回答

你写的:

我读过很多“任何事情都可能发生”,“市场细分可能是。 “最不坏的问题”,“你的硬盘可能会变成粉红色,独角兽也可能 在你的窗下唱歌,这是很好的,但真正的 危险吗?

这么说吧,给枪上膛。瞄准窗外,不要瞄准,然后开火。危险在哪里?

The issue is that you do not know. If your code overwrites something that crashes your program you are fine because it will stop it into a defined state. However if it does not crash then the issues start to arise. Which resources are under control of your program and what might it do to them? I know at least one major issue that was caused by such an overflow. The issue was in a seemingly meaningless statistics function that messed up some unrelated conversion table for a production database. The result was some very expensive cleanup afterwards. Actually it would have been much cheaper and easier to handle if this issue would have formatted the hard disks ... with other words: pink unicorns might be your least problem.

认为操作系统会保护你的想法是乐观的。如果可能,尽量避免越界写作。

Objective-C中的nsarray被分配一个特定的内存块。超过数组的边界意味着您将访问没有分配给数组的内存。这意味着:

This memory can have any value. There's no way of knowing if the data is valid based on your data type. This memory may contain sensitive information such as private keys or other user credentials. The memory address may be invalid or protected. The memory can have a changing value because it's being accessed by another program or thread. Other things use memory address space, such as memory-mapped ports. Writing data to unknown memory address can crash your program, overwrite OS memory space, and generally cause the sun to implode.

从程序的角度来看,您总是想知道代码何时超出了数组的边界。这可能导致返回未知值,导致应用程序崩溃或提供无效数据。

就ISO C标准(该语言的官方定义)而言,在其边界之外访问数组具有“未定义行为”。字面意思是:

行为,在使用不可移植或错误的程序构造或 错误的数据,本标准没有规定 需求

一个非规范性的注释对此进行了扩展:

可能的未定义行为包括忽略情况 翻译过程中的行为完全无法预测结果 或以文件化的方式执行程序的特点 环境(有或没有发出诊断消息),到 终止翻译或执行(通过发出 诊断消息)。

这就是理论。现实是什么?

在“最佳”情况下,您将访问一些内存,这些内存要么属于当前运行的程序(这可能导致您的程序行为不正常),要么不属于当前运行的程序(这可能导致您的程序因分段错误而崩溃)。或者你可能会尝试写入程序拥有的内存,但它被标记为只读;这也可能导致您的程序崩溃。

That's assuming your program is running under an operating system that attempts to protect concurrently running processes from each other. If your code is running on the "bare metal", say if it's part of an OS kernel or an embedded system, then there is no such protection; your misbehaving code is what was supposed to provide that protection. In that case, the possibilities for damage are considerably greater, including, in some cases, physical damage to the hardware (or to things or people nearby).

即使在受保护的操作系统环境中,保护也不总是100%。例如,有些操作系统错误允许非特权程序获得根(管理)访问权限。即使使用普通用户权限,出现故障的程序也会消耗过多的资源(CPU、内存、磁盘),可能导致整个系统瘫痪。许多恶意软件(病毒等)利用缓冲区溢出来获得对系统的未经授权的访问。

(一个历史上的例子:我听说在一些具有核心内存的旧系统上,在一个紧密循环中重复访问单个内存位置可能会导致内存块融化。其他的可能性包括损坏CRT显示器,以驱动器柜的谐波频率移动磁盘驱动器的读写头,导致它走过桌子,掉到地板上。)

而且还要担心天网。

底线是这样的:如果你可以编写一个程序故意做一些不好的事情,那么至少在理论上,一个有bug的程序可能会意外地做同样的事情。

实际上,在MacOS X系统上运行的有bug的程序不太可能出现比崩溃更严重的情况。但是完全阻止有bug的代码做一些非常糟糕的事情是不可能的。

一般来说,现在的操作系统(流行的操作系统)使用虚拟内存管理器在受保护的内存区域中运行所有应用程序。事实证明,简单地读取或写入存在于已分配给进程的区域之外的REAL空间中的位置(就其本身而言)并不容易。

直接回答:

Reading will almost never directly damage another process, however it can indirectly damage a process if you happen to read a KEY value used to encrypt, decrypt, or validate a program / process. Reading out of bounds can have somewhat adverse / unexpected affects on your code if you are making decisions based on the data you are reading The only way your could really DAMAGE something by writing to a loaction accessible by a memory address is if that memory address that you are writing to is actually a hardware register (a location that actually is not for data storage but for controlling some piece of hardware) not a RAM location. In all fact, you still wont normally damage something unless you are writing some one time programmable location that is not re-writable (or something of that nature). Generally running from within the debugger runs the code in debug mode. Running in debug mode does TEND to (but not always) stop your code faster when you have done something considered out of practice or downright illegal. Never use macros, use data structures that already have array index bounds checking built in, etc....

ADDITIONAL I should add that the above information is really only for systems using an operating system with memory protection windows. If writing code for an embedded system or even a system utilizing an operating system (real-time or other) that does not have memory protection windows (or virtual addressed windows) that one should practice a lot more caution in reading and writing to memory. Also in these cases SAFE and SECURE coding practices should always be employed to avoid security issues.

不以根用户或其他特权用户身份运行程序不会对任何系统造成损害,因此通常这可能是一个好主意。

通过将数据写入某个随机的内存位置,你不会直接“破坏”计算机上运行的任何其他程序,因为每个进程都运行在自己的内存空间中。

如果你试图访问任何没有分配给你的进程的内存,操作系统将停止你的程序执行分割错误。

因此,直接(无需以根用户身份运行并直接访问/dev/mem之类的文件),您的程序不会干扰在您的操作系统上运行的任何其他程序。

尽管如此——这可能是你听说过的危险——盲目地将随机数据写入随机的内存位置,你肯定会损坏任何你能损坏的东西。

例如,您的程序可能希望删除存储在程序某处的文件名所给出的特定文件。如果你不小心覆盖了文件名所在的位置,你可能会删除一个完全不同的文件。