[cfe-commits] r146533 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp test/Analysis/taint-tester.c

Anna Zaks ganna at apple.com
Tue Dec 13 16:56:02 PST 2011


Author: zaks
Date: Tue Dec 13 18:56:02 2011
New Revision: 146533

URL: http://llvm.org/viewvc/llvm-project?rev=146533&view=rev
Log:
[analyzer] Mark output of fscanf and fopen as tainted.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
    cfe/trunk/test/Analysis/taint-tester.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp?rev=146533&r1=146532&r2=146533&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Tue Dec 13 18:56:02 2011
@@ -39,6 +39,7 @@
   typedef void (GenericTaintChecker::*FnCheck)(const CallExpr *,
                                                CheckerContext &C) const;
   void processScanf(const CallExpr *CE, CheckerContext &C) const;
+  void processFscanf(const CallExpr *CE, CheckerContext &C) const;
   void processRetTaint(const CallExpr *CE, CheckerContext &C) const;
 
 public:
@@ -62,8 +63,14 @@
   // Set the evaluation function by switching on the callee name.
   FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
     .Case("scanf", &GenericTaintChecker::processScanf)
+    .Case("fscanf", &GenericTaintChecker::processFscanf)
+    .Case("sscanf", &GenericTaintChecker::processFscanf)
+    // TODO: Add support for vfscanf & family.
     .Case("getchar", &GenericTaintChecker::processRetTaint)
     .Case("getenv", &GenericTaintChecker::processRetTaint)
+    .Case("fopen", &GenericTaintChecker::processRetTaint)
+    .Case("fdopen", &GenericTaintChecker::processRetTaint)
+    .Case("freopen", &GenericTaintChecker::processRetTaint)
     .Default(NULL);
 
   // If the callee isn't defined, it is not of security concern.
@@ -108,7 +115,7 @@
 void GenericTaintChecker::processScanf(const CallExpr *CE,
                                        CheckerContext &C) const {
   const ProgramState *State = C.getState();
-  assert(CE->getNumArgs() == 2);
+  assert(CE->getNumArgs() >= 2);
   SVal x = State->getSVal(CE->getArg(1));
   // All arguments except for the very first one should get taint.
   for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
@@ -120,7 +127,29 @@
       State = State->addTaint(Sym);
   }
   C.addTransition(State);
+}
+
+/// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
+/// and arg 1 should get taint.
+void GenericTaintChecker::processFscanf(const CallExpr *CE,
+                                        CheckerContext &C) const {
+  const ProgramState *State = C.getState();
+  assert(CE->getNumArgs() >= 2);
 
+  // Check is the file descriptor is tainted.
+  if (!State->isTainted(CE->getArg(0)))
+    return;
+
+  // All arguments except for the first two should get taint.
+  for (unsigned int i = 2; i < CE->getNumArgs(); ++i) {
+    // The arguments are pointer arguments. The data they are pointing at is
+    // tainted after the call.
+    const Expr* Arg = CE->getArg(i);
+    SymbolRef Sym = getPointedToSymbol(C, Arg);
+    if (Sym)
+      State = State->addTaint(Sym);
+  }
+  C.addTransition(State);
 }
 
 void GenericTaintChecker::processRetTaint(const CallExpr *CE,

Modified: cfe/trunk/test/Analysis/taint-tester.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-tester.c?rev=146533&r1=146532&r2=146533&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/taint-tester.c (original)
+++ cfe/trunk/test/Analysis/taint-tester.c Tue Dec 13 18:56:02 2011
@@ -54,6 +54,10 @@
   int tx = xy.x; // expected-warning {{tainted}}
   int ty = xy.y; // FIXME: This should be tainted as well.
   char ntz = xy.z;// no warning
+  // Now, scanf scans both.
+  scanf("%d %d", &xy.y, &xy.x);
+  int ttx = xy.x; // expected-warning {{tainted}}
+  int tty = xy.y; // expected-warning {{tainted}}
 }
 
 void BitwiseOp(int in, char inn) {
@@ -80,3 +84,34 @@
     }
 }
 
+struct _IO_FILE {
+  unsigned fakeField1;
+  char fakeField2;
+};
+typedef struct _IO_FILE FILE;
+extern struct _IO_FILE *stdin;
+extern struct _IO_FILE *stdout;
+extern struct _IO_FILE *stderr;
+int fscanf(FILE *restrict stream, const char *restrict format, ...);
+int fprintf(FILE *stream, const char *format, ...);
+int fclose(FILE *stream);
+FILE *fopen(const char *path, const char *mode);
+
+int fscanfTest(void) {
+  FILE *fp;
+  char s[80];
+  int t;
+
+  if((fp=fopen("test", "w")) == 0) // expected-warning 3 {{tainted}}
+    return 1;
+  // TODO: Have to mark stdin as tainted.
+  fscanf(stdin, "%s%d", s, &t);
+  fprintf(fp, "%s %d", s, t); // expected-warning 1 {{tainted}}
+  fclose(fp); // expected-warning 1 {{tainted}}
+
+  if((fp=fopen("test","r")) == 0) // expected-warning 3 {{tainted}}
+    return 1;
+  fscanf(fp, "%s%d", s, &t); // expected-warning 1 {{tainted}}
+  fprintf(stdout, "%s %d", s, t); // expected-warning 1 {{tainted}}
+  return 0;
+}





More information about the cfe-commits mailing list