Current version

v1.10.4 (stable)


Main page
Archived news
Plugin SDK
Knowledge base
Contact info
Other projects


Blog Archive

Weird PREfast problem

For a while now, Microsoft has made the /analyze mode of the VC++ compiler -- a.k.a. PREfast -- available through the Windows SDK. I've run it a couple of times before out of curiosity, and it's found a few interesting null pointer deference paths, but like most static analysis tools it has a huge problem with spewing dubious results when you first sic it on a codebase. This mainly results from C/C++ being an unexpressive language, and while you can fix that and improve the results by peppering your source code with annotations, it's not something I've gotten around to doing given the time and risk involved.

One of the problems specifically with PREfast is that it seems to have a habit of issuing bogus warnings about bad array indices. For instance, take this simplified code:

void foo(int *p) {
static const int data[16] = {0};
    for(int i=0; i<16; ++i) {
if (i != 0)
p[i] = data[i-1];

The if() clearly prevents any pointer deferencing when i = 0, but PREfast gives this output:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

oops.cpp(6) : warning C6200: Index '-1' is out of valid index range '0' to '15' for non-stack buffer 'int const * const `void __cdecl foo(int *)'::`2'::data'

All such warnings turned out to be impossible cases in code. I tracked down some of them to PREfast being confused by an assert macro, but this is the one case I've been able to pin down to the static analyzer ignoring an obvious prohibition in control flow. A related problem is that it isn't very good about indicating how sure it is about a buffer overflow, so instead of indicating that it has found a possible overflow, it assumes some rather large numbers:

warning C6201: Index '18446744073709551615' is out of valid index range '0' to '255' for possibly stack allocated buffer 'mStackLevels'

Kind of hard to do that when indexing with a uint8_t in 32-bit code.

I did try cppcheck once as a possible alternative for a free code analysis tool. It was a bit better about false positives and focused more on structural issues rather than dynamic ones, but its problem was speed -- due to a combination of not supporting precompiled headers and slow parsing performance it was taking over five minutes per .cpp file. It turned out to be primarily due to an unexpectedly mediocre implementation of std::string::operator==(const char *) in the VC++ STL and an O(N^2) implementation of a core string pattern matching algorithm, but even after fixing those it was still prohibitively slow.


This blog was originally open for comments when this entry was first posted, but was later closed and then removed due to spam and after a migration away from the original blog software. Unfortunately, it would have been a lot of work to reformat the comments to republish them. The author thanks everyone who posted comments and added to the discussion.