From: Anna Zaks Date: Fri, 9 Dec 2011 03:34:02 +0000 (+0000) Subject: [analyzer] Fix inconsistency on when SValBuilder assumes that 2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=432a4558b8161c362efc319f8a38e074e74da201;p=clang [analyzer] Fix inconsistency on when SValBuilder assumes that 2 types are equivalent. + A taint test which tests bitwise operations and which was triggering an assertion due to presence of the integer to integer cast. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146240 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index bbc5b660d5..fd29e45c3d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -68,6 +68,17 @@ public: virtual ~SValBuilder() {} + bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) { + return haveSameType(Sym1->getType(Context), Sym2->getType(Context)); + } + + bool haveSameType(QualType Ty1, QualType Ty2) { + // FIXME: Remove the second disjunct when we support symbolic + // truncation/extension. + return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) || + (Ty2->isIntegerType() && Ty2->isIntegerType())); + } + SVal evalCast(SVal val, QualType castTy, QualType originalType); virtual SVal evalMinus(NonLoc val) = 0; diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index ff0a85a572..f381f1a5ad 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -37,7 +37,6 @@ DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) { return UnknownVal(); } - NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType type) { // The Environment ensures we always get a persistent APSInt in @@ -51,7 +50,7 @@ NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType type) { assert(lhs && rhs); - assert(SymMgr.getType(lhs) == SymMgr.getType(rhs)); + assert(haveSameType(lhs->getType(Context), rhs->getType(Context)) == true); assert(!Loc::isLocType(type)); return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type)); } diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 89d9dc0242..a7b67fbe8a 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -80,16 +80,14 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) { if (const SymExpr *se = val.getAsSymbolicExpression()) { QualType T = Context.getCanonicalType(se->getType(Context)); - if (T == Context.getCanonicalType(castTy)) - return val; - + // If types are the same or both are integers, ignore the cast. // FIXME: Remove this hack when we support symbolic truncation/extension. // HACK: If both castTy and T are integers, ignore the cast. This is // not a permanent solution. Eventually we want to precisely handle // extension/truncation of symbolic integers. This prevents us from losing // precision when we assign 'x = y' and 'y' is symbolic and x and y are // different integer types. - if (T->isIntegerType() && castTy->isIntegerType()) + if (haveSameType(T, castTy)) return val; if (!isLocType) @@ -483,7 +481,7 @@ SVal SimpleSValBuilder::evalBinOpNN(const ProgramState *state, // Otherwise, make a SymbolVal out of the expression. return MakeSymIntVal(symIntExpr, op, rhsInt->getValue(), resultTy); - // LHS is a simple symbol. + // LHS is a simple symbol (not a symbolic expression). } else { nonloc::SymbolVal *slhs = cast(&lhs); SymbolRef Sym = slhs->getSymbol(); diff --git a/test/Analysis/taint-tester.c b/test/Analysis/taint-tester.c index f1dd5d0f03..8a82cd397a 100644 --- a/test/Analysis/taint-tester.c +++ b/test/Analysis/taint-tester.c @@ -55,3 +55,18 @@ void taintTracking(int x) { int ty = xy.y; // FIXME: This should be tainted as well. char ntz = xy.z;// no warning } + +void BitwiseOp(int in, char inn) { + // Taint on bitwise operations, integer to integer cast. + int m; + int x = 0; + scanf("%d", &x); + int y = (in << (x << in)) * 5;// expected-warning 4 {{tainted}} + // The next line tests integer to integer cast. + int z = y & inn; // expected-warning 2 {{tainted}} + if (y == 5) // expected-warning 2 {{tainted}} + m = z | z;// expected-warning 4 {{tainted}} + else + m = inn; + int mm = m; // expected-warning {{tainted}} +}