]> granicus.if.org Git - clang/commitdiff
[analyzer] Add socket API as a source of taint.
authorAnna Zaks <ganna@apple.com>
Fri, 20 Jan 2012 00:11:19 +0000 (00:11 +0000)
committerAnna Zaks <ganna@apple.com>
Fri, 20 Jan 2012 00:11:19 +0000 (00:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148518 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
test/Analysis/taint-generic.c

index 5a962ab7d15757a068ef75b661ac124e7da5e725..c3cd3b05c5a2e3efd05bc6cab5c67a18edd90676 100644 (file)
@@ -76,6 +76,7 @@ private:
   typedef const ProgramState *(GenericTaintChecker::*FnCheck)(const CallExpr *,
                                                        CheckerContext &C) const;
   const ProgramState *postScanf(const CallExpr *CE, CheckerContext &C) const;
+  const ProgramState *postSocket(const CallExpr *CE, CheckerContext &C) const;
   const ProgramState *postRetTaint(const CallExpr *CE, CheckerContext &C) const;
 
   /// Taint the scanned input if the file is tainted.
@@ -207,6 +208,8 @@ GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
     .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
     .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
     .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("read", TaintPropagationRule(0, 2, 1, true))
+    .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
     .Default(TaintPropagationRule());
 
   if (!Rule.isNull())
@@ -360,6 +363,7 @@ void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
     .Case("fopen", &GenericTaintChecker::postRetTaint)
     .Case("fdopen", &GenericTaintChecker::postRetTaint)
     .Case("freopen", &GenericTaintChecker::postRetTaint)
+    .Case("socket", &GenericTaintChecker::postSocket)
     .Default(0);
 
   // If the callee isn't defined, it is not of security concern.
@@ -501,6 +505,23 @@ const ProgramState *GenericTaintChecker::preFscanf(const CallExpr *CE,
   return 0;
 }
 
+
+// If argument 0(protocol domain) is network, the return value should get taint.
+const ProgramState *GenericTaintChecker::postSocket(const CallExpr *CE,
+                                                    CheckerContext &C) const {
+  assert(CE->getNumArgs() >= 3);
+  const ProgramState *State = C.getState();
+
+  SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
+  StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
+  // White list the internal communication protocols.
+  if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
+      DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
+    return State;
+  State = State->addTaint(CE, C.getLocationContext());
+  return State;
+}
+
 const ProgramState *GenericTaintChecker::postScanf(const CallExpr *CE,
                                                    CheckerContext &C) const {
   const ProgramState *State = C.getState();
@@ -627,6 +648,12 @@ bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
   unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
     .Case("system", 0)
     .Case("popen", 0)
+    .Case("execl", 0)
+    .Case("execle", 0)
+    .Case("execlp", 0)
+    .Case("execv", 0)
+    .Case("execvp", 0)
+    .Case("execvP", 0)
     .Default(UINT_MAX);
 
   if (ArgNum == UINT_MAX)
index c50f7193445bed843dc5ac76c86ad584d6699a8e..47bdb4e4c9c97ffc7bec5ec62c8727f4e729761c 100644 (file)
@@ -148,5 +148,26 @@ void testTaintedBufferSize() {
   // If both buffers are trusted, do not issue a warning.
   char *dst2 = (char*)malloc(ts*sizeof(char)); // expected-warning {{Tainted data is used to specify the buffer size}}
   strncat(dst2, dst, ts); // no-warning
+}
 
+#define AF_UNIX   1   /* local to host (pipes) */
+#define AF_INET   2   /* internetwork: UDP, TCP, etc. */
+#define AF_LOCAL  AF_UNIX   /* backward compatibility */
+#define SOCK_STREAM 1
+int socket(int, int, int);
+size_t read(int, void *, size_t);
+int  execl(const char *, const char *, ...);
+
+void testSocket() {
+  int sock;
+  char buffer[100];
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, buffer, 100);
+  execl(buffer, "filename", 0); // expected-warning {{Tainted data passed to a system call}}
+
+  sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+  read(sock, buffer, 100);
+  execl(buffer, "filename", 0); // no-warning
 }
+