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;
151 static bool SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
163 const char *message =
nullptr)
const;
167 const Expr *FirstBuf,
168 const Expr *SecondBuf,
169 const char *firstMessage =
nullptr,
170 const char *secondMessage =
nullptr,
171 bool WarnAboutSize =
false)
const;
177 const char *message =
nullptr,
178 bool WarnAboutSize =
false)
const {
180 return CheckBufferAccess(C, state, Size, Buf,
nullptr, message,
nullptr,
187 const Expr *Second)
const;
191 const Stmt *Second)
const;
203 const Expr *FirstBuf,
220 return std::pair<ProgramStateRef , ProgramStateRef >(state, state);
224 return state->assume(svalBuilder.evalEQ(state, *val, zero));
228 ProgramStateRef state,
234 ProgramStateRef stateNull, stateNonNull;
235 std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->
getType());
237 if (stateNull && !stateNonNull) {
238 if (!Filter.CheckCStringNullArg)
248 "Null pointer argument in call to byte string function"));
251 llvm::raw_svector_ostream os(buf);
252 assert(CurrentFunctionDescription);
253 os <<
"Null pointer argument in call to " << CurrentFunctionDescription;
257 auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
259 report->addRange(S->getSourceRange());
266 assert(stateNonNull);
272 ProgramStateRef state,
274 const char *warningMsg)
const {
289 "CheckLocation should only be called with char* ElementRegions");
295 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
301 ProgramStateRef StInBound = state->assumeInBound(Idx, Size,
true);
302 ProgramStateRef StOutBound = state->assumeInBound(Idx, Size,
false);
303 if (StOutBound && !StInBound) {
310 Filter.CheckNameCStringOutOfBounds,
"Out-of-bound array access",
311 "Byte string function accesses out-of-bound array element"));
316 std::unique_ptr<BugReport> report;
318 report = llvm::make_unique<BugReport>(*BT, warningMsg, N);
320 assert(CurrentFunctionDescription);
321 assert(CurrentFunctionDescription[0] !=
'\0');
324 llvm::raw_svector_ostream os(buf);
326 << &CurrentFunctionDescription[1]
327 <<
" accesses out-of-bound array element";
328 report = llvm::make_unique<BugReport>(*BT, os.str(), N);
335 report->addRange(S->getSourceRange());
345 ProgramStateRef CStringChecker::CheckBufferAccess(
CheckerContext &C,
346 ProgramStateRef state,
348 const Expr *FirstBuf,
349 const Expr *SecondBuf,
350 const char *firstMessage,
351 const char *secondMessage,
352 bool WarnAboutSize)
const {
365 SVal BufVal = state->getSVal(FirstBuf, LCtx);
366 state = checkNonNull(C, state, FirstBuf, BufVal);
371 if (!Filter.CheckCStringOutOfBounds)
377 SVal LengthVal = state->getSVal(Size, LCtx);
384 NonLoc LastOffset = svalBuilder
390 const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
394 state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
403 BufVal = state->getSVal(SecondBuf, LCtx);
404 state = checkNonNull(C, state, SecondBuf, BufVal);
410 const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
414 state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
423 ProgramStateRef state,
426 const Expr *Second)
const {
427 if (!Filter.CheckCStringBufferOverlap)
438 ProgramStateRef stateTrue, stateFalse;
442 SVal firstVal = state->getSVal(First, LCtx);
443 SVal secondVal = state->getSVal(Second, LCtx);
455 std::tie(stateTrue, stateFalse) =
456 state->assume(svalBuilder.
evalEQ(state, *firstLoc, *secondLoc));
458 if (stateTrue && !stateFalse) {
460 emitOverlapBug(C, stateTrue, First, Second);
471 *firstLoc, *secondLoc, cmpTy);
477 std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
484 std::swap(firstLoc, secondLoc);
487 std::swap(First, Second);
492 SVal LengthVal = state->getSVal(Size, LCtx);
501 SVal FirstStart = svalBuilder.
evalCast(*firstLoc, CharPtrTy,
509 *FirstStartLoc, *Length, CharPtrTy);
516 *FirstEndLoc, *secondLoc, cmpTy);
522 std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
524 if (stateTrue && !stateFalse) {
526 emitOverlapBug(C, stateTrue, First, Second);
535 void CStringChecker::emitOverlapBug(
CheckerContext &C, ProgramStateRef state,
536 const Stmt *First,
const Stmt *Second)
const {
542 BT_Overlap.reset(
new BugType(Filter.CheckNameCStringBufferOverlap,
546 auto report = llvm::make_unique<BugReport>(
547 *BT_Overlap,
"Arguments must not be overlapping buffers", N);
548 report->addRange(First->getSourceRange());
549 report->addRange(Second->getSourceRange());
554 ProgramStateRef CStringChecker::checkAdditionOverflow(
CheckerContext &C,
555 ProgramStateRef state,
559 if (!Filter.CheckCStringOutOfBounds)
570 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
589 *maxMinusRightNL, cmpTy);
591 ProgramStateRef stateOverflow, stateOkay;
592 std::tie(stateOverflow, stateOkay) =
595 if (stateOverflow && !stateOkay) {
601 if (!BT_AdditionOverflow)
602 BT_AdditionOverflow.reset(
603 new BuiltinBug(Filter.CheckNameCStringOutOfBounds,
"API",
604 "Sum of expressions causes overflow"));
609 const char *warning =
610 "This expression will create a string whose length is too big to "
611 "be represented as a size_t";
615 llvm::make_unique<BugReport>(*BT_AdditionOverflow, warning, N));
628 ProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state,
631 assert(!strLength.
isUndef() &&
"Attempt to set an undefined string length");
635 switch (MR->getKind()) {
663 return state->remove<CStringLength>(MR);
665 return state->set<CStringLength>(MR, strLength);
669 ProgramStateRef &state,
675 const SVal *Recorded = state->get<CStringLength>(MR);
691 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
700 state = state->set<CStringLength>(MR, strLength);
708 bool hypothetical)
const {
715 if (!Filter.CheckCStringNotNullTerm)
722 "Argument is not a null-terminated string."));
725 llvm::raw_svector_ostream os(buf);
726 assert(CurrentFunctionDescription);
727 os <<
"Argument to " << CurrentFunctionDescription
728 <<
" is the address of the label '" << Label->getLabel()->getName()
729 <<
"', which is not a null-terminated string";
732 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
734 report->addRange(Ex->getSourceRange());
755 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
763 return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
775 if (!Filter.CheckCStringNotNullTerm)
782 "Argument is not a null-terminated string."));
785 llvm::raw_svector_ostream os(buf);
787 assert(CurrentFunctionDescription);
788 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
791 os <<
", which is not a null-terminated string";
793 os <<
"not a null-terminated string";
796 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
798 report->addRange(Ex->getSourceRange());
807 ProgramStateRef &state,
const Expr *
expr,
SVal val)
const {
827 ProgramStateRef state,
828 const Expr *FirstBuf,
841 SVal BufVal = state->getSVal(FirstBuf, LCtx);
843 SVal LengthVal = state->getSVal(Size, LCtx);
873 "IsFirstBufInBound should only be called with char* ElementRegions");
884 ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize,
true);
886 return static_cast<bool>(StInBound);
889 ProgramStateRef CStringChecker::InvalidateBuffer(
CheckerContext &C,
890 ProgramStateRef state,
914 bool CausesPointerEscape =
false;
918 if (IsSourceBuffer) {
922 CausesPointerEscape =
true;
926 if (Size && IsFirstBufInBound(C, state, E, Size)) {
935 return state->invalidateRegions(R, E, C.
blockCount(), LCtx,
936 CausesPointerEscape,
nullptr,
nullptr,
943 return state->killBinding(*L);
946 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
952 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
954 os <<
"the address of the function '" << *FD <<
'\'';
956 os <<
"the address of a function";
989 ProgramStateRef state,
991 const Expr *Source,
bool Restricted,
992 bool IsMempcpy)
const {
993 CurrentFunctionDescription =
"memory copy function";
997 SVal sizeVal = state->getSVal(Size, LCtx);
1000 ProgramStateRef stateZeroSize, stateNonZeroSize;
1001 std::tie(stateZeroSize, stateNonZeroSize) =
1002 assumeZero(C, state, sizeVal, sizeTy);
1005 SVal destVal = state->getSVal(Dest, LCtx);
1009 if (stateZeroSize && !stateNonZeroSize) {
1010 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1016 if (stateNonZeroSize) {
1017 state = stateNonZeroSize;
1021 state = checkNonNull(C, state, Dest, destVal);
1026 SVal srcVal = state->getSVal(Source, LCtx);
1030 state = checkNonNull(C, state, Source, srcVal);
1035 const char *
const writeWarning =
1036 "Memory copy function overflows destination buffer";
1037 state = CheckBufferAccess(C, state, Size, Dest, Source,
1038 writeWarning,
nullptr);
1040 state = CheckOverlap(C, state, Size, Dest, Source);
1057 CharPtrTy, Dest->
getType()).castAs<loc::MemRegionVal>();
1064 state = state->BindExpr(CE, LCtx, lastElement);
1070 state = state->BindExpr(CE, LCtx, result);
1076 state = state->BindExpr(CE, LCtx, destVal);
1085 state = InvalidateBuffer(C, state, Dest, C.
getSVal(Dest),
1090 state = InvalidateBuffer(C, state, Source, C.
getSVal(Source),
1105 ProgramStateRef state = C.
getState();
1107 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1117 ProgramStateRef state = C.
getState();
1119 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1129 ProgramStateRef state = C.
getState();
1131 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1139 evalCopyCommon(C, CE, C.
getState(),
1148 CurrentFunctionDescription =
"memory comparison function";
1154 ProgramStateRef state = C.
getState();
1159 SVal sizeVal = state->getSVal(Size, LCtx);
1162 ProgramStateRef stateZeroSize, stateNonZeroSize;
1163 std::tie(stateZeroSize, stateNonZeroSize) =
1164 assumeZero(C, state, sizeVal, sizeTy);
1168 if (stateZeroSize) {
1169 state = stateZeroSize;
1170 state = state->BindExpr(CE, LCtx,
1176 if (stateNonZeroSize) {
1177 state = stateNonZeroSize;
1188 ProgramStateRef StSameBuf, StNotSameBuf;
1189 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1195 state = CheckBufferAccess(C, state, Size, Left);
1197 state = StSameBuf->BindExpr(CE, LCtx,
1206 state = StNotSameBuf;
1207 state = CheckBufferAccess(C, state, Size, Left, Right);
1212 state = state->BindExpr(CE, LCtx, CmpV);
1225 evalstrLengthCommon(C, CE,
false);
1234 evalstrLengthCommon(C, CE,
true);
1238 bool IsStrnlen)
const {
1239 CurrentFunctionDescription =
"string length function";
1240 ProgramStateRef state = C.
getState();
1245 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1247 ProgramStateRef stateZeroSize, stateNonZeroSize;
1248 std::tie(stateZeroSize, stateNonZeroSize) =
1249 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1253 if (stateZeroSize) {
1255 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1260 if (!stateNonZeroSize)
1264 state = stateNonZeroSize;
1269 SVal ArgVal = state->getSVal(Arg, LCtx);
1271 state = checkNonNull(C, state, Arg, ArgVal);
1276 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1293 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1298 if (strLengthNL && maxlenValNL) {
1299 ProgramStateRef stateStringTooLong, stateStringNotTooLong;
1302 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1307 if (stateStringTooLong && !stateStringNotTooLong) {
1309 result = *maxlenValNL;
1310 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1312 result = *strLengthNL;
1327 state,
BO_LE, resultNL, *strLengthNL, cmpTy)
1333 state,
BO_LE, resultNL, *maxlenValNL, cmpTy)
1351 assert(!result.
isUnknown() &&
"Should have conjured a value by now");
1352 state = state->BindExpr(CE, LCtx, result);
1361 evalStrcpyCommon(C, CE,
1372 evalStrcpyCommon(C, CE,
1383 evalStrcpyCommon(C, CE,
1394 evalStrcpyCommon(C, CE,
1405 evalStrcpyCommon(C, CE,
1412 bool returnEnd,
bool isBounded,
1413 bool isAppending)
const {
1414 CurrentFunctionDescription =
"string copy function";
1415 ProgramStateRef state = C.
getState();
1420 SVal DstVal = state->getSVal(Dst, LCtx);
1422 state = checkNonNull(C, state, Dst, DstVal);
1428 SVal srcVal = state->getSVal(srcExpr, LCtx);
1429 state = checkNonNull(C, state, srcExpr, srcVal);
1434 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1449 const char *boundWarning =
nullptr;
1455 SVal lenVal = state->getSVal(lenExpr, LCtx);
1465 if (strLengthNL && lenValNL) {
1466 ProgramStateRef stateSourceTooLong, stateSourceNotTooLong;
1471 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1475 if (stateSourceTooLong && !stateSourceNotTooLong) {
1478 state = stateSourceTooLong;
1479 amountCopied = lenVal;
1481 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1483 state = stateSourceNotTooLong;
1484 amountCopied = strLength;
1496 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1505 boundWarning =
"Size argument is greater than the free space in the "
1506 "destination buffer";
1517 ProgramStateRef StateZeroSize, StateNonZeroSize;
1518 std::tie(StateZeroSize, StateNonZeroSize) =
1519 assumeZero(C, state, *lenValNL, sizeTy);
1522 if (StateZeroSize && !StateNonZeroSize) {
1523 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1534 boundWarning =
"Size argument is greater than the length of the "
1535 "destination buffer";
1543 if (amountCopied.
isUnknown() && !isAppending) {
1546 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1547 assert(!amountCopied.
isUndef());
1556 state = state->assume(
1568 state = state->assume(
1579 amountCopied = strLength;
1595 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1603 if (srcStrLengthNL && dstStrLengthNL) {
1605 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1610 *dstStrLengthNL, sizeTy);
1618 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1619 assert(!finalStrLength.
isUndef());
1622 if (srcStrLengthNL) {
1634 if (dstStrLengthNL) {
1651 finalStrLength = amountCopied;
1672 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1682 *knownStrLength, ptrTy);
1685 if (!boundWarning) {
1686 const char *
const warningMsg =
1687 "String copy function overflows destination buffer";
1688 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1695 Result = lastElement;
1705 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1710 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true,
1714 if (isBounded && !isAppending) {
1719 if (amountCopied != strLength)
1720 finalStrLength = UnknownVal();
1722 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1734 state = state->BindExpr(CE, LCtx, Result);
1743 evalStrcmpCommon(C, CE,
false,
false);
1751 evalStrcmpCommon(C, CE,
true,
false);
1760 evalStrcmpCommon(C, CE,
false,
true);
1769 evalStrcmpCommon(C, CE,
true,
true);
1773 bool isBounded,
bool ignoreCase)
const {
1774 CurrentFunctionDescription =
"string comparison function";
1775 ProgramStateRef state = C.
getState();
1780 SVal s1Val = state->getSVal(s1, LCtx);
1781 state = checkNonNull(C, state, s1, s1Val);
1787 SVal s2Val = state->getSVal(s2, LCtx);
1788 state = checkNonNull(C, state, s2, s2Val);
1793 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1798 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1811 ProgramStateRef StSameBuf, StNotSameBuf;
1812 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1817 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1818 svalBuilder.makeZeroVal(CE->
getType()));
1826 assert(StNotSameBuf);
1827 state = StNotSameBuf;
1833 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1834 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1835 bool canComputeResult =
false;
1837 if (s1StrLiteral && s2StrLiteral) {
1838 StringRef s1StrRef = s1StrLiteral->
getString();
1839 StringRef s2StrRef = s2StrLiteral->
getString();
1844 SVal lenVal = state->getSVal(lenExpr, LCtx);
1847 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1849 s1StrRef = s1StrRef.substr(0, (
size_t)len->getZExtValue());
1850 s2StrRef = s2StrRef.substr(0, (
size_t)len->getZExtValue());
1851 canComputeResult =
true;
1855 canComputeResult =
true;
1858 if (canComputeResult) {
1860 size_t s1Term = s1StrRef.find(
'\0');
1861 if (s1Term != StringRef::npos)
1862 s1StrRef = s1StrRef.substr(0, s1Term);
1864 size_t s2Term = s2StrRef.find(
'\0');
1865 if (s2Term != StringRef::npos)
1866 s2StrRef = s2StrRef.substr(0, s2Term);
1873 result = s1StrRef.compare_lower(s2StrRef);
1876 result = s1StrRef.compare(s2StrRef);
1880 SVal resultVal = svalBuilder.makeIntVal(result, CE->
getType());
1881 state = state->BindExpr(CE, LCtx, resultVal);
1885 if (!canComputeResult) {
1887 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1889 state = state->BindExpr(CE, LCtx, resultVal);
1904 if (CharPtrTy.
isNull() ||
1908 CurrentFunctionDescription =
"strsep()";
1914 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
1915 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
1921 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
1922 State = checkNonNull(C, State, DelimStr, DelimStrVal);
1930 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
1934 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
1939 State = State->bindLoc(*SearchStrLoc,
1949 State = State->BindExpr(CE, LCtx, Result);
1965 FnCheck evalFunction =
nullptr;
1967 evalFunction = &CStringChecker::evalMemcpy;
1969 evalFunction = &CStringChecker::evalMempcpy;
1971 evalFunction = &CStringChecker::evalMemcmp;
1973 evalFunction = &CStringChecker::evalMemmove;
1975 evalFunction = &CStringChecker::evalStrcpy;
1977 evalFunction = &CStringChecker::evalStrncpy;
1979 evalFunction = &CStringChecker::evalStpcpy;
1981 evalFunction = &CStringChecker::evalStrcat;
1983 evalFunction = &CStringChecker::evalStrncat;
1985 evalFunction = &CStringChecker::evalstrLength;
1987 evalFunction = &CStringChecker::evalstrnLength;
1989 evalFunction = &CStringChecker::evalStrcmp;
1991 evalFunction = &CStringChecker::evalStrncmp;
1993 evalFunction = &CStringChecker::evalStrcasecmp;
1995 evalFunction = &CStringChecker::evalStrncasecmp;
1997 evalFunction = &CStringChecker::evalStrsep;
1999 evalFunction = &CStringChecker::evalBcopy;
2001 evalFunction = &CStringChecker::evalMemcmp;
2008 (this->*evalFunction)(C, CE);
2021 ProgramStateRef state = C.
getState();
2023 for (
const auto *
I : DS->
decls()) {
2035 if (!isa<StringLiteral>(Init))
2044 assert(StrVal.
isValid() &&
"Initializer string is unknown or undefined");
2048 state = state->set<CStringLength>(MR, strLength);
2054 bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state)
const {
2055 CStringLengthTy Entries = state->get<CStringLength>();
2056 return !Entries.isEmpty();
2060 CStringChecker::checkRegionChanges(ProgramStateRef state,
2065 CStringLengthTy Entries = state->get<CStringLength>();
2066 if (Entries.isEmpty())
2069 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
2070 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
2074 I = Regions.begin(), E = Regions.end();
I !=
E; ++
I) {
2076 Invalidated.insert(MR);
2078 SuperRegions.insert(MR);
2079 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2080 MR = SR->getSuperRegion();
2081 SuperRegions.insert(MR);
2085 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2089 E = Entries.end();
I !=
E; ++
I) {
2093 if (SuperRegions.count(MR)) {
2094 Entries = F.remove(Entries, MR);
2100 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2101 Super = SR->getSuperRegion();
2102 if (Invalidated.count(Super)) {
2103 Entries = F.remove(Entries, MR);
2109 return state->set<CStringLength>(Entries);
2112 void CStringChecker::checkLiveSymbols(ProgramStateRef state,
2115 CStringLengthTy Entries = state->get<CStringLength>();
2119 SVal Len =
I.getData();
2127 void CStringChecker::checkDeadSymbols(
SymbolReaper &SR,
2132 ProgramStateRef state = C.
getState();
2133 CStringLengthTy Entries = state->get<CStringLength>();
2134 if (Entries.isEmpty())
2137 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2140 SVal Len =
I.getData();
2143 Entries = F.remove(Entries,
I.getKey());
2147 state = state->set<CStringLength>(Entries);
2151 #define REGISTER_CHECKER(name) \
2152 void ento::register##name(CheckerManager &mgr) { \
2153 CStringChecker *checker = mgr.registerChecker<CStringChecker>(); \
2154 checker->Filter.Check##name = true; \
2155 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
2164 registerCStringNullArg(Mgr);
Suppress pointer-escaping of a region.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
TypedValueRegion - An abstract class representing regions having a typed value.
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
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).
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.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
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
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
Create a new value which represents a binary expression with a memory location and non-location opera...
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
detail::InMemoryDirectory::const_iterator I
const MemRegion * getSuperRegion() const
const LocationContext * getLocationContext() const
#define REGISTER_CHECKER(name)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
const MemRegion * StripCasts(bool StripBaseCasts=true) const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
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.
Expr - This represents one expression.
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
Create a new value which represents a binary expression with two memory location operands.
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
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'.
const TemplateArgument * iterator
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
ASTContext & getContext()
SymExpr::symbol_iterator symbol_end() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
A class responsible for cleaning up unused symbols.
const llvm::APSInt * evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)
Tells that a region's contents is not changed.
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
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)
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Represents an abstract call to a function or method along a particular path.
SVal convertToArrayIndex(SVal val)
BasicValueFactory & getBasicValueFactory()
SubRegion - A region that subsets another larger region.
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)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
QualType getValueType() const override
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
SValBuilder & getSValBuilder()
StringLiteral - This represents a string literal expression, e.g.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
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)
Converts the given ASCII character to its uppercase equivalent.
NamedDecl - This represents a decl with a name.
bool isNull() const
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.