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