Before your project begins, or if you’re already partway through development, you should identify which static analysis tools you will use to find bugs missed through code review. During the development of Windows Vista, we used numerous source code analysis tools, including PREfast, which is included in Visual Studio 2005 Team Suite or any of the Visual Studio Team System products. You can invoke the PREfast engine through the /analyze compiler switch.
Application Verifier was used to verify native applications at run time, and we used FXCop for managed code to verify compliance with SDL requirements.
At a minimum, for native code written in C or C++, you should triage all buffer overrun– and integer overflow–related warnings regardless of which compiler and static analysis tools you use. Additionally, there are compiler warnings that aren’t enabled until you compile at warning level 4. Some of the additional warnings have significant security implications and aren’t replicated in PREfast because it doesn’t make sense to provide redundant warnings. An examination of a large codebase where many of the integer-related warnings had been disabled found potentially exploitable conditions in about 20 percent of the places where the warning had been masked.
The /analyze warnings in Table 1-1 should be flagged for triage to determine if they are real security bugs or not. And please err on the side of caution! A full list of static analysis warnings is available in “Code Analysis for C/C++ Warnings” on MSDN (MSDN 2005).
Warning | Description |
---|---|
4018 | “Expression”: signed/unsigned mismatch |
4389 | “Operator”: signed/unsigned mismatch |
4244 | “Conversion”: conversion from “type1” to “type2”; possible loss of data |
4996 | “Function”: was declared deprecated |
6029 | Possible buffer overrun in call to <function>: use of unchecked value |
6053 | Call to <function>: may not zero-terminate string <variable> |
6057 | Buffer overrun due to number of characters/number of bytes mismatch in call to <function> |
6059 | Incorrect length parameter in call to <function>: pass the number of remaining characters, not the buffer size of <variable> |
6200 | Index <name> is out of valid index range <min> to <max> for non-stack buffer <variable> |
6201 | Buffer overrun for <variable>, which is possibly stack allocated: index <name> is out of valid index range <min> to <max> |
6202 | Buffer overrun for <variable>, which is possibly stack allocated, in call to <function>: length <size> exceeds buffer size <max> |
6203 | Buffer overrun for buffer <variable> in call to <function>: length <size> exceeds buffer size |
6204 | Possible buffer overrun in call to <function>: use of unchecked parameter <variable> |
6209 | Using “sizeof<variable1>” as parameter <number> in call to <function> where <variable2> may be an array of wide characters; did you intend to use character count rather than byte count? |
6248 | Setting a SECURITY_DESCRIPTOR’s DACL to NULL will result in an unprotected object |
6383 | Setting a SECURITY_DESCRIPTOR’s DACL to NULL will result in an unprotected object |
Also, make sure you review code, looking for constructs that disable any of these warnings. For example, the following code will disable all 6204 warnings:
#pragma warning ( disable : 6204 )
A more correct way to suppress warnings is to use the following, which only suppresses the warning on the line of code following the #pragma.
#pragma warning ( suppress : 6204 )
Run your native application (written in an unmanaged language such as C or C++) under AppVerif set to use “Basic Tests,” and triage all the warnings you see. There are two versions of AppVerif: one is included with Visual Studio 2005, and the other is a free download. It is recommended that you use the free download because it performs many more checks than the version in Visual Studio.
Load your managed assemblies into FxCop and then triage all the security rule messages.