SimpleConstraintManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. //== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines SimpleConstraintManager, a class that holds code shared
  11. // between BasicConstraintManager and RangeConstraintManager.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "SimpleConstraintManager.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  18. namespace clang {
  19. namespace ento {
  20. SimpleConstraintManager::~SimpleConstraintManager() {}
  21. bool SimpleConstraintManager::canReasonAbout(SVal X) const {
  22. Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
  23. if (SymVal && SymVal->isExpression()) {
  24. const SymExpr *SE = SymVal->getSymbol();
  25. if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
  26. switch (SIE->getOpcode()) {
  27. // We don't reason yet about bitwise-constraints on symbolic values.
  28. case BO_And:
  29. case BO_Or:
  30. case BO_Xor:
  31. return false;
  32. // We don't reason yet about these arithmetic constraints on
  33. // symbolic values.
  34. case BO_Mul:
  35. case BO_Div:
  36. case BO_Rem:
  37. case BO_Shl:
  38. case BO_Shr:
  39. return false;
  40. // All other cases.
  41. default:
  42. return true;
  43. }
  44. }
  45. if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
  46. if (BinaryOperator::isComparisonOp(SSE->getOpcode())) {
  47. // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
  48. if (Loc::isLocType(SSE->getLHS()->getType())) {
  49. assert(Loc::isLocType(SSE->getRHS()->getType()));
  50. return true;
  51. }
  52. }
  53. }
  54. return false;
  55. }
  56. return true;
  57. }
  58. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
  59. DefinedSVal Cond,
  60. bool Assumption) {
  61. // If we have a Loc value, cast it to a bool NonLoc first.
  62. if (Optional<Loc> LV = Cond.getAs<Loc>()) {
  63. SValBuilder &SVB = State->getStateManager().getSValBuilder();
  64. QualType T;
  65. const MemRegion *MR = LV->getAsRegion();
  66. if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
  67. T = TR->getLocationType();
  68. else
  69. T = SVB.getContext().VoidPtrTy;
  70. Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
  71. }
  72. return assume(State, Cond.castAs<NonLoc>(), Assumption);
  73. }
  74. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
  75. NonLoc Cond, bool Assumption) {
  76. State = assumeAux(State, Cond, Assumption);
  77. if (NotifyAssumeClients && SU)
  78. return SU->processAssume(State, Cond, Assumption);
  79. return State;
  80. }
  81. ProgramStateRef
  82. SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
  83. SymbolRef Sym, bool Assumption) {
  84. BasicValueFactory &BVF = getBasicVals();
  85. QualType T = Sym->getType();
  86. // None of the constraint solvers currently support non-integer types.
  87. if (!T->isIntegralOrEnumerationType())
  88. return State;
  89. const llvm::APSInt &zero = BVF.getValue(0, T);
  90. if (Assumption)
  91. return assumeSymNE(State, Sym, zero, zero);
  92. else
  93. return assumeSymEQ(State, Sym, zero, zero);
  94. }
  95. ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
  96. NonLoc Cond,
  97. bool Assumption) {
  98. // We cannot reason about SymSymExprs, and can only reason about some
  99. // SymIntExprs.
  100. if (!canReasonAbout(Cond)) {
  101. // Just add the constraint to the expression without trying to simplify.
  102. SymbolRef Sym = Cond.getAsSymExpr();
  103. return assumeAuxForSymbol(State, Sym, Assumption);
  104. }
  105. switch (Cond.getSubKind()) {
  106. default:
  107. llvm_unreachable("'Assume' not implemented for this NonLoc");
  108. case nonloc::SymbolValKind: {
  109. nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
  110. SymbolRef Sym = SV.getSymbol();
  111. assert(Sym);
  112. // Handle SymbolData.
  113. if (!SV.isExpression()) {
  114. return assumeAuxForSymbol(State, Sym, Assumption);
  115. // Handle symbolic expression.
  116. } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
  117. // We can only simplify expressions whose RHS is an integer.
  118. BinaryOperator::Opcode Op = SE->getOpcode();
  119. if (BinaryOperator::isComparisonOp(Op)) {
  120. if (!Assumption)
  121. Op = BinaryOperator::negateComparisonOp(Op);
  122. return assumeSymRel(State, SE->getLHS(), Op, SE->getRHS());
  123. }
  124. } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
  125. // Translate "a != b" to "(b - a) != 0".
  126. // We invert the order of the operands as a heuristic for how loop
  127. // conditions are usually written ("begin != end") as compared to length
  128. // calculations ("end - begin"). The more correct thing to do would be to
  129. // canonicalize "a - b" and "b - a", which would allow us to treat
  130. // "a != b" and "b != a" the same.
  131. SymbolManager &SymMgr = getSymbolManager();
  132. BinaryOperator::Opcode Op = SSE->getOpcode();
  133. assert(BinaryOperator::isComparisonOp(Op));
  134. // For now, we only support comparing pointers.
  135. assert(Loc::isLocType(SSE->getLHS()->getType()));
  136. assert(Loc::isLocType(SSE->getRHS()->getType()));
  137. QualType DiffTy = SymMgr.getContext().getPointerDiffType();
  138. SymbolRef Subtraction =
  139. SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy);
  140. const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
  141. Op = BinaryOperator::reverseComparisonOp(Op);
  142. if (!Assumption)
  143. Op = BinaryOperator::negateComparisonOp(Op);
  144. return assumeSymRel(State, Subtraction, Op, Zero);
  145. }
  146. // If we get here, there's nothing else we can do but treat the symbol as
  147. // opaque.
  148. return assumeAuxForSymbol(State, Sym, Assumption);
  149. }
  150. case nonloc::ConcreteIntKind: {
  151. bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
  152. bool isFeasible = b ? Assumption : !Assumption;
  153. return isFeasible ? State : nullptr;
  154. }
  155. case nonloc::PointerToMemberKind: {
  156. bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
  157. bool IsFeasible = IsNull ? Assumption : !Assumption;
  158. return IsFeasible ? State : nullptr;
  159. }
  160. case nonloc::LocAsIntegerKind:
  161. return assume(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
  162. Assumption);
  163. } // end switch
  164. }
  165. ProgramStateRef SimpleConstraintManager::assumeInclusiveRange(
  166. ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
  167. const llvm::APSInt &To, bool InRange) {
  168. assert(From.isUnsigned() == To.isUnsigned() &&
  169. From.getBitWidth() == To.getBitWidth() &&
  170. "Values should have same types!");
  171. if (!canReasonAbout(Value)) {
  172. // Just add the constraint to the expression without trying to simplify.
  173. SymbolRef Sym = Value.getAsSymExpr();
  174. assert(Sym);
  175. return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange);
  176. }
  177. switch (Value.getSubKind()) {
  178. default:
  179. llvm_unreachable("'assumeInclusiveRange' is not implemented"
  180. "for this NonLoc");
  181. case nonloc::LocAsIntegerKind:
  182. case nonloc::SymbolValKind: {
  183. if (SymbolRef Sym = Value.getAsSymbol())
  184. return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange);
  185. return State;
  186. } // end switch
  187. case nonloc::ConcreteIntKind: {
  188. const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
  189. bool IsInRange = IntVal >= From && IntVal <= To;
  190. bool isFeasible = (IsInRange == InRange);
  191. return isFeasible ? State : nullptr;
  192. }
  193. } // end switch
  194. }
  195. static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
  196. // Is it a "($sym+constant1)" expression?
  197. if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
  198. BinaryOperator::Opcode Op = SE->getOpcode();
  199. if (Op == BO_Add || Op == BO_Sub) {
  200. Sym = SE->getLHS();
  201. Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
  202. // Don't forget to negate the adjustment if it's being subtracted.
  203. // This should happen /after/ promotion, in case the value being
  204. // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
  205. if (Op == BO_Sub)
  206. Adjustment = -Adjustment;
  207. }
  208. }
  209. }
  210. ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef State,
  211. const SymExpr *LHS,
  212. BinaryOperator::Opcode Op,
  213. const llvm::APSInt &Int) {
  214. assert(BinaryOperator::isComparisonOp(Op) &&
  215. "Non-comparison ops should be rewritten as comparisons to zero.");
  216. SymbolRef Sym = LHS;
  217. // Simplification: translate an assume of a constraint of the form
  218. // "(exp comparison_op expr) != 0" to true into an assume of
  219. // "exp comparison_op expr" to true. (And similarly, an assume of the form
  220. // "(exp comparison_op expr) == 0" to true into an assume of
  221. // "exp comparison_op expr" to false.)
  222. if (Int == 0 && (Op == BO_EQ || Op == BO_NE)) {
  223. if (const BinarySymExpr *SE = dyn_cast<BinarySymExpr>(Sym))
  224. if (BinaryOperator::isComparisonOp(SE->getOpcode()))
  225. return assume(State, nonloc::SymbolVal(Sym), (Op == BO_NE ? true : false));
  226. }
  227. // Get the type used for calculating wraparound.
  228. BasicValueFactory &BVF = getBasicVals();
  229. APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
  230. // We only handle simple comparisons of the form "$sym == constant"
  231. // or "($sym+constant1) == constant2".
  232. // The adjustment is "constant1" in the above expression. It's used to
  233. // "slide" the solution range around for modular arithmetic. For example,
  234. // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
  235. // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
  236. // the subclasses of SimpleConstraintManager to handle the adjustment.
  237. llvm::APSInt Adjustment = WraparoundType.getZeroValue();
  238. computeAdjustment(Sym, Adjustment);
  239. // Convert the right-hand side integer as necessary.
  240. APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
  241. llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
  242. // Prefer unsigned comparisons.
  243. if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
  244. ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
  245. Adjustment.setIsSigned(false);
  246. switch (Op) {
  247. default:
  248. llvm_unreachable("invalid operation not caught by assertion above");
  249. case BO_EQ:
  250. return assumeSymEQ(State, Sym, ConvertedInt, Adjustment);
  251. case BO_NE:
  252. return assumeSymNE(State, Sym, ConvertedInt, Adjustment);
  253. case BO_GT:
  254. return assumeSymGT(State, Sym, ConvertedInt, Adjustment);
  255. case BO_GE:
  256. return assumeSymGE(State, Sym, ConvertedInt, Adjustment);
  257. case BO_LT:
  258. return assumeSymLT(State, Sym, ConvertedInt, Adjustment);
  259. case BO_LE:
  260. return assumeSymLE(State, Sym, ConvertedInt, Adjustment);
  261. } // end switch
  262. }
  263. ProgramStateRef SimpleConstraintManager::assumeSymWithinInclusiveRange(
  264. ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
  265. const llvm::APSInt &To, bool InRange) {
  266. // Get the type used for calculating wraparound.
  267. BasicValueFactory &BVF = getBasicVals();
  268. APSIntType WraparoundType = BVF.getAPSIntType(Sym->getType());
  269. llvm::APSInt Adjustment = WraparoundType.getZeroValue();
  270. SymbolRef AdjustedSym = Sym;
  271. computeAdjustment(AdjustedSym, Adjustment);
  272. // Convert the right-hand side integer as necessary.
  273. APSIntType ComparisonType = std::max(WraparoundType, APSIntType(From));
  274. llvm::APSInt ConvertedFrom = ComparisonType.convert(From);
  275. llvm::APSInt ConvertedTo = ComparisonType.convert(To);
  276. // Prefer unsigned comparisons.
  277. if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
  278. ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
  279. Adjustment.setIsSigned(false);
  280. if (InRange)
  281. return assumeSymbolWithinInclusiveRange(State, AdjustedSym, ConvertedFrom,
  282. ConvertedTo, Adjustment);
  283. return assumeSymbolOutOfInclusiveRange(State, AdjustedSym, ConvertedFrom,
  284. ConvertedTo, Adjustment);
  285. }
  286. } // end of namespace ento
  287. } // end of namespace clang