[cfe-dev] [analyzer] Expressing dependencies between arguments and return values
Peter Wu via cfe-dev
cfe-dev at lists.llvm.org
Sun May 6 15:07:31 PDT 2018
Hi!
I just got started with writing a Clang Static Analyzer checker,
primarily to detect these classes of issues in C:
- allocator/deallocator mismatch: e.g. "g_malloc" must be accompanied by
"g_free" and not "free".
- memory leak due to allocator mismatch: e.g. "g_list_new" must be
accompanied by "g_list_free" and not "g_free".
- memory leaks and use-after-free issues in general.
I have an initial version working based on Anna's and Jordan's talk, but
am looking at methods to reduce false positives and false negatives.
Consider this example:
void checkIdentityFunctionLeak() {
char *p = g_strdup("");
char *q = g_strdelimit(p, "_", '-');
} // expected-warning {{Memory leak}}
To avoid false positives with memleak reporting, I added a pointerEscape
callback that removes symbols. This however has as side-effect that "p"
in the above example is not reported as leaked. "g_strdelimit" can be
modelled as an identity function (p==q), but my attempt to express this
constraint in the PostCall callback failed:
SValBuilder &svalBuilder = C.getSValBuilder();
ProgramStateRef State = C.getState();
SVal Arg0 = Call.getArgSVal(0);
SVal RetVal = Call.getReturnValue();
DefinedOrUnknownSVal arg0 = Arg0.castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal retVal = RetVal.castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal PtrEQ = svalBuilder.evalEQ(State, arg0, retVal);
State = State->assume(PtrEQ, true);
C.addTransition(State);
While the debug.ViewExplodedGraph option shows that the symbols are
assumed to be the same in the CallExpr node:
conj_$1{gpointer} : { [1, 18446744073709551615] }
(conj_$4{gchar *}) - (conj_$1{gpointer}) : { [0, 0] }
this range information is somehow lost in the next nodes.
Another example which is currently not caught either (strstr returns an
address from the region of "p"):
int main() {
char *p = strdup("xyz");
if (!p) return 1;
char *p2 = strstr(p, "z");
free(p);
puts(p2); // expected-warning {{Use-after-free}}
}
Have I misunderstood something in modelling this? Is it possible to
express dependencies between the return value and the arguments of a
library function?
--
Kind regards,
Peter Wu
https://lekensteyn.nl
More information about the cfe-dev
mailing list