PREfast for Drivers is a compile-time static verification tool that detects basic coding errors in C and C++ programs and specialized errors in driver code. PREfast for Drivers is available as a stand-alone tool in the WDK.
PREfast can be extremely valuable as a driver development tool because it can find errors that are difficult to test and debug and it can identify assumptions that might not always be valid. You can use PREfast to analyze your code as soon as the code can be compiled-it does not have to be linked or run. This enables PREfast to find mistaken assumptions and errors early-before they propagate through the program-when errors are easier to fix and typically have less impact on the development schedule.
PREfast for Drivers is licensed only as a driver development tool. You should not use it to test user-mode applications.
PREfast for Drivers includes a component that detects common basic coding errors in C and C++ programs ("PREfast"), and a specialized driver module that is designed to detect errors in kernel-mode driver code (that's the "for Drivers" part). For simplicity, this chapter refers to "PREfast for Drivers" as simply "PREfast."
If you use Visual Studio, you may already have used PREfast. The C/C++ Code Analysis tool in Microsoft Visual Studio Team System, Team Edition for Developers, includes the same functionality as PREfast in the /analyze option, without the specialized driver functionality.
PREfast intercepts the Build utility's call to the regular cl compiler-cl.exe-and then runs an intercept compiler that analyzes the source code and creates a log file of error and warning messages. PREfast simulates execution of possible code paths on a function-by-function basis, including code paths that are rarely executed during runtime. It checks possible code paths against a set of rules that identify potential errors or bad coding practices, and it logs warnings for code that appears to break the rules.
For example, PREfast can identify uninitialized variables that might be used in subsequent code, such as a variable that is initialized inside a loop. If the loop is executed zero times, the variable remains uninitialized, which creates a potentially serious problem that should be corrected. If PREfast cannot exclude a code path in which this situation might occur, it issues a warning.
Note For better performance, PREfast limits the number of paths it checks to a default maximum. Use the /maxpaths command line option to increase the maximum number of paths PREfast can check.
PREfast can detect several significant categories of potential errors in your code as soon as you can compile it, including the following:
Memory Potential memory leaks, dereferenced NULL pointers, access to uninitialized memory, excessive use of the kernel-mode stack, and improper use of pool tags.
Resources Failure to release resources such as locks, resources that a function holds when it should not, and resources that a function incorrectly fails to hold when it should.
Function usage Potentially incorrect usage of certain functions, function arguments that appear to be incorrect, possible argument type mismatches for functions that do not strictly check types, possible use of certain obsolete functions, and function calls at a potentially incorrect IRQL.
Floating-point state Failure to protect floating-point hardware state in a driver and attempting to restore floating-point state after saving it at a different IRQL.
Precedence rules Code that might not behave as the programmer intended because of the precedence rules of C.
Kernel-mode coding practices Coding practices that can cause errors, such as modifying an opaque MDL structure, failing to examine the value of a variable set by a called function, using C runtime library string manipulation functions rather than the safe string functions that are defined in Ntstrsafe.h, and some misuses of pageable code segments.
Driver-specific coding practices Specific operations that are often a source of errors in kernel-mode drivers, such as copying a whole IRP without modifying members or saving a pointer to a string or structure argument instead of copying an argument in a DriverEntry routine.
PREfast is highly effective at detecting many errors that are difficult to find by other means, and it usually reports errors in a way that makes them easier to fix. This helps to free your test resources to concentrate on finding and fixing deeper, more significant bugs. However, PREfast does not find every possible error or even all possible instances of the errors it was designed to detect, so passing PREfast does not necessarily mean that your code is free of errors. Be sure to thoroughly test your code with all available tools, including Driver Verifier and Static Driver Verifier. See Chapter 21, "Tools for Testing WDF Drivers," for details.