CStringChecker.cpp revision b8b875be7b2d177d755641c6212111859372d611
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//= CStringChecker.h - Checks calls to C string functions ----------*- C++ -*-// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This defines CStringChecker, which is an assortment of checks on calls 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to functions in <string.h>. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//===----------------------------------------------------------------------===// 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ClangSACheckers.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/StaticAnalyzer/Core/Checker.h" 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/StaticAnalyzer/Core/CheckerManager.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/StringSwitch.h" 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass CStringChecker : public Checker< eval::Call, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::PreStmt<DeclStmt>, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::LiveSymbols, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::DeadSymbols, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::RegionChanges 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable llvm::OwningPtr<BugType> BT_Null, BT_Bounds, BT_BoundsWrite, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT_Overlap, BT_NotCString; 35public: 36 static void *getTag() { static int tag; return &tag; } 37 38 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 39 void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; 40 void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const; 41 void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; 42 bool wantsRegionChangeUpdate(const GRState *state) const; 43 44 const GRState *checkRegionChanges(const GRState *state, 45 const MemRegion * const *Begin, 46 const MemRegion * const *End) const; 47 48 typedef void (CStringChecker::*FnCheck)(CheckerContext &, 49 const CallExpr *) const; 50 51 void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; 52 void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; 53 void evalMemmove(CheckerContext &C, const CallExpr *CE) const; 54 void evalBcopy(CheckerContext &C, const CallExpr *CE) const; 55 void evalCopyCommon(CheckerContext &C, const CallExpr *CE, 56 const GRState *state, 57 const Expr *Size, const Expr *Source, const Expr *Dest, 58 bool Restricted = false, 59 bool IsMempcpy = false) const; 60 61 void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; 62 63 void evalstrLength(CheckerContext &C, const CallExpr *CE) const; 64 void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; 65 void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 66 bool IsStrnlen = false) const; 67 68 void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; 69 void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; 70 void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; 71 void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, 72 bool isStrncpy) const; 73 74 // Utility methods 75 std::pair<const GRState*, const GRState*> 76 static assumeZero(CheckerContext &C, 77 const GRState *state, SVal V, QualType Ty); 78 79 static const GRState *setCStringLength(const GRState *state, 80 const MemRegion *MR, SVal strLength); 81 static SVal getCStringLengthForRegion(CheckerContext &C, 82 const GRState *&state, 83 const Expr *Ex, const MemRegion *MR); 84 SVal getCStringLength(CheckerContext &C, const GRState *&state, 85 const Expr *Ex, SVal Buf) const; 86 87 static const GRState *InvalidateBuffer(CheckerContext &C, 88 const GRState *state, 89 const Expr *Ex, SVal V); 90 91 static bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 92 const MemRegion *MR); 93 94 // Re-usable checks 95 const GRState *checkNonNull(CheckerContext &C, const GRState *state, 96 const Expr *S, SVal l) const; 97 const GRState *CheckLocation(CheckerContext &C, const GRState *state, 98 const Expr *S, SVal l, 99 bool IsDestination = false) const; 100 const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, 101 const Expr *Size, 102 const Expr *FirstBuf, 103 const Expr *SecondBuf = NULL, 104 bool FirstIsDestination = false) const; 105 const GRState *CheckOverlap(CheckerContext &C, const GRState *state, 106 const Expr *Size, const Expr *First, 107 const Expr *Second) const; 108 void emitOverlapBug(CheckerContext &C, const GRState *state, 109 const Stmt *First, const Stmt *Second) const; 110}; 111 112class CStringLength { 113public: 114 typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap; 115}; 116} //end anonymous namespace 117 118namespace clang { 119namespace ento { 120 template <> 121 struct GRStateTrait<CStringLength> 122 : public GRStatePartialTrait<CStringLength::EntryMap> { 123 static void *GDMIndex() { return CStringChecker::getTag(); } 124 }; 125} 126} 127 128//===----------------------------------------------------------------------===// 129// Individual checks and utility methods. 130//===----------------------------------------------------------------------===// 131 132std::pair<const GRState*, const GRState*> 133CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V, 134 QualType Ty) { 135 DefinedSVal *val = dyn_cast<DefinedSVal>(&V); 136 if (!val) 137 return std::pair<const GRState*, const GRState *>(state, state); 138 139 SValBuilder &svalBuilder = C.getSValBuilder(); 140 DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); 141 return state->assume(svalBuilder.evalEQ(state, *val, zero)); 142} 143 144const GRState *CStringChecker::checkNonNull(CheckerContext &C, 145 const GRState *state, 146 const Expr *S, SVal l) const { 147 // If a previous check has failed, propagate the failure. 148 if (!state) 149 return NULL; 150 151 const GRState *stateNull, *stateNonNull; 152 llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); 153 154 if (stateNull && !stateNonNull) { 155 ExplodedNode *N = C.generateSink(stateNull); 156 if (!N) 157 return NULL; 158 159 if (!BT_Null) 160 BT_Null.reset(new BuiltinBug("API", 161 "Null pointer argument in call to byte string function")); 162 163 // Generate a report for this bug. 164 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get()); 165 EnhancedBugReport *report = new EnhancedBugReport(*BT, 166 BT->getDescription(), N); 167 168 report->addRange(S->getSourceRange()); 169 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S); 170 C.EmitReport(report); 171 return NULL; 172 } 173 174 // From here on, assume that the value is non-null. 175 assert(stateNonNull); 176 return stateNonNull; 177} 178 179// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? 180const GRState *CStringChecker::CheckLocation(CheckerContext &C, 181 const GRState *state, 182 const Expr *S, SVal l, 183 bool IsDestination) const { 184 // If a previous check has failed, propagate the failure. 185 if (!state) 186 return NULL; 187 188 // Check for out of bound array element access. 189 const MemRegion *R = l.getAsRegion(); 190 if (!R) 191 return state; 192 193 const ElementRegion *ER = dyn_cast<ElementRegion>(R); 194 if (!ER) 195 return state; 196 197 assert(ER->getValueType() == C.getASTContext().CharTy && 198 "CheckLocation should only be called with char* ElementRegions"); 199 200 // Get the size of the array. 201 const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); 202 SValBuilder &svalBuilder = C.getSValBuilder(); 203 SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); 204 DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent); 205 206 // Get the index of the accessed element. 207 DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); 208 209 const GRState *StInBound = state->assumeInBound(Idx, Size, true); 210 const GRState *StOutBound = state->assumeInBound(Idx, Size, false); 211 if (StOutBound && !StInBound) { 212 ExplodedNode *N = C.generateSink(StOutBound); 213 if (!N) 214 return NULL; 215 216 BuiltinBug *BT; 217 if (IsDestination) { 218 if (!BT_BoundsWrite) { 219 BT_BoundsWrite.reset(new BuiltinBug("Out-of-bound array access", 220 "Byte string function overflows destination buffer")); 221 } 222 BT = static_cast<BuiltinBug*>(BT_BoundsWrite.get()); 223 } else { 224 if (!BT_Bounds) { 225 BT_Bounds.reset(new BuiltinBug("Out-of-bound array access", 226 "Byte string function accesses out-of-bound array element")); 227 } 228 BT = static_cast<BuiltinBug*>(BT_Bounds.get()); 229 } 230 231 // FIXME: It would be nice to eventually make this diagnostic more clear, 232 // e.g., by referencing the original declaration or by saying *why* this 233 // reference is outside the range. 234 235 // Generate a report for this bug. 236 RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N); 237 238 report->addRange(S->getSourceRange()); 239 C.EmitReport(report); 240 return NULL; 241 } 242 243 // Array bound check succeeded. From this point forward the array bound 244 // should always succeed. 245 return StInBound; 246} 247 248const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, 249 const GRState *state, 250 const Expr *Size, 251 const Expr *FirstBuf, 252 const Expr *SecondBuf, 253 bool FirstIsDestination) const { 254 // If a previous check has failed, propagate the failure. 255 if (!state) 256 return NULL; 257 258 SValBuilder &svalBuilder = C.getSValBuilder(); 259 ASTContext &Ctx = C.getASTContext(); 260 261 QualType sizeTy = Size->getType(); 262 QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); 263 264 // Check that the first buffer is non-null. 265 SVal BufVal = state->getSVal(FirstBuf); 266 state = checkNonNull(C, state, FirstBuf, BufVal); 267 if (!state) 268 return NULL; 269 270 // Get the access length and make sure it is known. 271 SVal LengthVal = state->getSVal(Size); 272 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 273 if (!Length) 274 return state; 275 276 // Compute the offset of the last element to be accessed: size-1. 277 NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 278 NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub, 279 *Length, One, sizeTy)); 280 281 // Check that the first buffer is sufficently long. 282 SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); 283 if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 284 SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 285 LastOffset, PtrTy); 286 state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination); 287 288 // If the buffer isn't large enough, abort. 289 if (!state) 290 return NULL; 291 } 292 293 // If there's a second buffer, check it as well. 294 if (SecondBuf) { 295 BufVal = state->getSVal(SecondBuf); 296 state = checkNonNull(C, state, SecondBuf, BufVal); 297 if (!state) 298 return NULL; 299 300 BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType()); 301 if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 302 SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 303 LastOffset, PtrTy); 304 state = CheckLocation(C, state, SecondBuf, BufEnd); 305 } 306 } 307 308 // Large enough or not, return this state! 309 return state; 310} 311 312const GRState *CStringChecker::CheckOverlap(CheckerContext &C, 313 const GRState *state, 314 const Expr *Size, 315 const Expr *First, 316 const Expr *Second) const { 317 // Do a simple check for overlap: if the two arguments are from the same 318 // buffer, see if the end of the first is greater than the start of the second 319 // or vice versa. 320 321 // If a previous check has failed, propagate the failure. 322 if (!state) 323 return NULL; 324 325 const GRState *stateTrue, *stateFalse; 326 327 // Get the buffer values and make sure they're known locations. 328 SVal firstVal = state->getSVal(First); 329 SVal secondVal = state->getSVal(Second); 330 331 Loc *firstLoc = dyn_cast<Loc>(&firstVal); 332 if (!firstLoc) 333 return state; 334 335 Loc *secondLoc = dyn_cast<Loc>(&secondVal); 336 if (!secondLoc) 337 return state; 338 339 // Are the two values the same? 340 SValBuilder &svalBuilder = C.getSValBuilder(); 341 llvm::tie(stateTrue, stateFalse) = 342 state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc)); 343 344 if (stateTrue && !stateFalse) { 345 // If the values are known to be equal, that's automatically an overlap. 346 emitOverlapBug(C, stateTrue, First, Second); 347 return NULL; 348 } 349 350 // assume the two expressions are not equal. 351 assert(stateFalse); 352 state = stateFalse; 353 354 // Which value comes first? 355 ASTContext &Ctx = svalBuilder.getContext(); 356 QualType cmpTy = Ctx.IntTy; 357 SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT, 358 *firstLoc, *secondLoc, cmpTy); 359 DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse); 360 if (!reverseTest) 361 return state; 362 363 llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest); 364 if (stateTrue) { 365 if (stateFalse) { 366 // If we don't know which one comes first, we can't perform this test. 367 return state; 368 } else { 369 // Switch the values so that firstVal is before secondVal. 370 Loc *tmpLoc = firstLoc; 371 firstLoc = secondLoc; 372 secondLoc = tmpLoc; 373 374 // Switch the Exprs as well, so that they still correspond. 375 const Expr *tmpExpr = First; 376 First = Second; 377 Second = tmpExpr; 378 } 379 } 380 381 // Get the length, and make sure it too is known. 382 SVal LengthVal = state->getSVal(Size); 383 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 384 if (!Length) 385 return state; 386 387 // Convert the first buffer's start address to char*. 388 // Bail out if the cast fails. 389 QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); 390 SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, First->getType()); 391 Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart); 392 if (!FirstStartLoc) 393 return state; 394 395 // Compute the end of the first buffer. Bail out if THAT fails. 396 SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add, 397 *FirstStartLoc, *Length, CharPtrTy); 398 Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd); 399 if (!FirstEndLoc) 400 return state; 401 402 // Is the end of the first buffer past the start of the second buffer? 403 SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT, 404 *FirstEndLoc, *secondLoc, cmpTy); 405 DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap); 406 if (!OverlapTest) 407 return state; 408 409 llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); 410 411 if (stateTrue && !stateFalse) { 412 // Overlap! 413 emitOverlapBug(C, stateTrue, First, Second); 414 return NULL; 415 } 416 417 // assume the two expressions don't overlap. 418 assert(stateFalse); 419 return stateFalse; 420} 421 422void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state, 423 const Stmt *First, const Stmt *Second) const { 424 ExplodedNode *N = C.generateSink(state); 425 if (!N) 426 return; 427 428 if (!BT_Overlap) 429 BT_Overlap.reset(new BugType("Unix API", "Improper arguments")); 430 431 // Generate a report for this bug. 432 RangedBugReport *report = 433 new RangedBugReport(*BT_Overlap, 434 "Arguments must not be overlapping buffers", N); 435 report->addRange(First->getSourceRange()); 436 report->addRange(Second->getSourceRange()); 437 438 C.EmitReport(report); 439} 440 441const GRState *CStringChecker::setCStringLength(const GRState *state, 442 const MemRegion *MR, 443 SVal strLength) { 444 assert(!strLength.isUndef() && "Attempt to set an undefined string length"); 445 if (strLength.isUnknown()) 446 return state; 447 448 MR = MR->StripCasts(); 449 450 switch (MR->getKind()) { 451 case MemRegion::StringRegionKind: 452 // FIXME: This can happen if we strcpy() into a string region. This is 453 // undefined [C99 6.4.5p6], but we should still warn about it. 454 return state; 455 456 case MemRegion::SymbolicRegionKind: 457 case MemRegion::AllocaRegionKind: 458 case MemRegion::VarRegionKind: 459 case MemRegion::FieldRegionKind: 460 case MemRegion::ObjCIvarRegionKind: 461 return state->set<CStringLength>(MR, strLength); 462 463 case MemRegion::ElementRegionKind: 464 // FIXME: Handle element regions by upper-bounding the parent region's 465 // string length. 466 return state; 467 468 default: 469 // Other regions (mostly non-data) can't have a reliable C string length. 470 // For now, just ignore the change. 471 // FIXME: These are rare but not impossible. We should output some kind of 472 // warning for things like strcpy((char[]){'a', 0}, "b"); 473 return state; 474 } 475} 476 477SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, 478 const GRState *&state, 479 const Expr *Ex, 480 const MemRegion *MR) { 481 // If there's a recorded length, go ahead and return it. 482 const SVal *Recorded = state->get<CStringLength>(MR); 483 if (Recorded) 484 return *Recorded; 485 486 // Otherwise, get a new symbol and update the state. 487 unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 488 SValBuilder &svalBuilder = C.getSValBuilder(); 489 QualType sizeTy = svalBuilder.getContext().getSizeType(); 490 SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), 491 MR, Ex, sizeTy, Count); 492 state = state->set<CStringLength>(MR, strLength); 493 return strLength; 494} 495 496SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, 497 const Expr *Ex, SVal Buf) const { 498 const MemRegion *MR = Buf.getAsRegion(); 499 if (!MR) { 500 // If we can't get a region, see if it's something we /know/ isn't a 501 // C string. In the context of locations, the only time we can issue such 502 // a warning is for labels. 503 if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { 504 if (ExplodedNode *N = C.generateNode(state)) { 505 if (!BT_NotCString) 506 BT_NotCString.reset(new BuiltinBug("API", 507 "Argument is not a null-terminated string.")); 508 509 llvm::SmallString<120> buf; 510 llvm::raw_svector_ostream os(buf); 511 os << "Argument to byte string function is the address of the label '" 512 << Label->getLabel()->getName() 513 << "', which is not a null-terminated string"; 514 515 // Generate a report for this bug. 516 EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 517 os.str(), N); 518 519 report->addRange(Ex->getSourceRange()); 520 C.EmitReport(report); 521 } 522 523 return UndefinedVal(); 524 } 525 526 // If it's not a region and not a label, give up. 527 return UnknownVal(); 528 } 529 530 // If we have a region, strip casts from it and see if we can figure out 531 // its length. For anything we can't figure out, just return UnknownVal. 532 MR = MR->StripCasts(); 533 534 switch (MR->getKind()) { 535 case MemRegion::StringRegionKind: { 536 // Modifying the contents of string regions is undefined [C99 6.4.5p6], 537 // so we can assume that the byte length is the correct C string length. 538 SValBuilder &svalBuilder = C.getSValBuilder(); 539 QualType sizeTy = svalBuilder.getContext().getSizeType(); 540 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral(); 541 return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy); 542 } 543 case MemRegion::SymbolicRegionKind: 544 case MemRegion::AllocaRegionKind: 545 case MemRegion::VarRegionKind: 546 case MemRegion::FieldRegionKind: 547 case MemRegion::ObjCIvarRegionKind: 548 return getCStringLengthForRegion(C, state, Ex, MR); 549 case MemRegion::CompoundLiteralRegionKind: 550 // FIXME: Can we track this? Is it necessary? 551 return UnknownVal(); 552 case MemRegion::ElementRegionKind: 553 // FIXME: How can we handle this? It's not good enough to subtract the 554 // offset from the base string length; consider "123\x00567" and &a[5]. 555 return UnknownVal(); 556 default: 557 // Other regions (mostly non-data) can't have a reliable C string length. 558 // In this case, an error is emitted and UndefinedVal is returned. 559 // The caller should always be prepared to handle this case. 560 if (ExplodedNode *N = C.generateNode(state)) { 561 if (!BT_NotCString) 562 BT_NotCString.reset(new BuiltinBug("API", 563 "Argument is not a null-terminated string.")); 564 565 llvm::SmallString<120> buf; 566 llvm::raw_svector_ostream os(buf); 567 568 os << "Argument to byte string function is "; 569 570 if (SummarizeRegion(os, C.getASTContext(), MR)) 571 os << ", which is not a null-terminated string"; 572 else 573 os << "not a null-terminated string"; 574 575 // Generate a report for this bug. 576 EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 577 os.str(), N); 578 579 report->addRange(Ex->getSourceRange()); 580 C.EmitReport(report); 581 } 582 583 return UndefinedVal(); 584 } 585} 586 587const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C, 588 const GRState *state, 589 const Expr *E, SVal V) { 590 Loc *L = dyn_cast<Loc>(&V); 591 if (!L) 592 return state; 593 594 // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes 595 // some assumptions about the value that CFRefCount can't. Even so, it should 596 // probably be refactored. 597 if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) { 598 const MemRegion *R = MR->getRegion()->StripCasts(); 599 600 // Are we dealing with an ElementRegion? If so, we should be invalidating 601 // the super-region. 602 if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 603 R = ER->getSuperRegion(); 604 // FIXME: What about layers of ElementRegions? 605 } 606 607 // Invalidate this region. 608 unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 609 return state->invalidateRegion(R, E, Count, NULL); 610 } 611 612 // If we have a non-region value by chance, just remove the binding. 613 // FIXME: is this necessary or correct? This handles the non-Region 614 // cases. Is it ever valid to store to these? 615 return state->unbindLoc(*L); 616} 617 618bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 619 const MemRegion *MR) { 620 const TypedRegion *TR = dyn_cast<TypedRegion>(MR); 621 if (!TR) 622 return false; 623 624 switch (TR->getKind()) { 625 case MemRegion::FunctionTextRegionKind: { 626 const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl(); 627 if (FD) 628 os << "the address of the function '" << FD << "'"; 629 else 630 os << "the address of a function"; 631 return true; 632 } 633 case MemRegion::BlockTextRegionKind: 634 os << "block text"; 635 return true; 636 case MemRegion::BlockDataRegionKind: 637 os << "a block"; 638 return true; 639 case MemRegion::CXXThisRegionKind: 640 case MemRegion::CXXTempObjectRegionKind: 641 os << "a C++ temp object of type " << TR->getValueType().getAsString(); 642 return true; 643 case MemRegion::VarRegionKind: 644 os << "a variable of type" << TR->getValueType().getAsString(); 645 return true; 646 case MemRegion::FieldRegionKind: 647 os << "a field of type " << TR->getValueType().getAsString(); 648 return true; 649 case MemRegion::ObjCIvarRegionKind: 650 os << "an instance variable of type " << TR->getValueType().getAsString(); 651 return true; 652 default: 653 return false; 654 } 655} 656 657//===----------------------------------------------------------------------===// 658// evaluation of individual function calls. 659//===----------------------------------------------------------------------===// 660 661void CStringChecker::evalCopyCommon(CheckerContext &C, 662 const CallExpr *CE, 663 const GRState *state, 664 const Expr *Size, const Expr *Dest, 665 const Expr *Source, bool Restricted, 666 bool IsMempcpy) const { 667 // See if the size argument is zero. 668 SVal sizeVal = state->getSVal(Size); 669 QualType sizeTy = Size->getType(); 670 671 const GRState *stateZeroSize, *stateNonZeroSize; 672 llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy); 673 674 // Get the value of the Dest. 675 SVal destVal = state->getSVal(Dest); 676 677 // If the size is zero, there won't be any actual memory access, so 678 // just bind the return value to the destination buffer and return. 679 if (stateZeroSize) { 680 C.addTransition(stateZeroSize); 681 if (IsMempcpy) 682 state->BindExpr(CE, destVal); 683 else 684 state->BindExpr(CE, sizeVal); 685 return; 686 } 687 688 // If the size can be nonzero, we have to check the other arguments. 689 if (stateNonZeroSize) { 690 691 // Ensure the destination is not null. If it is NULL there will be a 692 // NULL pointer dereference. 693 state = checkNonNull(C, state, Dest, destVal); 694 if (!state) 695 return; 696 697 // Get the value of the Src. 698 SVal srcVal = state->getSVal(Source); 699 700 // Ensure the source is not null. If it is NULL there will be a 701 // NULL pointer dereference. 702 state = checkNonNull(C, state, Source, srcVal); 703 if (!state) 704 return; 705 706 // Ensure the buffers do not overlap. 707 state = stateNonZeroSize; 708 state = CheckBufferAccess(C, state, Size, Dest, Source, 709 /* FirstIsDst = */ true); 710 if (Restricted) 711 state = CheckOverlap(C, state, Size, Dest, Source); 712 713 if (state) { 714 715 // If this is mempcpy, get the byte after the last byte copied and 716 // bind the expr. 717 if (IsMempcpy) { 718 loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal); 719 720 // Get the length to copy. 721 SVal lenVal = state->getSVal(Size); 722 NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&lenVal); 723 724 // Get the byte after the last byte copied. 725 SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, 726 *destRegVal, 727 *lenValNonLoc, 728 Dest->getType()); 729 730 // The byte after the last byte copied is the return value. 731 state = state->BindExpr(CE, lastElement); 732 } 733 734 // Invalidate the destination. 735 // FIXME: Even if we can't perfectly model the copy, we should see if we 736 // can use LazyCompoundVals to copy the source values into the destination. 737 // This would probably remove any existing bindings past the end of the 738 // copied region, but that's still an improvement over blank invalidation. 739 state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest)); 740 C.addTransition(state); 741 } 742 } 743} 744 745 746void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { 747 // void *memcpy(void *restrict dst, const void *restrict src, size_t n); 748 // The return value is the address of the destination buffer. 749 const Expr *Dest = CE->getArg(0); 750 const GRState *state = C.getState(); 751 state = state->BindExpr(CE, state->getSVal(Dest)); 752 evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); 753} 754 755void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { 756 // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); 757 // The return value is a pointer to the byte following the last written byte. 758 const Expr *Dest = CE->getArg(0); 759 const GRState *state = C.getState(); 760 761 evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); 762} 763 764void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { 765 // void *memmove(void *dst, const void *src, size_t n); 766 // The return value is the address of the destination buffer. 767 const Expr *Dest = CE->getArg(0); 768 const GRState *state = C.getState(); 769 state = state->BindExpr(CE, state->getSVal(Dest)); 770 evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); 771} 772 773void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { 774 // void bcopy(const void *src, void *dst, size_t n); 775 evalCopyCommon(C, CE, C.getState(), 776 CE->getArg(2), CE->getArg(1), CE->getArg(0)); 777} 778 779void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { 780 // int memcmp(const void *s1, const void *s2, size_t n); 781 const Expr *Left = CE->getArg(0); 782 const Expr *Right = CE->getArg(1); 783 const Expr *Size = CE->getArg(2); 784 785 const GRState *state = C.getState(); 786 SValBuilder &svalBuilder = C.getSValBuilder(); 787 788 // See if the size argument is zero. 789 SVal sizeVal = state->getSVal(Size); 790 QualType sizeTy = Size->getType(); 791 792 const GRState *stateZeroSize, *stateNonZeroSize; 793 llvm::tie(stateZeroSize, stateNonZeroSize) = 794 assumeZero(C, state, sizeVal, sizeTy); 795 796 // If the size can be zero, the result will be 0 in that case, and we don't 797 // have to check either of the buffers. 798 if (stateZeroSize) { 799 state = stateZeroSize; 800 state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 801 C.addTransition(state); 802 } 803 804 // If the size can be nonzero, we have to check the other arguments. 805 if (stateNonZeroSize) { 806 state = stateNonZeroSize; 807 // If we know the two buffers are the same, we know the result is 0. 808 // First, get the two buffers' addresses. Another checker will have already 809 // made sure they're not undefined. 810 DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left)); 811 DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right)); 812 813 // See if they are the same. 814 DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 815 const GRState *StSameBuf, *StNotSameBuf; 816 llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 817 818 // If the two arguments might be the same buffer, we know the result is zero, 819 // and we only need to check one size. 820 if (StSameBuf) { 821 state = StSameBuf; 822 state = CheckBufferAccess(C, state, Size, Left); 823 if (state) { 824 state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 825 C.addTransition(state); 826 } 827 } 828 829 // If the two arguments might be different buffers, we have to check the 830 // size of both of them. 831 if (StNotSameBuf) { 832 state = StNotSameBuf; 833 state = CheckBufferAccess(C, state, Size, Left, Right); 834 if (state) { 835 // The return value is the comparison result, which we don't know. 836 unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 837 SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 838 state = state->BindExpr(CE, CmpV); 839 C.addTransition(state); 840 } 841 } 842 } 843} 844 845void CStringChecker::evalstrLength(CheckerContext &C, 846 const CallExpr *CE) const { 847 // size_t strlen(const char *s); 848 evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); 849} 850 851void CStringChecker::evalstrnLength(CheckerContext &C, 852 const CallExpr *CE) const { 853 // size_t strnlen(const char *s, size_t maxlen); 854 evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); 855} 856 857void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 858 bool IsStrnlen) const { 859 const GRState *state = C.getState(); 860 const Expr *Arg = CE->getArg(0); 861 SVal ArgVal = state->getSVal(Arg); 862 863 // Check that the argument is non-null. 864 state = checkNonNull(C, state, Arg, ArgVal); 865 866 if (state) { 867 SVal strLength = getCStringLength(C, state, Arg, ArgVal); 868 869 // If the argument isn't a valid C string, there's no valid state to 870 // transition to. 871 if (strLength.isUndef()) 872 return; 873 874 // If the check is for strnlen() then bind the return value to no more than 875 // the maxlen value. 876 if (IsStrnlen) { 877 const Expr *maxlenExpr = CE->getArg(1); 878 SVal maxlenVal = state->getSVal(maxlenExpr); 879 880 NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 881 NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); 882 883 QualType cmpTy = C.getSValBuilder().getContext().IntTy; 884 const GRState *stateTrue, *stateFalse; 885 886 // Check if the strLength is greater than or equal to the maxlen 887 llvm::tie(stateTrue, stateFalse) = 888 state->assume(cast<DefinedOrUnknownSVal> 889 (C.getSValBuilder().evalBinOpNN(state, BO_GE, 890 *strLengthNL, *maxlenValNL, 891 cmpTy))); 892 893 // If the strLength is greater than or equal to the maxlen, set strLength 894 // to maxlen 895 if (stateTrue && !stateFalse) { 896 strLength = maxlenVal; 897 } 898 } 899 900 // If getCStringLength couldn't figure out the length, conjure a return 901 // value, so it can be used in constraints, at least. 902 if (strLength.isUnknown()) { 903 unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 904 strLength = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); 905 } 906 907 // Bind the return value. 908 state = state->BindExpr(CE, strLength); 909 C.addTransition(state); 910 } 911} 912 913void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { 914 // char *strcpy(char *restrict dst, const char *restrict src); 915 evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false); 916} 917 918void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { 919 // char *strcpy(char *restrict dst, const char *restrict src); 920 evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true); 921} 922 923void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { 924 // char *stpcpy(char *restrict dst, const char *restrict src); 925 evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false); 926} 927 928void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, 929 bool returnEnd, bool isStrncpy) const { 930 const GRState *state = C.getState(); 931 932 // Check that the destination is non-null 933 const Expr *Dst = CE->getArg(0); 934 SVal DstVal = state->getSVal(Dst); 935 936 state = checkNonNull(C, state, Dst, DstVal); 937 if (!state) 938 return; 939 940 // Check that the source is non-null. 941 const Expr *srcExpr = CE->getArg(1); 942 SVal srcVal = state->getSVal(srcExpr); 943 state = checkNonNull(C, state, srcExpr, srcVal); 944 if (!state) 945 return; 946 947 // Get the string length of the source. 948 SVal strLength = getCStringLength(C, state, srcExpr, srcVal); 949 950 // If the source isn't a valid C string, give up. 951 if (strLength.isUndef()) 952 return; 953 954 if (isStrncpy) { 955 // Get the max number of characters to copy 956 const Expr *lenExpr = CE->getArg(2); 957 SVal lenVal = state->getSVal(lenExpr); 958 959 NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 960 NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal); 961 962 QualType cmpTy = C.getSValBuilder().getContext().IntTy; 963 const GRState *stateTrue, *stateFalse; 964 965 // Check if the max number to copy is less than the length of the src 966 llvm::tie(stateTrue, stateFalse) = 967 state->assume(cast<DefinedOrUnknownSVal> 968 (C.getSValBuilder().evalBinOpNN(state, BO_GT, 969 *strLengthNL, *lenValNL, 970 cmpTy))); 971 972 if (stateTrue) { 973 // Max number to copy is less than the length of the src, so the actual 974 // strLength copied is the max number arg. 975 strLength = lenVal; 976 } 977 } 978 979 SVal Result = (returnEnd ? UnknownVal() : DstVal); 980 981 // If the destination is a MemRegion, try to check for a buffer overflow and 982 // record the new string length. 983 if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) { 984 // If the length is known, we can check for an overflow. 985 if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&strLength)) { 986 SVal lastElement = 987 C.getSValBuilder().evalBinOpLN(state, BO_Add, *dstRegVal, 988 *knownStrLength, Dst->getType()); 989 990 state = CheckLocation(C, state, Dst, lastElement, /* IsDst = */ true); 991 if (!state) 992 return; 993 994 // If this is a stpcpy-style copy, the last element is the return value. 995 if (returnEnd) 996 Result = lastElement; 997 } 998 999 // Invalidate the destination. This must happen before we set the C string 1000 // length because invalidation will clear the length. 1001 // FIXME: Even if we can't perfectly model the copy, we should see if we 1002 // can use LazyCompoundVals to copy the source values into the destination. 1003 // This would probably remove any existing bindings past the end of the 1004 // string, but that's still an improvement over blank invalidation. 1005 state = InvalidateBuffer(C, state, Dst, *dstRegVal); 1006 1007 // Set the C string length of the destination. 1008 state = setCStringLength(state, dstRegVal->getRegion(), strLength); 1009 } 1010 1011 // If this is a stpcpy-style copy, but we were unable to check for a buffer 1012 // overflow, we still need a result. Conjure a return value. 1013 if (returnEnd && Result.isUnknown()) { 1014 SValBuilder &svalBuilder = C.getSValBuilder(); 1015 unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 1016 strLength = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 1017 } 1018 1019 // Set the return value. 1020 state = state->BindExpr(CE, Result); 1021 C.addTransition(state); 1022} 1023 1024//===----------------------------------------------------------------------===// 1025// The driver method, and other Checker callbacks. 1026//===----------------------------------------------------------------------===// 1027 1028bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 1029 // Get the callee. All the functions we care about are C functions 1030 // with simple identifiers. 1031 const GRState *state = C.getState(); 1032 const Expr *Callee = CE->getCallee(); 1033 const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); 1034 1035 if (!FD) 1036 return false; 1037 1038 // Get the name of the callee. If it's a builtin, strip off the prefix. 1039 IdentifierInfo *II = FD->getIdentifier(); 1040 if (!II) // if no identifier, not a simple C function 1041 return false; 1042 llvm::StringRef Name = II->getName(); 1043 if (Name.startswith("__builtin_")) 1044 Name = Name.substr(10); 1045 1046 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 1047 .Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy) 1048 .Case("mempcpy", &CStringChecker::evalMempcpy) 1049 .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp) 1050 .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove) 1051 .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy) 1052 .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy) 1053 .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy) 1054 .Case("strlen", &CStringChecker::evalstrLength) 1055 .Case("strnlen", &CStringChecker::evalstrnLength) 1056 .Case("bcopy", &CStringChecker::evalBcopy) 1057 .Default(NULL); 1058 1059 // If the callee isn't a string function, let another checker handle it. 1060 if (!evalFunction) 1061 return false; 1062 1063 // Check and evaluate the call. 1064 (this->*evalFunction)(C, CE); 1065 return true; 1066} 1067 1068void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { 1069 // Record string length for char a[] = "abc"; 1070 const GRState *state = C.getState(); 1071 1072 for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1073 I != E; ++I) { 1074 const VarDecl *D = dyn_cast<VarDecl>(*I); 1075 if (!D) 1076 continue; 1077 1078 // FIXME: Handle array fields of structs. 1079 if (!D->getType()->isArrayType()) 1080 continue; 1081 1082 const Expr *Init = D->getInit(); 1083 if (!Init) 1084 continue; 1085 if (!isa<StringLiteral>(Init)) 1086 continue; 1087 1088 Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext()); 1089 const MemRegion *MR = VarLoc.getAsRegion(); 1090 if (!MR) 1091 continue; 1092 1093 SVal StrVal = state->getSVal(Init); 1094 assert(StrVal.isValid() && "Initializer string is unknown or undefined"); 1095 DefinedOrUnknownSVal strLength 1096 = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal)); 1097 1098 state = state->set<CStringLength>(MR, strLength); 1099 } 1100 1101 C.addTransition(state); 1102} 1103 1104bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const { 1105 CStringLength::EntryMap Entries = state->get<CStringLength>(); 1106 return !Entries.isEmpty(); 1107} 1108 1109const GRState * 1110CStringChecker::checkRegionChanges(const GRState *state, 1111 const MemRegion * const *Begin, 1112 const MemRegion * const *End) const { 1113 CStringLength::EntryMap Entries = state->get<CStringLength>(); 1114 if (Entries.isEmpty()) 1115 return state; 1116 1117 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; 1118 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; 1119 1120 // First build sets for the changed regions and their super-regions. 1121 for ( ; Begin != End; ++Begin) { 1122 const MemRegion *MR = *Begin; 1123 Invalidated.insert(MR); 1124 1125 SuperRegions.insert(MR); 1126 while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { 1127 MR = SR->getSuperRegion(); 1128 SuperRegions.insert(MR); 1129 } 1130 } 1131 1132 CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1133 1134 // Then loop over the entries in the current state. 1135 for (CStringLength::EntryMap::iterator I = Entries.begin(), 1136 E = Entries.end(); I != E; ++I) { 1137 const MemRegion *MR = I.getKey(); 1138 1139 // Is this entry for a super-region of a changed region? 1140 if (SuperRegions.count(MR)) { 1141 Entries = F.remove(Entries, MR); 1142 continue; 1143 } 1144 1145 // Is this entry for a sub-region of a changed region? 1146 const MemRegion *Super = MR; 1147 while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { 1148 Super = SR->getSuperRegion(); 1149 if (Invalidated.count(Super)) { 1150 Entries = F.remove(Entries, MR); 1151 break; 1152 } 1153 } 1154 } 1155 1156 return state->set<CStringLength>(Entries); 1157} 1158 1159void CStringChecker::checkLiveSymbols(const GRState *state, 1160 SymbolReaper &SR) const { 1161 // Mark all symbols in our string length map as valid. 1162 CStringLength::EntryMap Entries = state->get<CStringLength>(); 1163 1164 for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1165 I != E; ++I) { 1166 SVal Len = I.getData(); 1167 if (SymbolRef Sym = Len.getAsSymbol()) 1168 SR.markInUse(Sym); 1169 } 1170} 1171 1172void CStringChecker::checkDeadSymbols(SymbolReaper &SR, 1173 CheckerContext &C) const { 1174 if (!SR.hasDeadSymbols()) 1175 return; 1176 1177 const GRState *state = C.getState(); 1178 CStringLength::EntryMap Entries = state->get<CStringLength>(); 1179 if (Entries.isEmpty()) 1180 return; 1181 1182 CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1183 for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1184 I != E; ++I) { 1185 SVal Len = I.getData(); 1186 if (SymbolRef Sym = Len.getAsSymbol()) { 1187 if (SR.isDead(Sym)) 1188 Entries = F.remove(Entries, I.getKey()); 1189 } 1190 } 1191 1192 state = state->set<CStringLength>(Entries); 1193 C.generateNode(state); 1194} 1195 1196void ento::registerCStringChecker(CheckerManager &mgr) { 1197 mgr.registerChecker<CStringChecker>(); 1198} 1199