What is a C0000005 crash?

In my blog about Dr. Watson I talked about product crashes. What is an example of a crash? How destructive is it?

Here’s a simple example. MyFunction takes a string parameter and calculates its length

MyFunction (char * StringParam) {

         

          int nlen; // declare an integer variable

          nlen = strlen(StringParam);

          <more code>

}

Doesn’t look like there’s a bug does it?

But there’s a potential bug: the strlen function in the C Standard Library counts the bytes in the string before finding a zero (null) byte. If the string does not have a null byte, then the strlen function will be accessing memory beyond the string buffer looking for a null byte.

This is called a Buffer Overrun error. If the memory accessed beyond the string is not allocated to the process, then a C0000005 exception (Access Violation) will result. If this exception is unhandled by the process, then the ‘unhandled exception handler” of the OS will be invoked. This is typically Dr. Watson. (However, the memory may be legitimately accessed, but may be overwritten by a virus that takes advantage of a buffer overrun on a strcpy Standard Library function).

If you have Visual Studio installed, you can look at the file PlatformSDK\include\ntstatus.h to find some of the various kinds of exceptions:

// MessageId: STATUS_ACCESS_VIOLATION

//

// MessageText:

//

// The instruction at "0x%08lx" referenced memory at "0x%08lx". The memory could not be "%s".

//

#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005L) // winnt

In the old days of Win3.11, there was no memory protection enforcement: Accessing any memory in the process address space was fair game. strlen would just cruise merrily through the process memory, even through non-owned memory, until it found a null byte. Thus, old code may run fine on old OS’s, but when run on a new OS, it might crash.

The C Standard Library (also known as the runtime library) is not part of the C language, but it is assumed by all C development environments (particularly the linker) to be available. Microsoft’s versions have “MSVCRT” in their names. When the string functions were defined, the strings were assumed to be character arrays with a terminating null byte. This implies possible buffer overruns, as well as that no strings can have embedded nulls (like binary data).

The C++ language has just as much accessibility to the C Standard library, although string classes and objects can be used. Thus buffer overruns are still around. Most processes that run on your computer today are primarily written in C or C++.

Using managed code in .NET, a string is an object that has a length property. No null terminating byte is assumed.

What are the consequences of a crash? If it occurs in a User mode application, then that process is no longer running, but all other running processes on the machine are still valid. If it occurs in a kernel mode application, such as a device driver, all bets are off because the erroneous code had much higher access rights to the machine than a user mode program.

Except for video driver crashes, I haven’t rebooted my machines in years due to a crash.

Most of the security bulletins and Windows Updates are due to buffer overruns. If the standard library had been defined to pass in a maximum length parameter along with every string buffer, many of these security patches would never exist.