summaryrefslogtreecommitdiffstats
path: root/lib/StaticAnalyzer/Core/SValBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/SValBuilder.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp76
1 files changed, 54 insertions, 22 deletions
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 9e97f5e..d1936cd 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
@@ -61,7 +62,6 @@ NonLoc SValBuilder::makeNonLoc(const llvm::APSInt& lhs,
NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType type) {
assert(lhs && rhs);
- assert(haveSameType(lhs->getType(Context), rhs->getType(Context)) == true);
assert(!Loc::isLocType(type));
return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
}
@@ -149,6 +149,18 @@ SValBuilder::getConjuredSymbolVal(const Stmt *stmt,
return nonloc::SymbolVal(sym);
}
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned VisitCount) {
+ QualType T = E->getType();
+ assert(Loc::isLocType(T));
+ assert(SymbolManager::canSymbolicate(T));
+
+ SymbolRef sym = SymMgr.getConjuredSymbol(E, LCtx, T, VisitCount);
+ return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
+}
+
DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag,
const MemRegion *region,
const Expr *expr, QualType type,
@@ -193,31 +205,48 @@ DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
return loc::MemRegionVal(BD);
}
+/// Return a memory region for the 'this' object reference.
+loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
+ const StackFrameContext *SFC) {
+ return loc::MemRegionVal(getRegionManager().
+ getCXXThisRegion(D->getThisType(getContext()), SFC));
+}
+
+/// Return a memory region for the 'this' object reference.
+loc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D,
+ const StackFrameContext *SFC) {
+ const Type *T = D->getTypeForDecl();
+ QualType PT = getContext().getPointerType(QualType(T, 0));
+ return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC));
+}
+
//===----------------------------------------------------------------------===//
-SVal SValBuilder::makeGenericVal(ProgramStateRef State,
- BinaryOperator::Opcode Op,
- NonLoc LHS, NonLoc RHS,
- QualType ResultTy) {
- // If operands are tainted, create a symbol to ensure that we propagate taint.
- if (State->isTainted(RHS) || State->isTainted(LHS)) {
- const SymExpr *symLHS;
- const SymExpr *symRHS;
-
- if (const nonloc::ConcreteInt *rInt = dyn_cast<nonloc::ConcreteInt>(&RHS)) {
- symLHS = LHS.getAsSymExpr();
+SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
+ BinaryOperator::Opcode Op,
+ NonLoc LHS, NonLoc RHS,
+ QualType ResultTy) {
+ if (!State->isTainted(RHS) && !State->isTainted(LHS))
+ return UnknownVal();
+
+ 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 &&
+ (symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp)
+ return makeNonLoc(symLHS, Op, symRHS, ResultTy);
+
+ if (symLHS && symLHS->computeComplexity() < MaxComp)
+ if (const nonloc::ConcreteInt *rInt = dyn_cast<nonloc::ConcreteInt>(&RHS))
return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
- }
- if (const nonloc::ConcreteInt *lInt = dyn_cast<nonloc::ConcreteInt>(&LHS)) {
- symRHS = RHS.getAsSymExpr();
+ if (symRHS && symRHS->computeComplexity() < MaxComp)
+ if (const nonloc::ConcreteInt *lInt = dyn_cast<nonloc::ConcreteInt>(&LHS))
return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);
- }
- symLHS = LHS.getAsSymExpr();
- symRHS = RHS.getAsSymExpr();
- return makeNonLoc(symLHS, Op, symRHS, ResultTy);
- }
return UnknownVal();
}
@@ -324,7 +353,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
// Are we casting from an array to a pointer? If so just pass on
// the decayed value.
- if (castTy->isPointerType())
+ if (castTy->isPointerType() || castTy->isReferenceType())
return val;
// Are we casting from an array to an integer? If so, cast the decayed
@@ -340,9 +369,12 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
// Check for casts from a region to a specific type.
if (const MemRegion *R = val.getAsRegion()) {
+ // Handle other casts of locations to integers.
+ if (castTy->isIntegerType())
+ return evalCastFromLoc(loc::MemRegionVal(R), castTy);
+
// FIXME: We should handle the case where we strip off view layers to get
// to a desugared type.
-
if (!Loc::isLocType(castTy)) {
// FIXME: There can be gross cases where one casts the result of a function
// (that returns a pointer) to some other value that happens to fit
OpenPOWER on IntegriCloud