Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can undefined behavior erase the hard drive?

From "Effective C++ 3rd edition by Scott Meyers":

To emphasize that the results of undefined behavior are not predictable and may be very unpleasant, experienced C++ programmers often say that programs with undefined behavior can erase your hard drive.

Under what circumstances can this happen?

For example, can accessing and writing to locations out of array range corrupt memory that doesn't belong to this C++ program or thread?

like image 423
Oleksiy Avatar asked Aug 29 '13 08:08

Oleksiy


3 Answers

Can it? Sure. Happened to me, in fact.

I wrote code to delete a temporary directory. That involved creating a recursive delete <temp directory>\*.* command. Due to a bug, the <temp directory> field wasn't always filled in. Our file system code happily executed the recursive delete \*.* command.

My colleagues noticed when the icons on their desktop suddenly disappeared. Took out two machines.

like image 74
MSalters Avatar answered Oct 15 '22 07:10

MSalters


If you take into account that UB is available not only to user-mode code, but also the system programmer. In other words, if you are writing driver-code with UB (or other bugs!) in it, you could end up writing to to a piece of memory that is later written back as the "root of the whole disk-data structure".

I have indeed had a bug in a driver which I worked on, that caused disk corruption, because the driver was using stale pointers (pointer use after free). If you were UNLUCKY, the unused memory happened to be a block owned by the filesystem, so it would write back to the disk some random garbage. Fortunately, it wasn't too difficult to determine what the problem was, and I only needed reformat the disk once on my test-system (when working on drivers, you typically use two computers, one to build the code, and one to test the code on - the test machine typically has a minimal install set, and often gets reformatted and reconfigured relatively often anyway).

I don't think Scott's mention necessarily means this type of situation, but it's entirely possible that if you have wild-enough code, it can cause almost anything to happen. Including finding holes in the security system (cf. all the stack-smashing exploits that have been successful). You probably have to be VERY unlucky to achieve that, but people also win those mega-lotteries from time to time, so if you can achieve something that has one chance in several million once a week or once a month, then a computer that can perform operations many millions of times a second can achieve much less likely things...

like image 22
Mats Petersson Avatar answered Oct 15 '22 06:10

Mats Petersson


From the C++11 Standard (actually from Draft N3337), in section 1.3 Terms and definitions [intro.defs] (emphasis mine):

undefined behavior
behavior for which this International Standard imposes no requirements
[ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible 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). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]

From "no requirements" + "unpredictable results" we can conclude that (in theory) anything could happen.

Now, no "reasonable" compiler would purposely emit code to erase the hard drive for, e.g., a division by 0, but it could happen if you mess with the file system or indeed, as you said, if you corrupt memory (edit: see MSalters' comment on their own answer).

The point here is: always be careful to never ever ever invoke undefined behavior. "Here Be Dragons."

(In practice it can be hard to be sure that your program is well-defined. There's some advice. Know you language well, and keep away from the dusty corners. If a piece of code seems suspect or too complex, try to rewrite it to make it simpler and clearer. Always compile with the highest level of warnings, and don't ignore them. There are also compiler flags like -fcatch-undefined-behavior and tools like lint that can help. And testing of course, but that's a bit late.)

like image 7
gx_ Avatar answered Oct 15 '22 07:10

gx_