haowei created this revision.
Herald added a subscriber: xazax.hun.

This patch will suppress handle leak warnings if the path of a bug reported by 
MagentaHandleChecker will reach a no return function or will reach the end of 
main function. As these two scenarios mean program crash and the leaked handle 
will be recycled by OS, there is no point to report these bugs.


https://reviews.llvm.org/D36251

Files:
  lib/StaticAnalyzer/Checkers/MagentaHandleChecker.cpp
  test/Analysis/mxhandle.c


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);
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::DeadSymbols, check::PointerEscape, eval::Call,
-                     check::PostCall> {
+                     check::PostCall, check::PreStmt<ReturnStmt>> {
   std::unique_ptr<BugType> LeakBugType;
   std::unique_ptr<BugType> DoubleReleaseBugType;
   std::unique_ptr<BugType> 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<FunctionDecl>(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);
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::DeadSymbols, check::PointerEscape, eval::Call,
-                     check::PostCall> {
+                     check::PostCall, check::PreStmt<ReturnStmt>> {
   std::unique_ptr<BugType> LeakBugType;
   std::unique_ptr<BugType> DoubleReleaseBugType;
   std::unique_ptr<BugType> 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<FunctionDecl>(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 {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to