]> granicus.if.org Git - clang/commitdiff
[analyzer] UnixAPI: Check when open(2) is called with more than three arguments.
authorJordan Rose <jordan_rose@apple.com>
Wed, 20 Aug 2014 16:58:03 +0000 (16:58 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 20 Aug 2014 16:58:03 +0000 (16:58 +0000)
Patch by Daniel Fahlgren.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216078 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
test/Analysis/unix-api.c [new file with mode: 0644]

index 4887d804c60724f83841e4ca66428ab093b98e7e..e7626ca24b6a65b68732541b004a2304c3ca18ad 100644 (file)
@@ -62,6 +62,10 @@ private:
       return;
     BT.reset(new BugType(this, name, categories::UnixAPI));
   }
+  void ReportOpenBug(CheckerContext &C,
+                     ProgramStateRef State,
+                     const char *Msg,
+                     SourceRange SR) const;
 };
 } //end anonymous namespace
 
@@ -69,7 +73,35 @@ private:
 // "open" (man 2 open)
 //===----------------------------------------------------------------------===//
 
+void UnixAPIChecker::ReportOpenBug(CheckerContext &C,
+                                   ProgramStateRef State,
+                                   const char *Msg,
+                                   SourceRange SR) const {
+  ExplodedNode *N = C.generateSink(State);
+  if (!N)
+    return;
+
+  LazyInitialize(BT_open, "Improper use of 'open'");
+
+  BugReport *Report = new BugReport(*BT_open, Msg, N);
+  Report->addRange(SR);
+  C.emitReport(Report);
+}
+
 void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
+  ProgramStateRef state = C.getState();
+
+  if (CE->getNumArgs() < 2) {
+    // The frontend should issue a warning for this case, so this is a sanity
+    // check.
+    return;
+  } else if (CE->getNumArgs() > 3) {
+    ReportOpenBug(C, state,
+                  "Call to 'open' with more than three arguments",
+                  CE->getArg(3)->getSourceRange());
+    return;
+  }
+
   // The definition of O_CREAT is platform specific.  We need a better way
   // of querying this information from the checking environment.
   if (!Val_O_CREAT.hasValue()) {
@@ -85,15 +117,6 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
     }
   }
 
-  // Look at the 'oflags' argument for the O_CREAT flag.
-  ProgramStateRef state = C.getState();
-
-  if (CE->getNumArgs() < 2) {
-    // The frontend should issue a warning for this case, so this is a sanity
-    // check.
-    return;
-  }
-
   // Now check if oflags has O_CREAT set.
   const Expr *oflagsEx = CE->getArg(1);
   const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
@@ -122,18 +145,10 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
     return;
 
   if (CE->getNumArgs() < 3) {
-    ExplodedNode *N = C.generateSink(trueState);
-    if (!N)
-      return;
-
-    LazyInitialize(BT_open, "Improper use of 'open'");
-
-    BugReport *report =
-      new BugReport(*BT_open,
-                            "Call to 'open' requires a third argument when "
-                            "the 'O_CREAT' flag is set", N);
-    report->addRange(oflagsEx->getSourceRange());
-    C.emitReport(report);
+    ReportOpenBug(C, trueState,
+                  "Call to 'open' requires a third argument when "
+                  "the 'O_CREAT' flag is set",
+                  oflagsEx->getSourceRange());
   }
 }
 
diff --git a/test/Analysis/unix-api.c b/test/Analysis/unix-api.c
new file mode 100644 (file)
index 0000000..4146822
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.API -verify %s
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+int open(const char *, int, ...);
+int close(int fildes);
+
+void open_1(const char *path) {
+  int fd;
+  fd = open(path, O_RDONLY); // no-warning
+  if (fd > -1)
+    close(fd);
+}
+
+void open_2(const char *path) {
+  int fd;
+  int mode = 0x0;
+  fd = open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than three arguments}}
+  if (fd > -1)
+    close(fd);
+}