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;
126 std::pair<ProgramStateRef , ProgramStateRef >
142 bool hypothetical =
false)
const;
155 static bool SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
167 const char *message =
nullptr)
const;
171 const Expr *FirstBuf,
172 const Expr *SecondBuf,
173 const char *firstMessage =
nullptr,
174 const char *secondMessage =
nullptr,
175 bool WarnAboutSize =
false)
const;
181 const char *message =
nullptr,
182 bool WarnAboutSize =
false)
const {
184 return CheckBufferAccess(C, state, Size, Buf,
nullptr, message,
nullptr,
191 const Expr *Second)
const;
195 const Stmt *Second)
const;
207 const Expr *FirstBuf,
224 return std::pair<ProgramStateRef , ProgramStateRef >(
state,
state);
228 return state->assume(svalBuilder.evalEQ(state, *val, zero));
232 ProgramStateRef state,
238 ProgramStateRef stateNull, stateNonNull;
239 std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->
getType());
241 if (stateNull && !stateNonNull) {
242 if (!Filter.CheckCStringNullArg)
252 "Null pointer argument in call to byte string function"));
255 llvm::raw_svector_ostream os(buf);
256 assert(CurrentFunctionDescription);
257 os <<
"Null pointer argument in call to " << CurrentFunctionDescription;
261 auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
263 report->addRange(S->getSourceRange());
270 assert(stateNonNull);
276 ProgramStateRef state,
278 const char *warningMsg)
const {
293 "CheckLocation should only be called with char* ElementRegions");
299 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
305 ProgramStateRef StInBound = state->assumeInBound(Idx, Size,
true);
306 ProgramStateRef StOutBound = state->assumeInBound(Idx, Size,
false);
307 if (StOutBound && !StInBound) {
314 Filter.CheckNameCStringOutOfBounds,
"Out-of-bound array access",
315 "Byte string function accesses out-of-bound array element"));
320 std::unique_ptr<BugReport> report;
322 report = llvm::make_unique<BugReport>(*BT, warningMsg, N);
324 assert(CurrentFunctionDescription);
325 assert(CurrentFunctionDescription[0] !=
'\0');
328 llvm::raw_svector_ostream os(buf);
330 << &CurrentFunctionDescription[1]
331 <<
" accesses out-of-bound array element";
332 report = llvm::make_unique<BugReport>(*BT, os.str(), N);
339 report->addRange(S->getSourceRange());
349 ProgramStateRef CStringChecker::CheckBufferAccess(
CheckerContext &C,
350 ProgramStateRef state,
352 const Expr *FirstBuf,
353 const Expr *SecondBuf,
354 const char *firstMessage,
355 const char *secondMessage,
356 bool WarnAboutSize)
const {
369 SVal BufVal = state->getSVal(FirstBuf, LCtx);
370 state = checkNonNull(C, state, FirstBuf, BufVal);
375 if (!Filter.CheckCStringOutOfBounds)
381 SVal LengthVal = state->getSVal(Size, LCtx);
388 NonLoc LastOffset = svalBuilder
394 const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
398 state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
407 BufVal = state->getSVal(SecondBuf, LCtx);
408 state = checkNonNull(C, state, SecondBuf, BufVal);
414 const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
418 state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
427 ProgramStateRef state,
430 const Expr *Second)
const {
431 if (!Filter.CheckCStringBufferOverlap)
442 ProgramStateRef stateTrue, stateFalse;
446 SVal firstVal = state->getSVal(First, LCtx);
447 SVal secondVal = state->getSVal(Second, LCtx);
459 std::tie(stateTrue, stateFalse) =
460 state->assume(svalBuilder.
evalEQ(state, *firstLoc, *secondLoc));
462 if (stateTrue && !stateFalse) {
464 emitOverlapBug(C, stateTrue, First, Second);
475 *firstLoc, *secondLoc, cmpTy);
481 std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
488 std::swap(firstLoc, secondLoc);
491 std::swap(First, Second);
496 SVal LengthVal = state->getSVal(Size, LCtx);
505 SVal FirstStart = svalBuilder.
evalCast(*firstLoc, CharPtrTy,
513 *FirstStartLoc, *Length, CharPtrTy);
520 *FirstEndLoc, *secondLoc, cmpTy);
526 std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
528 if (stateTrue && !stateFalse) {
530 emitOverlapBug(C, stateTrue, First, Second);
539 void CStringChecker::emitOverlapBug(
CheckerContext &C, ProgramStateRef state,
540 const Stmt *First,
const Stmt *Second)
const {
546 BT_Overlap.reset(
new BugType(Filter.CheckNameCStringBufferOverlap,
550 auto report = llvm::make_unique<BugReport>(
551 *BT_Overlap,
"Arguments must not be overlapping buffers", N);
552 report->addRange(First->getSourceRange());
553 report->addRange(Second->getSourceRange());
558 ProgramStateRef CStringChecker::checkAdditionOverflow(
CheckerContext &C,
559 ProgramStateRef state,
563 if (!Filter.CheckCStringOutOfBounds)
574 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
579 maxMinusRight = svalBuilder.
evalBinOpNN(state, BO_Sub, maxVal, right,
584 maxMinusRight = svalBuilder.
evalBinOpNN(state, BO_Sub, maxVal, left,
593 *maxMinusRightNL, cmpTy);
595 ProgramStateRef stateOverflow, stateOkay;
596 std::tie(stateOverflow, stateOkay) =
599 if (stateOverflow && !stateOkay) {
605 if (!BT_AdditionOverflow)
606 BT_AdditionOverflow.reset(
607 new BuiltinBug(Filter.CheckNameCStringOutOfBounds,
"API",
608 "Sum of expressions causes overflow"));
613 const char *warning =
614 "This expression will create a string whose length is too big to "
615 "be represented as a size_t";
619 llvm::make_unique<BugReport>(*BT_AdditionOverflow, warning, N));
632 ProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state,
635 assert(!strLength.
isUndef() &&
"Attempt to set an undefined string length");
639 switch (MR->getKind()) {
640 case MemRegion::StringRegionKind:
645 case MemRegion::SymbolicRegionKind:
646 case MemRegion::AllocaRegionKind:
647 case MemRegion::VarRegionKind:
648 case MemRegion::FieldRegionKind:
649 case MemRegion::ObjCIvarRegionKind:
653 case MemRegion::ElementRegionKind:
667 return state->remove<CStringLength>(MR);
669 return state->set<CStringLength>(MR, strLength);
673 ProgramStateRef &state,
679 const SVal *Recorded = state->get<CStringLength>(MR);
695 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
697 const llvm::APSInt *maxLengthInt = BVF.
evalAPSInt(BO_Div, maxValInt,
704 state = state->set<CStringLength>(MR, strLength);
712 bool hypothetical)
const {
719 if (!Filter.CheckCStringNotNullTerm)
726 "Argument is not a null-terminated string."));
729 llvm::raw_svector_ostream os(buf);
730 assert(CurrentFunctionDescription);
731 os <<
"Argument to " << CurrentFunctionDescription
732 <<
" is the address of the label '" << Label->getLabel()->getName()
733 <<
"', which is not a null-terminated string";
736 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
738 report->addRange(Ex->getSourceRange());
754 case MemRegion::StringRegionKind: {
759 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
762 case MemRegion::SymbolicRegionKind:
763 case MemRegion::AllocaRegionKind:
764 case MemRegion::VarRegionKind:
765 case MemRegion::FieldRegionKind:
766 case MemRegion::ObjCIvarRegionKind:
767 return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
768 case MemRegion::CompoundLiteralRegionKind:
771 case MemRegion::ElementRegionKind:
779 if (!Filter.CheckCStringNotNullTerm)
786 "Argument is not a null-terminated string."));
789 llvm::raw_svector_ostream os(buf);
791 assert(CurrentFunctionDescription);
792 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
795 os <<
", which is not a null-terminated string";
797 os <<
"not a null-terminated string";
800 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
802 report->addRange(Ex->getSourceRange());
811 ProgramStateRef &state,
const Expr *
expr,
SVal val)
const {
831 ProgramStateRef state,
832 const Expr *FirstBuf,
845 SVal BufVal = state->getSVal(FirstBuf, LCtx);
847 SVal LengthVal = state->getSVal(Size, LCtx);
855 svalBuilder.
evalBinOpNN(state, BO_Sub, *Length, One, sizeTy)
865 svalBuilder.
evalBinOpLN(state, BO_Add, *BufLoc, LastOffset, PtrTy);
877 "IsFirstBufInBound should only be called with char* ElementRegions");
888 ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize,
true);
890 return static_cast<bool>(StInBound);
893 ProgramStateRef CStringChecker::InvalidateBuffer(
CheckerContext &C,
894 ProgramStateRef state,
918 bool CausesPointerEscape =
false;
922 if (IsSourceBuffer) {
926 CausesPointerEscape =
true;
929 if (K == MemRegion::FieldRegionKind)
930 if (Size && IsFirstBufInBound(C, state, E, Size)) {
939 return state->invalidateRegions(R, E, C.
blockCount(), LCtx,
940 CausesPointerEscape,
nullptr,
nullptr,
947 return state->killBinding(*L);
950 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
955 case MemRegion::FunctionCodeRegionKind: {
956 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
958 os <<
"the address of the function '" << *FD <<
'\'';
960 os <<
"the address of a function";
963 case MemRegion::BlockCodeRegionKind:
966 case MemRegion::BlockDataRegionKind:
969 case MemRegion::CXXThisRegionKind:
970 case MemRegion::CXXTempObjectRegionKind:
973 case MemRegion::VarRegionKind:
976 case MemRegion::FieldRegionKind:
979 case MemRegion::ObjCIvarRegionKind:
993 ProgramStateRef state,
995 const Expr *Source,
bool Restricted,
996 bool IsMempcpy)
const {
997 CurrentFunctionDescription =
"memory copy function";
1001 SVal sizeVal = state->getSVal(Size, LCtx);
1004 ProgramStateRef stateZeroSize, stateNonZeroSize;
1005 std::tie(stateZeroSize, stateNonZeroSize) =
1006 assumeZero(C, state, sizeVal, sizeTy);
1009 SVal destVal = state->getSVal(Dest, LCtx);
1013 if (stateZeroSize && !stateNonZeroSize) {
1014 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1020 if (stateNonZeroSize) {
1021 state = stateNonZeroSize;
1025 state = checkNonNull(C, state, Dest, destVal);
1030 SVal srcVal = state->getSVal(Source, LCtx);
1034 state = checkNonNull(C, state, Source, srcVal);
1039 const char *
const writeWarning =
1040 "Memory copy function overflows destination buffer";
1041 state = CheckBufferAccess(C, state, Size, Dest, Source,
1042 writeWarning,
nullptr);
1044 state = CheckOverlap(C, state, Size, Dest, Source);
1061 CharPtrTy, Dest->
getType()).castAs<loc::MemRegionVal>();
1068 state = state->BindExpr(CE, LCtx, lastElement);
1074 state = state->BindExpr(CE, LCtx, result);
1080 state = state->BindExpr(CE, LCtx, destVal);
1089 state = InvalidateBuffer(C, state, Dest, C.
getSVal(Dest),
1094 state = InvalidateBuffer(C, state, Source, C.
getSVal(Source),
1109 ProgramStateRef state = C.
getState();
1111 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1121 ProgramStateRef state = C.
getState();
1123 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1133 ProgramStateRef state = C.
getState();
1135 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1143 evalCopyCommon(C, CE, C.
getState(),
1152 CurrentFunctionDescription =
"memory comparison function";
1158 ProgramStateRef state = C.
getState();
1163 SVal sizeVal = state->getSVal(Size, LCtx);
1166 ProgramStateRef stateZeroSize, stateNonZeroSize;
1167 std::tie(stateZeroSize, stateNonZeroSize) =
1168 assumeZero(C, state, sizeVal, sizeTy);
1172 if (stateZeroSize) {
1173 state = stateZeroSize;
1174 state = state->BindExpr(CE, LCtx,
1180 if (stateNonZeroSize) {
1181 state = stateNonZeroSize;
1192 ProgramStateRef StSameBuf, StNotSameBuf;
1193 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1199 state = CheckBufferAccess(C, state, Size, Left);
1201 state = StSameBuf->BindExpr(CE, LCtx,
1210 state = StNotSameBuf;
1211 state = CheckBufferAccess(C, state, Size, Left, Right);
1216 state = state->BindExpr(CE, LCtx, CmpV);
1229 evalstrLengthCommon(C, CE,
false);
1238 evalstrLengthCommon(C, CE,
true);
1242 bool IsStrnlen)
const {
1243 CurrentFunctionDescription =
"string length function";
1244 ProgramStateRef state = C.
getState();
1249 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1251 ProgramStateRef stateZeroSize, stateNonZeroSize;
1252 std::tie(stateZeroSize, stateNonZeroSize) =
1253 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1257 if (stateZeroSize) {
1259 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1264 if (!stateNonZeroSize)
1268 state = stateNonZeroSize;
1273 SVal ArgVal = state->getSVal(Arg, LCtx);
1275 state = checkNonNull(C, state, Arg, ArgVal);
1280 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1297 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1302 if (strLengthNL && maxlenValNL) {
1303 ProgramStateRef stateStringTooLong, stateStringNotTooLong;
1306 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1308 .
evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1311 if (stateStringTooLong && !stateStringNotTooLong) {
1313 result = *maxlenValNL;
1314 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1316 result = *strLengthNL;
1331 state, BO_LE, resultNL, *strLengthNL, cmpTy)
1337 state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1355 assert(!result.
isUnknown() &&
"Should have conjured a value by now");
1356 state = state->BindExpr(CE, LCtx, result);
1365 evalStrcpyCommon(C, CE,
1376 evalStrcpyCommon(C, CE,
1387 evalStrcpyCommon(C, CE,
1398 evalStrcpyCommon(C, CE,
1409 evalStrcpyCommon(C, CE,
1416 bool returnEnd,
bool isBounded,
1417 bool isAppending)
const {
1418 CurrentFunctionDescription =
"string copy function";
1419 ProgramStateRef state = C.
getState();
1424 SVal DstVal = state->getSVal(Dst, LCtx);
1426 state = checkNonNull(C, state, Dst, DstVal);
1432 SVal srcVal = state->getSVal(srcExpr, LCtx);
1433 state = checkNonNull(C, state, srcExpr, srcVal);
1438 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1453 const char *boundWarning =
nullptr;
1459 SVal lenVal = state->getSVal(lenExpr, LCtx);
1469 if (strLengthNL && lenValNL) {
1470 ProgramStateRef stateSourceTooLong, stateSourceNotTooLong;
1475 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1476 svalBuilder.
evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1479 if (stateSourceTooLong && !stateSourceNotTooLong) {
1482 state = stateSourceTooLong;
1483 amountCopied = lenVal;
1485 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1487 state = stateSourceNotTooLong;
1488 amountCopied = strLength;
1500 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1505 maxLastElementIndex = svalBuilder.
evalBinOpNN(state, BO_Add,
1509 boundWarning =
"Size argument is greater than the free space in the "
1510 "destination buffer";
1521 ProgramStateRef StateZeroSize, StateNonZeroSize;
1522 std::tie(StateZeroSize, StateNonZeroSize) =
1523 assumeZero(C, state, *lenValNL, sizeTy);
1526 if (StateZeroSize && !StateNonZeroSize) {
1527 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1536 maxLastElementIndex = svalBuilder.
evalBinOpNN(state, BO_Sub, *lenValNL,
1538 boundWarning =
"Size argument is greater than the length of the "
1539 "destination buffer";
1547 if (amountCopied.
isUnknown() && !isAppending) {
1550 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1551 assert(!amountCopied.
isUndef());
1560 state = state->assume(
1572 state = state->assume(
1583 amountCopied = strLength;
1599 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1607 if (srcStrLengthNL && dstStrLengthNL) {
1609 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1613 finalStrLength = svalBuilder.
evalBinOpNN(state, BO_Add, *srcStrLengthNL,
1614 *dstStrLengthNL, sizeTy);
1622 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1623 assert(!finalStrLength.
isUndef());
1626 if (srcStrLengthNL) {
1638 if (dstStrLengthNL) {
1655 finalStrLength = amountCopied;
1674 SVal maxLastElement = svalBuilder.
evalBinOpLN(state, BO_Add, *dstRegVal,
1676 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1686 *knownStrLength, ptrTy);
1689 if (!boundWarning) {
1690 const char *
const warningMsg =
1691 "String copy function overflows destination buffer";
1692 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1699 Result = lastElement;
1709 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1714 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true,
1718 if (isBounded && !isAppending) {
1723 if (amountCopied != strLength)
1724 finalStrLength = UnknownVal();
1726 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1738 state = state->BindExpr(CE, LCtx, Result);
1747 evalStrcmpCommon(C, CE,
false,
false);
1755 evalStrcmpCommon(C, CE,
true,
false);
1764 evalStrcmpCommon(C, CE,
false,
true);
1773 evalStrcmpCommon(C, CE,
true,
true);
1777 bool isBounded,
bool ignoreCase)
const {
1778 CurrentFunctionDescription =
"string comparison function";
1779 ProgramStateRef state = C.
getState();
1784 SVal s1Val = state->getSVal(s1, LCtx);
1785 state = checkNonNull(C, state, s1, s1Val);
1791 SVal s2Val = state->getSVal(s2, LCtx);
1792 state = checkNonNull(C, state, s2, s2Val);
1797 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1802 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1815 ProgramStateRef StSameBuf, StNotSameBuf;
1816 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1821 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1822 svalBuilder.makeZeroVal(CE->
getType()));
1830 assert(StNotSameBuf);
1831 state = StNotSameBuf;
1837 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1838 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1839 bool canComputeResult =
false;
1840 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1843 if (s1StrLiteral && s2StrLiteral) {
1844 StringRef s1StrRef = s1StrLiteral->
getString();
1845 StringRef s2StrRef = s2StrLiteral->
getString();
1850 SVal lenVal = state->getSVal(lenExpr, LCtx);
1853 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1855 s1StrRef = s1StrRef.substr(0, (
size_t)len->getZExtValue());
1856 s2StrRef = s2StrRef.substr(0, (
size_t)len->getZExtValue());
1857 canComputeResult =
true;
1861 canComputeResult =
true;
1864 if (canComputeResult) {
1866 size_t s1Term = s1StrRef.find(
'\0');
1867 if (s1Term != StringRef::npos)
1868 s1StrRef = s1StrRef.substr(0, s1Term);
1870 size_t s2Term = s2StrRef.find(
'\0');
1871 if (s2Term != StringRef::npos)
1872 s2StrRef = s2StrRef.substr(0, s2Term);
1875 int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
1876 : s1StrRef.compare(s2StrRef);
1880 if (compareRes == 0) {
1881 resultVal = svalBuilder.makeIntVal(compareRes, CE->
getType());
1888 SVal compareWithZero =
1889 svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
1890 svalBuilder.getConditionType());
1892 state = state->assume(compareWithZeroVal,
true);
1897 state = state->BindExpr(CE, LCtx, resultVal);
1911 if (CharPtrTy.
isNull() ||
1915 CurrentFunctionDescription =
"strsep()";
1921 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
1922 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
1928 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
1929 State = checkNonNull(C, State, DelimStr, DelimStrVal);
1937 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
1941 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
1946 State = State->bindLoc(*SearchStrLoc,
1956 State = State->BindExpr(CE, LCtx, Result);
1962 evalStdCopyCommon(C, CE);
1967 evalStdCopyCommon(C, CE);
1975 ProgramStateRef State = C.
getState();
1986 SVal DstVal = State->getSVal(Dst, LCtx);
1987 State = InvalidateBuffer(C, State, Dst, DstVal,
false,
1993 State = State->BindExpr(CE, LCtx, ResultVal);
2006 if (II->
getName().equals(Name))
2022 FnCheck evalFunction =
nullptr;
2024 evalFunction = &CStringChecker::evalMemcpy;
2026 evalFunction = &CStringChecker::evalMempcpy;
2028 evalFunction = &CStringChecker::evalMemcmp;
2030 evalFunction = &CStringChecker::evalMemmove;
2032 evalFunction = &CStringChecker::evalStrcpy;
2034 evalFunction = &CStringChecker::evalStrncpy;
2036 evalFunction = &CStringChecker::evalStpcpy;
2038 evalFunction = &CStringChecker::evalStrcat;
2040 evalFunction = &CStringChecker::evalStrncat;
2042 evalFunction = &CStringChecker::evalstrLength;
2044 evalFunction = &CStringChecker::evalstrnLength;
2046 evalFunction = &CStringChecker::evalStrcmp;
2048 evalFunction = &CStringChecker::evalStrncmp;
2050 evalFunction = &CStringChecker::evalStrcasecmp;
2052 evalFunction = &CStringChecker::evalStrncasecmp;
2054 evalFunction = &CStringChecker::evalStrsep;
2056 evalFunction = &CStringChecker::evalBcopy;
2058 evalFunction = &CStringChecker::evalMemcmp;
2060 evalFunction = &CStringChecker::evalStdCopy;
2062 evalFunction = &CStringChecker::evalStdCopyBackward;
2069 (this->*evalFunction)(C, CE);
2082 ProgramStateRef state = C.
getState();
2084 for (
const auto *
I : DS->
decls()) {
2096 if (!isa<StringLiteral>(Init))
2105 assert(StrVal.
isValid() &&
"Initializer string is unknown or undefined");
2109 state = state->set<CStringLength>(MR, strLength);
2115 bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state)
const {
2116 CStringLengthTy Entries = state->get<CStringLength>();
2117 return !Entries.isEmpty();
2121 CStringChecker::checkRegionChanges(ProgramStateRef state,
2126 CStringLengthTy Entries = state->get<CStringLength>();
2127 if (Entries.isEmpty())
2130 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
2131 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
2135 I = Regions.begin(), E = Regions.end();
I !=
E; ++
I) {
2137 Invalidated.insert(MR);
2139 SuperRegions.insert(MR);
2140 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2141 MR = SR->getSuperRegion();
2142 SuperRegions.insert(MR);
2146 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2150 E = Entries.end();
I !=
E; ++
I) {
2154 if (SuperRegions.count(MR)) {
2155 Entries = F.remove(Entries, MR);
2161 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2162 Super = SR->getSuperRegion();
2163 if (Invalidated.count(Super)) {
2164 Entries = F.remove(Entries, MR);
2170 return state->set<CStringLength>(Entries);
2173 void CStringChecker::checkLiveSymbols(ProgramStateRef state,
2176 CStringLengthTy Entries = state->get<CStringLength>();
2180 SVal Len =
I.getData();
2188 void CStringChecker::checkDeadSymbols(
SymbolReaper &SR,
2193 ProgramStateRef state = C.
getState();
2194 CStringLengthTy Entries = state->get<CStringLength>();
2195 if (Entries.isEmpty())
2198 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2201 SVal Len =
I.getData();
2204 Entries = F.remove(Entries,
I.getKey());
2208 state = state->set<CStringLength>(Entries);
2212 #define REGISTER_CHECKER(name) \
2213 void ento::register##name(CheckerManager &mgr) { \
2214 CStringChecker *checker = mgr.registerChecker<CStringChecker>(); \
2215 checker->Filter.Check##name = true; \
2216 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
2225 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
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
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
const MemRegion * getBaseRegion() const
void markInUse(SymbolRef sym)
Marks a symbol as important to a checker.
One of these records is kept for each identifier that is lexed.
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...
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
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...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
void registerCStringCheckerBasic(CheckerManager &Mgr)
Register the checker which evaluates CString API calls.
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
const StringLiteral * getStringLiteral() const
static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name)
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.
StringRef getName() const
Return the actual identifier string.
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.