Buffer Overruns: Redemption steps

There is a variety of techniques to help you avoid buffer overruns, and a number of other techniques to reduce the damage it can cause. This excerpt from Chapter 1 of The 19 Deadly Sins of Software Security takes a look at how you can improve your code.

The 19 Deadly Sins of Software Security The following excerpt is from Chapter 1 of "The 19 Deadly Sins of Software Security" written by Michael Howard, David LeBlanc and John Viega. Click for the complete book excerpt series or visit McGraw-Hill to purchase the book.

Redemption steps

The road to buffer overrun redemption is long and filled with potholes. We discuss a wide variety of techniques that help you avoid buffer overruns, and a number of other techniques that reduce the damage buffer overruns can cause. Let's look at how you can improve your code.

    Replace dangerous string handling functions
    Audit allocations
    Check loops and array accesses
    Replace C string buffers with C++ strings
    Replace static arrays with STL containers
    Use analysis tools

  Replace dangerous string handling functions  Return to Table of Contents

You should, at minimum, replace unsafe functions like strcpy, strcat, and sprintf with the counted versions of each of these functions. You have a number of choices of what to replace them with. Keep in mind that older counted functions have interface problems, and ask you to do arithmetic in many cases to determine parameters. As you'll see in Sin 3, computers aren't as good at math as you might hope. Newer libraries like strsafe, the Safe CRT (C run-time library) that will be shipped in Microsoft Visual Studio (and is on a fast track to become part of the ANSI C/C++ standard), and strlcat/strlcpy for *nix. You also need to take care with how each of these functions handle termination and truncation of strings. Some functions guarantee null termination, but most of the older counted functions do not. The Microsoft Office group's experience with replacing unsafe string handling functions for the Office 2003 release was that the regression rate (new bugs caused per fix) was extremely low, so don't let fear of regressions stop you.

  Audit allocations  Return to Table of Contents

Another source of buffer overruns comes from arithmetic errors. Learn about integer overflows in Sin 3, and audit all your code where allocation sizes are calculated.

  Check loops and array accesses  Return to Table of Contents

A third way that buffer overruns are caused is not properly checking termination in loops, and not properly checking array bounds prior to write access. This is one of the most difficult areas, and you will find that, in some cases, the problem and the earth-shattering-kaboom are in completely different modules.

  Replace C string buffers with C++ strings  Return to Table of Contents

This is more effective than just replacing the usual C calls, but can cause tremendous amounts of change in existing code, particularly if the code isn't already compiled as C++. You should also be aware of and understand the performance characteristics of the STL container classes. It is very possible to write high-performance STL code, but like many other aspects of programming, a failure to Read The Fine Manual (RTFM) will often result in less than optimal results. The most common replacement is to use the STL std::string or std:wstring template classes.

  Replace static arrays with STL containers  Return to Table of Contents

All of the problems noted above apply to STL containers like vector, but an additional problem is that not all implementations of the vector::iterator construct check for out of bounds access. This measure may help, and the author finds that using the STL makes it possible for him to write correct code more quickly, but be aware that this isn't a silver bullet.

  Use analysis tools  Return to Table of Contents

There are some good tools coming on the market that analyze C/C++ code for security defects; examples include Coverity, PREfast, and Klocwork. There is a link to a list in the "Other Resources" section. Visual Studio .NET 2005 will include PREfast and another tool called Source code Annotation Language (SAL) to help track down security defects such as buffer overruns. The best way to describe SAL is by way of code.

In the (silly) example that follows, you know the relationship between the data and count arguments: data is count bytes long. But the compiler doesn't know; it just sees a char * and a size_t.

void *DoStuff(char *data, size_t count) {
     static char buf[32];
     return memcpy(buf, data, count);

This code looks OK (ignoring the fact we loath returning static buffers, but humor us). However, if count is larger that 32, then you have a buffer overrun. A SAL annotated version of this would catch the bug:

void *DoStuff(__in_ecount(count) char *data, size_t count) {
     static char buf[32];
     return memcpy(buf, data, count);

This is because the compiler and/or PREfast now knows that data and count are tightly related.

Click for the next excerpt in this series: Extra defensive measures

Click for the book excerpt series or visit McGraw-Hill to purchase the book.

Dig Deeper on Enterprise software

Start the conversation

Send me notifications when other members comment.

Please create a username to comment.