23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/Support/raw_ostream.h"
28 using namespace clang;
32 class CStringChecker :
public Checker< eval::Call,
33 check::PreStmt<DeclStmt>,
38 mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap,
39 BT_NotCString, BT_AdditionOverflow;
41 mutable const char *CurrentFunctionDescription;
46 struct CStringChecksFilter {
58 CStringChecksFilter Filter;
60 static void *getTag() {
static int tag;
return &tag; }
87 bool Restricted =
false,
88 bool IsMempcpy =
false)
const;
96 bool IsStrnlen =
false)
const;
105 bool isAppending)
const;
116 bool isBounded =
false,
117 bool ignoreCase =
false)
const;
122 std::pair<ProgramStateRef , ProgramStateRef >
138 bool hypothetical =
false)
const;
148 bool IsSourceBuffer);
150 static bool SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
162 const char *message =
nullptr)
const;
166 const Expr *FirstBuf,
167 const Expr *SecondBuf,
168 const char *firstMessage =
nullptr,
169 const char *secondMessage =
nullptr,
170 bool WarnAboutSize =
false)
const;
176 const char *message =
nullptr,
177 bool WarnAboutSize =
false)
const {
179 return CheckBufferAccess(C, state, Size, Buf,
nullptr, message,
nullptr,
186 const Expr *Second)
const;
190 const Stmt *Second)
const;
211 return std::pair<ProgramStateRef , ProgramStateRef >(state, state);
215 return state->assume(svalBuilder.evalEQ(state, *val, zero));
219 ProgramStateRef state,
225 ProgramStateRef stateNull, stateNonNull;
226 std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->
getType());
228 if (stateNull && !stateNonNull) {
229 if (!Filter.CheckCStringNullArg)
239 "Null pointer argument in call to byte string function"));
242 llvm::raw_svector_ostream os(buf);
243 assert(CurrentFunctionDescription);
244 os <<
"Null pointer argument in call to " << CurrentFunctionDescription;
248 auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
250 report->addRange(S->getSourceRange());
257 assert(stateNonNull);
263 ProgramStateRef state,
265 const char *warningMsg)
const {
280 "CheckLocation should only be called with char* ElementRegions");
286 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
292 ProgramStateRef StInBound = state->assumeInBound(Idx, Size,
true);
293 ProgramStateRef StOutBound = state->assumeInBound(Idx, Size,
false);
294 if (StOutBound && !StInBound) {
301 Filter.CheckNameCStringOutOfBounds,
"Out-of-bound array access",
302 "Byte string function accesses out-of-bound array element"));
307 std::unique_ptr<BugReport> report;
309 report = llvm::make_unique<BugReport>(*BT, warningMsg, N);
311 assert(CurrentFunctionDescription);
312 assert(CurrentFunctionDescription[0] !=
'\0');
315 llvm::raw_svector_ostream os(buf);
317 << &CurrentFunctionDescription[1]
318 <<
" accesses out-of-bound array element";
319 report = llvm::make_unique<BugReport>(*BT, os.str(), N);
326 report->addRange(S->getSourceRange());
336 ProgramStateRef CStringChecker::CheckBufferAccess(
CheckerContext &C,
337 ProgramStateRef state,
339 const Expr *FirstBuf,
340 const Expr *SecondBuf,
341 const char *firstMessage,
342 const char *secondMessage,
343 bool WarnAboutSize)
const {
356 SVal BufVal = state->getSVal(FirstBuf, LCtx);
357 state = checkNonNull(C, state, FirstBuf, BufVal);
362 if (!Filter.CheckCStringOutOfBounds)
368 SVal LengthVal = state->getSVal(Size, LCtx);
375 NonLoc LastOffset = svalBuilder
381 const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
385 state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
394 BufVal = state->getSVal(SecondBuf, LCtx);
395 state = checkNonNull(C, state, SecondBuf, BufVal);
401 const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
405 state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
414 ProgramStateRef state,
417 const Expr *Second)
const {
418 if (!Filter.CheckCStringBufferOverlap)
429 ProgramStateRef stateTrue, stateFalse;
433 SVal firstVal = state->getSVal(First, LCtx);
434 SVal secondVal = state->getSVal(Second, LCtx);
446 std::tie(stateTrue, stateFalse) =
447 state->assume(svalBuilder.
evalEQ(state, *firstLoc, *secondLoc));
449 if (stateTrue && !stateFalse) {
451 emitOverlapBug(C, stateTrue, First, Second);
462 *firstLoc, *secondLoc, cmpTy);
468 std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
475 std::swap(firstLoc, secondLoc);
478 std::swap(First, Second);
483 SVal LengthVal = state->getSVal(Size, LCtx);
492 SVal FirstStart = svalBuilder.
evalCast(*firstLoc, CharPtrTy,
500 *FirstStartLoc, *Length, CharPtrTy);
507 *FirstEndLoc, *secondLoc, cmpTy);
513 std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
515 if (stateTrue && !stateFalse) {
517 emitOverlapBug(C, stateTrue, First, Second);
526 void CStringChecker::emitOverlapBug(
CheckerContext &C, ProgramStateRef state,
527 const Stmt *First,
const Stmt *Second)
const {
533 BT_Overlap.reset(
new BugType(Filter.CheckNameCStringBufferOverlap,
537 auto report = llvm::make_unique<BugReport>(
538 *BT_Overlap,
"Arguments must not be overlapping buffers", N);
539 report->addRange(First->getSourceRange());
540 report->addRange(Second->getSourceRange());
545 ProgramStateRef CStringChecker::checkAdditionOverflow(
CheckerContext &C,
546 ProgramStateRef state,
550 if (!Filter.CheckCStringOutOfBounds)
561 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
580 *maxMinusRightNL, cmpTy);
582 ProgramStateRef stateOverflow, stateOkay;
583 std::tie(stateOverflow, stateOkay) =
586 if (stateOverflow && !stateOkay) {
592 if (!BT_AdditionOverflow)
593 BT_AdditionOverflow.reset(
594 new BuiltinBug(Filter.CheckNameCStringOutOfBounds,
"API",
595 "Sum of expressions causes overflow"));
600 const char *warning =
601 "This expression will create a string whose length is too big to "
602 "be represented as a size_t";
606 llvm::make_unique<BugReport>(*BT_AdditionOverflow, warning, N));
619 ProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state,
622 assert(!strLength.
isUndef() &&
"Attempt to set an undefined string length");
626 switch (MR->getKind()) {
654 return state->remove<CStringLength>(MR);
656 return state->set<CStringLength>(MR, strLength);
660 ProgramStateRef &state,
666 const SVal *Recorded = state->get<CStringLength>(MR);
682 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
691 state = state->set<CStringLength>(MR, strLength);
699 bool hypothetical)
const {
706 if (!Filter.CheckCStringNotNullTerm)
713 "Argument is not a null-terminated string."));
716 llvm::raw_svector_ostream os(buf);
717 assert(CurrentFunctionDescription);
718 os <<
"Argument to " << CurrentFunctionDescription
719 <<
" is the address of the label '" << Label->getLabel()->getName()
720 <<
"', which is not a null-terminated string";
723 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
725 report->addRange(Ex->getSourceRange());
746 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
754 return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
766 if (!Filter.CheckCStringNotNullTerm)
773 "Argument is not a null-terminated string."));
776 llvm::raw_svector_ostream os(buf);
778 assert(CurrentFunctionDescription);
779 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
782 os <<
", which is not a null-terminated string";
784 os <<
"not a null-terminated string";
787 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
789 report->addRange(Ex->getSourceRange());
798 ProgramStateRef &state,
const Expr *
expr,
SVal val)
const {
817 ProgramStateRef CStringChecker::InvalidateBuffer(
CheckerContext &C,
818 ProgramStateRef state,
820 bool IsSourceBuffer) {
841 bool CausesPointerEscape =
false;
845 if (IsSourceBuffer) {
849 CausesPointerEscape =
true;
852 return state->invalidateRegions(R, E, C.
blockCount(), LCtx,
853 CausesPointerEscape,
nullptr,
nullptr,
860 return state->killBinding(*L);
863 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
869 const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
871 os <<
"the address of the function '" << *FD <<
'\'';
873 os <<
"the address of a function";
906 ProgramStateRef state,
908 const Expr *Source,
bool Restricted,
909 bool IsMempcpy)
const {
910 CurrentFunctionDescription =
"memory copy function";
914 SVal sizeVal = state->getSVal(Size, LCtx);
917 ProgramStateRef stateZeroSize, stateNonZeroSize;
918 std::tie(stateZeroSize, stateNonZeroSize) =
919 assumeZero(C, state, sizeVal, sizeTy);
922 SVal destVal = state->getSVal(Dest, LCtx);
926 if (stateZeroSize && !stateNonZeroSize) {
927 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
933 if (stateNonZeroSize) {
934 state = stateNonZeroSize;
938 state = checkNonNull(C, state, Dest, destVal);
943 SVal srcVal = state->getSVal(Source, LCtx);
947 state = checkNonNull(C, state, Source, srcVal);
952 const char *
const writeWarning =
953 "Memory copy function overflows destination buffer";
954 state = CheckBufferAccess(C, state, Size, Dest, Source,
955 writeWarning,
nullptr);
957 state = CheckOverlap(C, state, Size, Dest, Source);
974 CharPtrTy, Dest->
getType()).castAs<loc::MemRegionVal>();
981 state = state->BindExpr(CE, LCtx, lastElement);
987 state = state->BindExpr(CE, LCtx, result);
993 state = state->BindExpr(CE, LCtx, destVal);
1002 state = InvalidateBuffer(C, state, Dest, C.
getSVal(Dest),
1007 state = InvalidateBuffer(C, state, Source, C.
getSVal(Source),
1022 ProgramStateRef state = C.
getState();
1024 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1034 ProgramStateRef state = C.
getState();
1036 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1046 ProgramStateRef state = C.
getState();
1048 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1056 evalCopyCommon(C, CE, C.
getState(),
1065 CurrentFunctionDescription =
"memory comparison function";
1071 ProgramStateRef state = C.
getState();
1076 SVal sizeVal = state->getSVal(Size, LCtx);
1079 ProgramStateRef stateZeroSize, stateNonZeroSize;
1080 std::tie(stateZeroSize, stateNonZeroSize) =
1081 assumeZero(C, state, sizeVal, sizeTy);
1085 if (stateZeroSize) {
1086 state = stateZeroSize;
1087 state = state->BindExpr(CE, LCtx,
1093 if (stateNonZeroSize) {
1094 state = stateNonZeroSize;
1105 ProgramStateRef StSameBuf, StNotSameBuf;
1106 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1112 state = CheckBufferAccess(C, state, Size, Left);
1114 state = StSameBuf->BindExpr(CE, LCtx,
1123 state = StNotSameBuf;
1124 state = CheckBufferAccess(C, state, Size, Left, Right);
1129 state = state->BindExpr(CE, LCtx, CmpV);
1142 evalstrLengthCommon(C, CE,
false);
1151 evalstrLengthCommon(C, CE,
true);
1155 bool IsStrnlen)
const {
1156 CurrentFunctionDescription =
"string length function";
1157 ProgramStateRef state = C.
getState();
1162 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1164 ProgramStateRef stateZeroSize, stateNonZeroSize;
1165 std::tie(stateZeroSize, stateNonZeroSize) =
1166 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1170 if (stateZeroSize) {
1172 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1177 if (!stateNonZeroSize)
1181 state = stateNonZeroSize;
1186 SVal ArgVal = state->getSVal(Arg, LCtx);
1188 state = checkNonNull(C, state, Arg, ArgVal);
1193 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1210 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1215 if (strLengthNL && maxlenValNL) {
1216 ProgramStateRef stateStringTooLong, stateStringNotTooLong;
1219 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1224 if (stateStringTooLong && !stateStringNotTooLong) {
1226 result = *maxlenValNL;
1227 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1229 result = *strLengthNL;
1244 state,
BO_LE, resultNL, *strLengthNL, cmpTy)
1250 state,
BO_LE, resultNL, *maxlenValNL, cmpTy)
1268 assert(!result.
isUnknown() &&
"Should have conjured a value by now");
1269 state = state->BindExpr(CE, LCtx, result);
1278 evalStrcpyCommon(C, CE,
1289 evalStrcpyCommon(C, CE,
1300 evalStrcpyCommon(C, CE,
1311 evalStrcpyCommon(C, CE,
1322 evalStrcpyCommon(C, CE,
1329 bool returnEnd,
bool isBounded,
1330 bool isAppending)
const {
1331 CurrentFunctionDescription =
"string copy function";
1332 ProgramStateRef state = C.
getState();
1337 SVal DstVal = state->getSVal(Dst, LCtx);
1339 state = checkNonNull(C, state, Dst, DstVal);
1345 SVal srcVal = state->getSVal(srcExpr, LCtx);
1346 state = checkNonNull(C, state, srcExpr, srcVal);
1351 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1366 const char *boundWarning =
nullptr;
1372 SVal lenVal = state->getSVal(lenExpr, LCtx);
1382 if (strLengthNL && lenValNL) {
1383 ProgramStateRef stateSourceTooLong, stateSourceNotTooLong;
1388 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1392 if (stateSourceTooLong && !stateSourceNotTooLong) {
1395 state = stateSourceTooLong;
1396 amountCopied = lenVal;
1398 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1400 state = stateSourceNotTooLong;
1401 amountCopied = strLength;
1413 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1422 boundWarning =
"Size argument is greater than the free space in the "
1423 "destination buffer";
1434 ProgramStateRef StateZeroSize, StateNonZeroSize;
1435 std::tie(StateZeroSize, StateNonZeroSize) =
1436 assumeZero(C, state, *lenValNL, sizeTy);
1439 if (StateZeroSize && !StateNonZeroSize) {
1440 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1451 boundWarning =
"Size argument is greater than the length of the "
1452 "destination buffer";
1460 if (amountCopied.
isUnknown() && !isAppending) {
1463 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1464 assert(!amountCopied.
isUndef());
1473 state = state->assume(
1485 state = state->assume(
1496 amountCopied = strLength;
1512 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1520 if (srcStrLengthNL && dstStrLengthNL) {
1522 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1527 *dstStrLengthNL, sizeTy);
1535 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1536 assert(!finalStrLength.
isUndef());
1539 if (srcStrLengthNL) {
1551 if (dstStrLengthNL) {
1568 finalStrLength = amountCopied;
1589 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1599 *knownStrLength, ptrTy);
1602 if (!boundWarning) {
1603 const char *
const warningMsg =
1604 "String copy function overflows destination buffer";
1605 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1612 Result = lastElement;
1622 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1627 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true);
1630 if (isBounded && !isAppending) {
1635 if (amountCopied != strLength)
1636 finalStrLength = UnknownVal();
1638 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1650 state = state->BindExpr(CE, LCtx, Result);
1659 evalStrcmpCommon(C, CE,
false,
false);
1667 evalStrcmpCommon(C, CE,
true,
false);
1676 evalStrcmpCommon(C, CE,
false,
true);
1685 evalStrcmpCommon(C, CE,
true,
true);
1689 bool isBounded,
bool ignoreCase)
const {
1690 CurrentFunctionDescription =
"string comparison function";
1691 ProgramStateRef state = C.
getState();
1696 SVal s1Val = state->getSVal(s1, LCtx);
1697 state = checkNonNull(C, state, s1, s1Val);
1703 SVal s2Val = state->getSVal(s2, LCtx);
1704 state = checkNonNull(C, state, s2, s2Val);
1709 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1714 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1727 ProgramStateRef StSameBuf, StNotSameBuf;
1728 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1733 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1734 svalBuilder.makeZeroVal(CE->
getType()));
1742 assert(StNotSameBuf);
1743 state = StNotSameBuf;
1749 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1750 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1751 bool canComputeResult =
false;
1753 if (s1StrLiteral && s2StrLiteral) {
1754 StringRef s1StrRef = s1StrLiteral->
getString();
1755 StringRef s2StrRef = s2StrLiteral->
getString();
1760 SVal lenVal = state->getSVal(lenExpr, LCtx);
1763 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1765 s1StrRef = s1StrRef.substr(0, (
size_t)len->getZExtValue());
1766 s2StrRef = s2StrRef.substr(0, (
size_t)len->getZExtValue());
1767 canComputeResult =
true;
1771 canComputeResult =
true;
1774 if (canComputeResult) {
1776 size_t s1Term = s1StrRef.find(
'\0');
1777 if (s1Term != StringRef::npos)
1778 s1StrRef = s1StrRef.substr(0, s1Term);
1780 size_t s2Term = s2StrRef.find(
'\0');
1781 if (s2Term != StringRef::npos)
1782 s2StrRef = s2StrRef.substr(0, s2Term);
1789 result = s1StrRef.compare_lower(s2StrRef);
1792 result = s1StrRef.compare(s2StrRef);
1796 SVal resultVal = svalBuilder.makeIntVal(result, CE->
getType());
1797 state = state->BindExpr(CE, LCtx, resultVal);
1801 if (!canComputeResult) {
1803 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1805 state = state->BindExpr(CE, LCtx, resultVal);
1820 if (CharPtrTy.
isNull() ||
1824 CurrentFunctionDescription =
"strsep()";
1830 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
1831 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
1837 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
1838 State = checkNonNull(C, State, DelimStr, DelimStrVal);
1846 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
1850 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
1855 State = State->bindLoc(*SearchStrLoc,
1865 State = State->BindExpr(CE, LCtx, Result);
1881 FnCheck evalFunction =
nullptr;
1883 evalFunction = &CStringChecker::evalMemcpy;
1885 evalFunction = &CStringChecker::evalMempcpy;
1887 evalFunction = &CStringChecker::evalMemcmp;
1889 evalFunction = &CStringChecker::evalMemmove;
1891 evalFunction = &CStringChecker::evalStrcpy;
1893 evalFunction = &CStringChecker::evalStrncpy;
1895 evalFunction = &CStringChecker::evalStpcpy;
1897 evalFunction = &CStringChecker::evalStrcat;
1899 evalFunction = &CStringChecker::evalStrncat;
1901 evalFunction = &CStringChecker::evalstrLength;
1903 evalFunction = &CStringChecker::evalstrnLength;
1905 evalFunction = &CStringChecker::evalStrcmp;
1907 evalFunction = &CStringChecker::evalStrncmp;
1909 evalFunction = &CStringChecker::evalStrcasecmp;
1911 evalFunction = &CStringChecker::evalStrncasecmp;
1913 evalFunction = &CStringChecker::evalStrsep;
1915 evalFunction = &CStringChecker::evalBcopy;
1917 evalFunction = &CStringChecker::evalMemcmp;
1924 (this->*evalFunction)(C, CE);
1940 ProgramStateRef state = C.
getState();
1942 for (
const auto *I : DS->
decls()) {
1954 if (!isa<StringLiteral>(Init))
1963 assert(StrVal.
isValid() &&
"Initializer string is unknown or undefined");
1967 state = state->set<CStringLength>(MR, strLength);
1973 bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state)
const {
1974 CStringLengthTy Entries = state->get<CStringLength>();
1975 return !Entries.isEmpty();
1979 CStringChecker::checkRegionChanges(ProgramStateRef state,
1984 CStringLengthTy Entries = state->get<CStringLength>();
1985 if (Entries.isEmpty())
1988 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
1989 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
1993 I = Regions.begin(), E = Regions.end(); I != E; ++I) {
1995 Invalidated.insert(MR);
1997 SuperRegions.insert(MR);
1998 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
1999 MR = SR->getSuperRegion();
2000 SuperRegions.insert(MR);
2004 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2007 for (CStringLengthTy::iterator I = Entries.begin(),
2008 E = Entries.end(); I != E; ++I) {
2012 if (SuperRegions.count(MR)) {
2013 Entries = F.remove(Entries, MR);
2019 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2020 Super = SR->getSuperRegion();
2021 if (Invalidated.count(Super)) {
2022 Entries = F.remove(Entries, MR);
2028 return state->set<CStringLength>(Entries);
2031 void CStringChecker::checkLiveSymbols(ProgramStateRef state,
2034 CStringLengthTy Entries = state->get<CStringLength>();
2036 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2038 SVal Len = I.getData();
2046 void CStringChecker::checkDeadSymbols(
SymbolReaper &SR,
2051 ProgramStateRef state = C.
getState();
2052 CStringLengthTy Entries = state->get<CStringLength>();
2053 if (Entries.isEmpty())
2056 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2057 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2059 SVal Len = I.getData();
2062 Entries = F.remove(Entries, I.getKey());
2066 state = state->set<CStringLength>(Entries);
2070 #define REGISTER_CHECKER(name) \
2071 void ento::register##name(CheckerManager &mgr) { \
2072 CStringChecker *checker = mgr.registerChecker<CStringChecker>(); \
2073 checker->Filter.Check##name = true; \
2074 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
2083 registerCStringNullArg(Mgr);
Suppress pointer-escaping of a region.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
TypedValueRegion - An abstract class representing regions having a typed value.
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
MemRegion - The root abstract class for all memory regions.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool hasDeadSymbols() const
Information about invalidation for a particular region/symbol.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
A helper class which wraps a boolean value set to false by default.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
virtual QualType getValueType() const =0
std::string getAsString() const
const Expr * getInit() const
SVal evalCast(SVal val, QualType castTy, QualType originalType)
Value representing integer constant.
void setTrait(SymbolRef Sym, InvalidationKinds IK)
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
const char *const UnixAPI
Symbolic value. These values used to capture symbolic execution of the program.
void markInUse(SymbolRef sym)
Marks a symbol as important to a checker.
virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy)=0
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
void registerCStringCheckerBasic(CheckerManager &Mgr)
Register the checker which evaluates CString API calls.
const StringLiteral * getStringLiteral() const
A record of the "type" of an APSInt, used for conversions.
SymExpr::symbol_iterator symbol_begin() const
const MemRegion * getSuperRegion() const
const LocationContext * getLocationContext() const
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
#define REGISTER_CHECKER(name)
const MemRegion * StripCasts(bool StripBaseCasts=true) const
QualType getPointeeType() const
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
const ProgramStateRef & getState() const
static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name=StringRef())
Returns true if the callee is an externally-visible function in the top-level namespace, such as malloc.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy)=0
The result type of a method or function.
QualType getConditionType() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
ASTContext & getContext()
SymExpr::symbol_iterator symbol_end() const
A class responsible for cleaning up unused symbols.
const llvm::APSInt * evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)
REGISTER_MAP_WITH_PROGRAMSTATE(AllocatedData, SymbolRef, MacOSKeychainAPIChecker::AllocationState) static bool isEnclosingFunctionParam(const Expr *E)
Tells that a region's contents is not changed.
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY
ASTContext & getASTContext()
unsigned getByteLength() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
StringRef getString() const
DefinedSVal getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, unsigned count)
const MemRegion * getAsRegion() const
unsigned getNumArgs() const
Represents an abstract call to a function or method along a particular path.
BasicValueFactory & getBasicValueFactory()
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
QualType getValueType() const override
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
SValBuilder & getSValBuilder()
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
StringRegion - Region associated with a StringLiteral.
ElementRegin is used to represent both array elements and casts.
static LLVM_READONLY char toUppercase(char c)
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
bool isDifferent()
Check if the checker changed the state of the execution; ex: added a new transition or a bug report...
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
Iterator over symbols that the current symbol depends on.