aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h2
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp7
-rw-r--r--test/Analysis/taint-generic.c20
4 files changed, 36 insertions, 3 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index ad76f39187..8431b0e739 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -94,6 +94,8 @@ public:
return symbol_iterator(this);
}
static symbol_iterator symbol_end() { return symbol_iterator(); }
+
+ unsigned computeComplexity() const;
};
typedef const SymExpr* SymbolRef;
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index a61cbe8761..d286f495cd 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -204,15 +204,19 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
const SymExpr *symLHS = LHS.getAsSymExpr();
const SymExpr *symRHS = RHS.getAsSymExpr();
+ // TODO: When the Max Complexity is reached, we should conjure a symbol
+ // instead of generating an Unknown value and propagate the taint info to it.
+ const unsigned MaxComp = 10000; // 100000 28X
- if (symLHS && symRHS)
+ if (symLHS && symRHS &&
+ (symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp)
return makeNonLoc(symLHS, Op, symRHS, ResultTy);
- if (symLHS)
+ if (symLHS && symLHS->computeComplexity() < MaxComp)
if (const nonloc::ConcreteInt *rInt = dyn_cast<nonloc::ConcreteInt>(&RHS))
return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
- if (symRHS)
+ if (symRHS && symRHS->computeComplexity() < MaxComp)
if (const nonloc::ConcreteInt *lInt = dyn_cast<nonloc::ConcreteInt>(&LHS))
return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 5fee9afc08..0bc192d645 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -164,6 +164,13 @@ void SymExpr::symbol_iterator::expand() {
llvm_unreachable("unhandled expansion case");
}
+unsigned SymExpr::computeComplexity() const {
+ unsigned R = 0;
+ for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
+ R++;
+ return R;
+}
+
const SymbolRegionValue*
SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
llvm::FoldingSetNodeID profile;
diff --git a/test/Analysis/taint-generic.c b/test/Analysis/taint-generic.c
index b00372a3ff..1cfdfead64 100644
--- a/test/Analysis/taint-generic.c
+++ b/test/Analysis/taint-generic.c
@@ -183,3 +183,23 @@ void testTaintedVLASize() {
scanf("%d", &x);
int vla[x]; // expected-warning{{Declared variable-length array (VLA) has tainted size}}
}
+
+// This computation used to take a very long time.
+#define longcmp(a,b,c) { \
+ a -= c; a ^= c; c += b; b -= a; b ^= (a<<6) | (a >> (32-b)); a += c; c -= b; c ^= b; b += a; \
+ a -= c; a ^= c; c += b; b -= a; b ^= a; a += c; c -= b; c ^= b; b += a; }
+
+unsigned radar11369570_hanging(const unsigned char *arr, int l) {
+ unsigned a, b, c;
+ a = b = c = 0x9899e3 + l;
+ while (l >= 6) {
+ unsigned t;
+ scanf("%d", &t);
+ a += b;
+ a ^= a;
+ a += (arr[3] + ((unsigned) arr[2] << 8) + ((unsigned) arr[1] << 16) + ((unsigned) arr[0] << 24));
+ longcmp(a, t, c);
+ l -= 12;
+ }
+ return 5/a; // expected-warning {{Division by a tainted value, possibly zero}}
+}