Index: lib/StaticAnalyzer/Checkers/MagentaHandleChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/MagentaHandleChecker.cpp +++ lib/StaticAnalyzer/Checkers/MagentaHandleChecker.cpp @@ -239,7 +239,7 @@ class MagentaHandleChecker : public Checker { + check::PostCall, check::PreStmt> { std::unique_ptr LeakBugType; std::unique_ptr DoubleReleaseBugType; std::unique_ptr UseAfterFreeBugType; @@ -255,6 +255,7 @@ void checkPostCall(const CallEvent &Call, CheckerContext &Ctx) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &Ctx) const; bool evalCall(const CallExpr *CE, CheckerContext &Ctx) const; + void checkPreStmt(const ReturnStmt *RS, CheckerContext &Ctx) const; ProgramStateRef checkPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, @@ -402,6 +403,7 @@ // Initialize the bug types. LeakBugType.reset( new BugType(this, "MX handle leak", "Magenta Handle Error")); + LeakBugType->setSuppressOnSink(true); DoubleReleaseBugType.reset( new BugType(this, "MX handle double release", "Magenta Handle Error")); UseAfterFreeBugType.reset( @@ -478,6 +480,23 @@ } } +void MagentaHandleChecker::checkPreStmt(const ReturnStmt *RS, + CheckerContext &Ctx) const { + ProgramStateRef State = Ctx.getState(); + const StackFrameContext *SFCtx = Ctx.getStackFrame(); + if (!SFCtx || !SFCtx->inTopFrame()) + return; + const FunctionDecl *FD = dyn_cast_or_null(SFCtx->getDecl()); + if (!FD) + return; + const IdentifierInfo *II = FD->getIdentifier(); + if (!II) + return; + + if (II->isStr("main")) + Ctx.generateSink(State, Ctx.getPredecessor()); +} + ProgramStateRef MagentaHandleChecker::checkPointerEscape( ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const { Index: test/Analysis/mxhandle.c =================================================================== --- test/Analysis/mxhandle.c +++ test/Analysis/mxhandle.c @@ -58,7 +58,20 @@ void useHandle02( MX_SYSCALL_PARAM_ATTR(handle_use) mx_handle_t *handle); +void noReturnFunc() __attribute__((__noreturn__)); + +int leakingFunc(int argc, char* argv[]) { + mx_handle_t sa, sb; + mx_channel_create(0, &sa, &sb); + return 1; +} + // End of declaration +int main(int argc, char* argv[]) { + if (argc == 2) + return leakingFunc(argc, argv); // Should not report any bugs here + return 0; +} void checkNoLeak01() { mx_handle_t sa, sb; @@ -207,6 +220,14 @@ mx_handle_close(sb); } +void checkNoLeak16() { + mx_handle_t sa, sb; + if (mx_channel_create(0, &sa, &sb) < 0) { + return; + } + noReturnFunc(); // Should not report any bugs here +} + void checkLeak01() { mx_handle_t sa, sb; mx_channel_create(0, &sa, &sb);