Attempting to modify SimpleStreamChecker for a different file API

I’m interested in trying out clang based code analysis. I saw the following slides:

http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf

So thought I’d try using tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp as a base for a similar check using our products’ internal file API.

In the sample, there’s the following code to get the close parameter:

void SimpleStreamChecker::checkPreCall

// Get the symbolic value corresponding to the file handle.
SymbolRef FileDesc = Call.getArgSVal(0).getAsSymbol();

I’ll want to do the same thing, with a small difference. My close API looks like:

struct my_filehandle { int fh ; … } ;

int myclose( my_filehandle & fh )

so once I get the close parameter symbol, I have the task of looking up the actual file descriptor.

I’m guessing that I have to:

  1. check it for -1 instead of NULL (hardcoding the assumption for now that I’m only running this checking on Unix)

I’ve changed:

ConditionTruthVal OpenFailed = CMgr.isNull(State, Sym);

to call isNegative(), which I think will do the trick, provided I first:

  1. find the symbol that the myclose() parameter is a reference to.

  2. look up the my_filehandle::fh value out of that symbol.

  3. put that ::fh symbol in the checker stream instead of the FILE*.

Anybody willing to give any tips on how to do 2-3 above.

Peeter,

For the purposes of tracking the state of the file, you could just track the symbol representing the struct, not the file handle inside of it. I would suggest getting this working first.

In order to get rid of the false positive, you should build an SVal expression representing “fh.fh == -1” and use ConstraintManager::assumeDual() to check if it’s true/false/underconstrained in the given state, similarly to how checkNull() is implemented. (I don’t think there is isNegative() helper function; but you are welcome to add it.)

When building the expression, you can use the helper routines in the SValBuilder (ex: evalBinOp). You should be using MemRegionManager::getFieldRegion to represent the field of the struct. (Ex: See how BoolAssignmentChecker.cpp is building an expression and uses assumeDual.)

Cheers,
Anna.