1//== RangeConstraintManager.cpp - Manage range constraints.------*- 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 RangeConstraintManager, a class that tracks simple 11// equality and inequality constraints on symbolic values of ProgramState. 12// 13//===----------------------------------------------------------------------===// 14 15#include "SimpleConstraintManager.h" 16#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" 17#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 18#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 19#include "llvm/Support/Debug.h" 20#include "llvm/ADT/FoldingSet.h" 21#include "llvm/ADT/ImmutableSet.h" 22#include "llvm/Support/raw_ostream.h" 23 24using namespace clang; 25using namespace ento; 26 27namespace { class ConstraintRange {}; } 28static int ConstraintRangeIndex = 0; 29 30/// A Range represents the closed range [from, to]. The caller must 31/// guarantee that from <= to. Note that Range is immutable, so as not 32/// to subvert RangeSet's immutability. 33namespace { 34class Range : public std::pair<const llvm::APSInt*, 35 const llvm::APSInt*> { 36public: 37 Range(const llvm::APSInt &from, const llvm::APSInt &to) 38 : std::pair<const llvm::APSInt*, const llvm::APSInt*>(&from, &to) { 39 assert(from <= to); 40 } 41 bool Includes(const llvm::APSInt &v) const { 42 return *first <= v && v <= *second; 43 } 44 const llvm::APSInt &From() const { 45 return *first; 46 } 47 const llvm::APSInt &To() const { 48 return *second; 49 } 50 const llvm::APSInt *getConcreteValue() const { 51 return &From() == &To() ? &From() : NULL; 52 } 53 54 void Profile(llvm::FoldingSetNodeID &ID) const { 55 ID.AddPointer(&From()); 56 ID.AddPointer(&To()); 57 } 58}; 59 60 61class RangeTrait : public llvm::ImutContainerInfo<Range> { 62public: 63 // When comparing if one Range is less than another, we should compare 64 // the actual APSInt values instead of their pointers. This keeps the order 65 // consistent (instead of comparing by pointer values) and can potentially 66 // be used to speed up some of the operations in RangeSet. 67 static inline bool isLess(key_type_ref lhs, key_type_ref rhs) { 68 return *lhs.first < *rhs.first || (!(*rhs.first < *lhs.first) && 69 *lhs.second < *rhs.second); 70 } 71}; 72 73/// RangeSet contains a set of ranges. If the set is empty, then 74/// there the value of a symbol is overly constrained and there are no 75/// possible values for that symbol. 76class RangeSet { 77 typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet; 78 PrimRangeSet ranges; // no need to make const, since it is an 79 // ImmutableSet - this allows default operator= 80 // to work. 81public: 82 typedef PrimRangeSet::Factory Factory; 83 typedef PrimRangeSet::iterator iterator; 84 85 RangeSet(PrimRangeSet RS) : ranges(RS) {} 86 87 iterator begin() const { return ranges.begin(); } 88 iterator end() const { return ranges.end(); } 89 90 bool isEmpty() const { return ranges.isEmpty(); } 91 92 /// Construct a new RangeSet representing '{ [from, to] }'. 93 RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to) 94 : ranges(F.add(F.getEmptySet(), Range(from, to))) {} 95 96 /// Profile - Generates a hash profile of this RangeSet for use 97 /// by FoldingSet. 98 void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); } 99 100 /// getConcreteValue - If a symbol is contrained to equal a specific integer 101 /// constant then this method returns that value. Otherwise, it returns 102 /// NULL. 103 const llvm::APSInt* getConcreteValue() const { 104 return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : 0; 105 } 106 107private: 108 void IntersectInRange(BasicValueFactory &BV, Factory &F, 109 const llvm::APSInt &Lower, 110 const llvm::APSInt &Upper, 111 PrimRangeSet &newRanges, 112 PrimRangeSet::iterator &i, 113 PrimRangeSet::iterator &e) const { 114 // There are six cases for each range R in the set: 115 // 1. R is entirely before the intersection range. 116 // 2. R is entirely after the intersection range. 117 // 3. R contains the entire intersection range. 118 // 4. R starts before the intersection range and ends in the middle. 119 // 5. R starts in the middle of the intersection range and ends after it. 120 // 6. R is entirely contained in the intersection range. 121 // These correspond to each of the conditions below. 122 for (/* i = begin(), e = end() */; i != e; ++i) { 123 if (i->To() < Lower) { 124 continue; 125 } 126 if (i->From() > Upper) { 127 break; 128 } 129 130 if (i->Includes(Lower)) { 131 if (i->Includes(Upper)) { 132 newRanges = F.add(newRanges, Range(BV.getValue(Lower), 133 BV.getValue(Upper))); 134 break; 135 } else 136 newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To())); 137 } else { 138 if (i->Includes(Upper)) { 139 newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper))); 140 break; 141 } else 142 newRanges = F.add(newRanges, *i); 143 } 144 } 145 } 146 147 const llvm::APSInt &getMinValue() const { 148 assert(!isEmpty()); 149 return ranges.begin()->From(); 150 } 151 152 bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const { 153 // This function has nine cases, the cartesian product of range-testing 154 // both the upper and lower bounds against the symbol's type. 155 // Each case requires a different pinning operation. 156 // The function returns false if the described range is entirely outside 157 // the range of values for the associated symbol. 158 APSIntType Type(getMinValue()); 159 APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower); 160 APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper); 161 162 switch (LowerTest) { 163 case APSIntType::RTR_Below: 164 switch (UpperTest) { 165 case APSIntType::RTR_Below: 166 // The entire range is outside the symbol's set of possible values. 167 // If this is a conventionally-ordered range, the state is infeasible. 168 if (Lower < Upper) 169 return false; 170 171 // However, if the range wraps around, it spans all possible values. 172 Lower = Type.getMinValue(); 173 Upper = Type.getMaxValue(); 174 break; 175 case APSIntType::RTR_Within: 176 // The range starts below what's possible but ends within it. Pin. 177 Lower = Type.getMinValue(); 178 Type.apply(Upper); 179 break; 180 case APSIntType::RTR_Above: 181 // The range spans all possible values for the symbol. Pin. 182 Lower = Type.getMinValue(); 183 Upper = Type.getMaxValue(); 184 break; 185 } 186 break; 187 case APSIntType::RTR_Within: 188 switch (UpperTest) { 189 case APSIntType::RTR_Below: 190 // The range wraps around, but all lower values are not possible. 191 Type.apply(Lower); 192 Upper = Type.getMaxValue(); 193 break; 194 case APSIntType::RTR_Within: 195 // The range may or may not wrap around, but both limits are valid. 196 Type.apply(Lower); 197 Type.apply(Upper); 198 break; 199 case APSIntType::RTR_Above: 200 // The range starts within what's possible but ends above it. Pin. 201 Type.apply(Lower); 202 Upper = Type.getMaxValue(); 203 break; 204 } 205 break; 206 case APSIntType::RTR_Above: 207 switch (UpperTest) { 208 case APSIntType::RTR_Below: 209 // The range wraps but is outside the symbol's set of possible values. 210 return false; 211 case APSIntType::RTR_Within: 212 // The range starts above what's possible but ends within it (wrap). 213 Lower = Type.getMinValue(); 214 Type.apply(Upper); 215 break; 216 case APSIntType::RTR_Above: 217 // The entire range is outside the symbol's set of possible values. 218 // If this is a conventionally-ordered range, the state is infeasible. 219 if (Lower < Upper) 220 return false; 221 222 // However, if the range wraps around, it spans all possible values. 223 Lower = Type.getMinValue(); 224 Upper = Type.getMaxValue(); 225 break; 226 } 227 break; 228 } 229 230 return true; 231 } 232 233public: 234 // Returns a set containing the values in the receiving set, intersected with 235 // the closed range [Lower, Upper]. Unlike the Range type, this range uses 236 // modular arithmetic, corresponding to the common treatment of C integer 237 // overflow. Thus, if the Lower bound is greater than the Upper bound, the 238 // range is taken to wrap around. This is equivalent to taking the 239 // intersection with the two ranges [Min, Upper] and [Lower, Max], 240 // or, alternatively, /removing/ all integers between Upper and Lower. 241 RangeSet Intersect(BasicValueFactory &BV, Factory &F, 242 llvm::APSInt Lower, llvm::APSInt Upper) const { 243 if (!pin(Lower, Upper)) 244 return F.getEmptySet(); 245 246 PrimRangeSet newRanges = F.getEmptySet(); 247 248 PrimRangeSet::iterator i = begin(), e = end(); 249 if (Lower <= Upper) 250 IntersectInRange(BV, F, Lower, Upper, newRanges, i, e); 251 else { 252 // The order of the next two statements is important! 253 // IntersectInRange() does not reset the iteration state for i and e. 254 // Therefore, the lower range most be handled first. 255 IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e); 256 IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e); 257 } 258 259 return newRanges; 260 } 261 262 void print(raw_ostream &os) const { 263 bool isFirst = true; 264 os << "{ "; 265 for (iterator i = begin(), e = end(); i != e; ++i) { 266 if (isFirst) 267 isFirst = false; 268 else 269 os << ", "; 270 271 os << '[' << i->From().toString(10) << ", " << i->To().toString(10) 272 << ']'; 273 } 274 os << " }"; 275 } 276 277 bool operator==(const RangeSet &other) const { 278 return ranges == other.ranges; 279 } 280}; 281} // end anonymous namespace 282 283typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstraintRangeTy; 284 285namespace clang { 286namespace ento { 287template<> 288struct ProgramStateTrait<ConstraintRange> 289 : public ProgramStatePartialTrait<ConstraintRangeTy> { 290 static inline void *GDMIndex() { return &ConstraintRangeIndex; } 291}; 292} 293} 294 295namespace { 296class RangeConstraintManager : public SimpleConstraintManager{ 297 RangeSet GetRange(ProgramStateRef state, SymbolRef sym); 298public: 299 RangeConstraintManager(SubEngine &subengine, BasicValueFactory &BVF) 300 : SimpleConstraintManager(subengine, BVF) {} 301 302 ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym, 303 const llvm::APSInt& Int, 304 const llvm::APSInt& Adjustment); 305 306 ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym, 307 const llvm::APSInt& Int, 308 const llvm::APSInt& Adjustment); 309 310 ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym, 311 const llvm::APSInt& Int, 312 const llvm::APSInt& Adjustment); 313 314 ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym, 315 const llvm::APSInt& Int, 316 const llvm::APSInt& Adjustment); 317 318 ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym, 319 const llvm::APSInt& Int, 320 const llvm::APSInt& Adjustment); 321 322 ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym, 323 const llvm::APSInt& Int, 324 const llvm::APSInt& Adjustment); 325 326 const llvm::APSInt* getSymVal(ProgramStateRef St, SymbolRef sym) const; 327 328 ProgramStateRef removeDeadBindings(ProgramStateRef St, SymbolReaper& SymReaper); 329 330 void print(ProgramStateRef St, raw_ostream &Out, 331 const char* nl, const char *sep); 332 333private: 334 RangeSet::Factory F; 335}; 336 337} // end anonymous namespace 338 339ConstraintManager * 340ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine &Eng) { 341 return new RangeConstraintManager(Eng, StMgr.getBasicVals()); 342} 343 344const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St, 345 SymbolRef sym) const { 346 const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym); 347 return T ? T->getConcreteValue() : NULL; 348} 349 350/// Scan all symbols referenced by the constraints. If the symbol is not alive 351/// as marked in LSymbols, mark it as dead in DSymbols. 352ProgramStateRef 353RangeConstraintManager::removeDeadBindings(ProgramStateRef state, 354 SymbolReaper& SymReaper) { 355 356 ConstraintRangeTy CR = state->get<ConstraintRange>(); 357 ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>(); 358 359 for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) { 360 SymbolRef sym = I.getKey(); 361 if (SymReaper.maybeDead(sym)) 362 CR = CRFactory.remove(CR, sym); 363 } 364 365 return state->set<ConstraintRange>(CR); 366} 367 368RangeSet 369RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) { 370 if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym)) 371 return *V; 372 373 // Lazily generate a new RangeSet representing all possible values for the 374 // given symbol type. 375 BasicValueFactory &BV = getBasicVals(); 376 QualType T = sym->getType(BV.getContext()); 377 378 RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T)); 379 380 // Special case: references are known to be non-zero. 381 if (T->isReferenceType()) { 382 APSIntType IntType = BV.getAPSIntType(T); 383 Result = Result.Intersect(BV, F, ++IntType.getZeroValue(), 384 --IntType.getZeroValue()); 385 } 386 387 return Result; 388} 389 390//===------------------------------------------------------------------------=== 391// assumeSymX methods: public interface for RangeConstraintManager. 392//===------------------------------------------------------------------------===/ 393 394// The syntax for ranges below is mathematical, using [x, y] for closed ranges 395// and (x, y) for open ranges. These ranges are modular, corresponding with 396// a common treatment of C integer overflow. This means that these methods 397// do not have to worry about overflow; RangeSet::Intersect can handle such a 398// "wraparound" range. 399// As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1, 400// UINT_MAX, 0, 1, and 2. 401 402ProgramStateRef 403RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, 404 const llvm::APSInt &Int, 405 const llvm::APSInt &Adjustment) { 406 // Before we do any real work, see if the value can even show up. 407 APSIntType AdjustmentType(Adjustment); 408 if (AdjustmentType.testInRange(Int) != APSIntType::RTR_Within) 409 return St; 410 411 llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment; 412 llvm::APSInt Upper = Lower; 413 --Lower; 414 ++Upper; 415 416 // [Int-Adjustment+1, Int-Adjustment-1] 417 // Notice that the lower bound is greater than the upper bound. 418 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower); 419 return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New); 420} 421 422ProgramStateRef 423RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, 424 const llvm::APSInt &Int, 425 const llvm::APSInt &Adjustment) { 426 // Before we do any real work, see if the value can even show up. 427 APSIntType AdjustmentType(Adjustment); 428 if (AdjustmentType.testInRange(Int) != APSIntType::RTR_Within) 429 return NULL; 430 431 // [Int-Adjustment, Int-Adjustment] 432 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment; 433 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt); 434 return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New); 435} 436 437ProgramStateRef 438RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym, 439 const llvm::APSInt &Int, 440 const llvm::APSInt &Adjustment) { 441 // Before we do any real work, see if the value can even show up. 442 APSIntType AdjustmentType(Adjustment); 443 switch (AdjustmentType.testInRange(Int)) { 444 case APSIntType::RTR_Below: 445 return NULL; 446 case APSIntType::RTR_Within: 447 break; 448 case APSIntType::RTR_Above: 449 return St; 450 } 451 452 // Special case for Int == Min. This is always false. 453 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 454 llvm::APSInt Min = AdjustmentType.getMinValue(); 455 if (ComparisonVal == Min) 456 return NULL; 457 458 llvm::APSInt Lower = Min-Adjustment; 459 llvm::APSInt Upper = ComparisonVal-Adjustment; 460 --Upper; 461 462 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 463 return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New); 464} 465 466ProgramStateRef 467RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym, 468 const llvm::APSInt &Int, 469 const llvm::APSInt &Adjustment) { 470 // Before we do any real work, see if the value can even show up. 471 APSIntType AdjustmentType(Adjustment); 472 switch (AdjustmentType.testInRange(Int)) { 473 case APSIntType::RTR_Below: 474 return St; 475 case APSIntType::RTR_Within: 476 break; 477 case APSIntType::RTR_Above: 478 return NULL; 479 } 480 481 // Special case for Int == Max. This is always false. 482 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 483 llvm::APSInt Max = AdjustmentType.getMaxValue(); 484 if (ComparisonVal == Max) 485 return NULL; 486 487 llvm::APSInt Lower = ComparisonVal-Adjustment; 488 llvm::APSInt Upper = Max-Adjustment; 489 ++Lower; 490 491 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 492 return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New); 493} 494 495ProgramStateRef 496RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym, 497 const llvm::APSInt &Int, 498 const llvm::APSInt &Adjustment) { 499 // Before we do any real work, see if the value can even show up. 500 APSIntType AdjustmentType(Adjustment); 501 switch (AdjustmentType.testInRange(Int)) { 502 case APSIntType::RTR_Below: 503 return St; 504 case APSIntType::RTR_Within: 505 break; 506 case APSIntType::RTR_Above: 507 return NULL; 508 } 509 510 // Special case for Int == Min. This is always feasible. 511 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 512 llvm::APSInt Min = AdjustmentType.getMinValue(); 513 if (ComparisonVal == Min) 514 return St; 515 516 llvm::APSInt Max = AdjustmentType.getMaxValue(); 517 llvm::APSInt Lower = ComparisonVal-Adjustment; 518 llvm::APSInt Upper = Max-Adjustment; 519 520 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 521 return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New); 522} 523 524ProgramStateRef 525RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, 526 const llvm::APSInt &Int, 527 const llvm::APSInt &Adjustment) { 528 // Before we do any real work, see if the value can even show up. 529 APSIntType AdjustmentType(Adjustment); 530 switch (AdjustmentType.testInRange(Int)) { 531 case APSIntType::RTR_Below: 532 return NULL; 533 case APSIntType::RTR_Within: 534 break; 535 case APSIntType::RTR_Above: 536 return St; 537 } 538 539 // Special case for Int == Max. This is always feasible. 540 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 541 llvm::APSInt Max = AdjustmentType.getMaxValue(); 542 if (ComparisonVal == Max) 543 return St; 544 545 llvm::APSInt Min = AdjustmentType.getMinValue(); 546 llvm::APSInt Lower = Min-Adjustment; 547 llvm::APSInt Upper = ComparisonVal-Adjustment; 548 549 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 550 return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New); 551} 552 553//===------------------------------------------------------------------------=== 554// Pretty-printing. 555//===------------------------------------------------------------------------===/ 556 557void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out, 558 const char* nl, const char *sep) { 559 560 ConstraintRangeTy Ranges = St->get<ConstraintRange>(); 561 562 if (Ranges.isEmpty()) { 563 Out << nl << sep << "Ranges are empty." << nl; 564 return; 565 } 566 567 Out << nl << sep << "Ranges of symbol values:"; 568 for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){ 569 Out << nl << ' ' << I.getKey() << " : "; 570 I.getData().print(Out); 571 } 572 Out << nl; 573} 574