Security improvements in VC++ 2005 and the C standards committee

Last Friday I returned from the C standards committee meeting in Mont Tremblant, Canada at a beautiful hotel resort. These meetings are pretty fascinating, because of the diverse set of smart people they draw in. Even though C is quite stable at this point, there are always a range of interesting feature proposals and defect reports discussed.

I’ve been representing Visual C++ on this committee for a couple of years now, as part of my work on the Safe C and C++ Libraries [which you’ll hear more about]. My team started this work late in 2002, and I first took this to the committee back in April of 2003. There was very positive feedback, and over the last two years we’ve worked with the committee on a technical report which is now coming close to completion. The great thing about working with the committee on this project has been the opportunity to take some work we had done, get a lot of constructive and helpful feedback from a group of very knowledgeable people, and build up a standard which will help the whole C and C++ community migrate their existing code to work more safely. It’s been very fun, and a great learning experience.

You can find our implementation of these C functions, along with many others (C++, MFC, ATL), plus other safely improvements in Visual C++ 2005. We’ve tried to think what we could do to make your program safer, and that’s led to a bunch of features beyond the actual functions in question. I’ll talk about a few of these over the next few days.

One of my favourite features is our ability to automagically transform some less safe calls into more safe ones. For example, imagine that you have this code

void foo(char *str)
{

            char buf[20];

            strcpy(buf, str);

}

At this point, I hope that everyone reading already knows that this is an unsafe function. Function foo makes no attempt to ensure that str doesn’t overrun its buffer. VC8 is smart, and knows that strcpy isn’t safe, so it issues a warning when you compile this code, telling you that strcpy is unsafe and that you should use our new strcpy_s function instead. And you could do that. A basic fix for this function would be:

void foo(char *str)
{

            char buf[20];

            strcpy_s(buf, _countof(buf), str);

}

This fix isn’t very tolerant (since the new code still assumes that buf is large enough – the program’s invalid_parameter_handler will abort inside strcpy_s if not). A deep question when making this kind of code safer is whether you need a string to be truncated or to be But it’s completely safe – this code will no longer buffer overrun.

But if you’re compiling C++, you can do something much simpler. You can simply put /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1 on the compiler command line, and the original code will compile without a warning. We’ve used The Magic of Templates to transform the code into the safe code automatically.

These templates are not over-zealous. They only do what they know to be safe. For example, if you give us a function like this:

void bar(char *dest, char *src)
{

            strcpy(dest, src);

}

you'll still get the same warning you got above before you added the /D switch. The templates notice that dest is a pointer (not an array) whose size is unknown. So they allow the normal compiler warning to happen, instead of interposing themselves.

Clearly, the safest way to fix code like this is to switch to the use of a decent string class (I own at least two of these – std::string and CStringT). But much code won’t be able to be rewritten this deeply any time soon. So features like this one are intended to help those of you with large, existing code-bases to move your code forward to be safer, in much the same way that we at Microsoft have had to do over the last 6 years. We’ve taken all that we’ve learnt from our security pushes and secure development practices, and applied it to our library changes. We hope you find them helpful.

Write to me and let me know.

Martyn

[Edit 10/14/2005 MartynL: fix link to C starndard committee doc].