]> granicus.if.org Git - clang/commitdiff
[analyzer] Catch the first taint propagation implied buffer overflow.
authorAnna Zaks <ganna@apple.com>
Wed, 16 Nov 2011 19:58:17 +0000 (19:58 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 16 Nov 2011 19:58:17 +0000 (19:58 +0000)
Change the ArrayBoundCheckerV2 to be more aggressive in reporting buffer overflows
when the offset is tainted. Previously, we did not report bugs when the state was
underconstrained (not enough information about the bound to determine if there is
an overflow) to avoid false positives. However, if we know that the buffer
offset is tainted - comes in from the user space and can be anything, we should
report it as a bug.

+ The very first example of us catching a taint related bug.
This is the only example we can currently handle. More to come...

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

lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
test/Analysis/taint-generic.c [new file with mode: 0644]

index 59733564fb6a64ba4e2c73c01a882d6c3e675898..041e74e764fe7bcd6db1be0d55c2db5bffad8db9 100644 (file)
@@ -153,9 +153,17 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
     const ProgramState *state_exceedsUpperBound, *state_withinUpperBound;
     llvm::tie(state_exceedsUpperBound, state_withinUpperBound) =
       state->assume(*upperboundToCheck);
+
+    // If we are under constrained and the index variables are tainted, report.
+    if (state_exceedsUpperBound && state_withinUpperBound) {
+      if (state->isTainted(rawOffset.getByteOffset()))
+        reportOOB(checkerContext, state_exceedsUpperBound, OOB_Excedes);
+        return;
+    }
   
-    // Are we constrained enough to definitely exceed the upper bound?
-    if (state_exceedsUpperBound && !state_withinUpperBound) {
+    // If we are constrained enough to definitely exceed the upper bound, report.
+    if (state_exceedsUpperBound) {
+      assert(!state_withinUpperBound);
       reportOOB(checkerContext, state_exceedsUpperBound, OOB_Excedes);
       return;
     }
@@ -277,9 +285,9 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const ProgramState *state,
         offset = addValue(state,
                           getValue(offset, svalBuilder),
                           scaleValue(state,
-                                     cast<NonLoc>(index),
-                                     astContext.getTypeSizeInChars(elemType),
-                                     svalBuilder),
+                          cast<NonLoc>(index),
+                          astContext.getTypeSizeInChars(elemType),
+                          svalBuilder),
                           svalBuilder);
 
         if (offset.isUnknownOrUndef())
diff --git a/test/Analysis/taint-generic.c b/test/Analysis/taint-generic.c
new file mode 100644 (file)
index 0000000..9179a57
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1  -analyze -analyzer-checker=experimental.security.taint,experimental.security.ArrayBoundV2 -verify %s
+
+int scanf(const char *restrict format, ...);
+int getchar(void);
+
+#define BUFSIZE 10
+
+int Buffer[BUFSIZE];
+void bufferFoo1(void)
+{
+  int n;
+  scanf("%d", &n);
+  Buffer[n] = 1; // expected-warning {{Out of bound memory access }}
+}