23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/Support/raw_ostream.h"
27 using namespace clang;
31 class CStringChecker :
public Checker< eval::Call,
32 check::PreStmt<DeclStmt>,
37 mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap,
38 BT_NotCString, BT_AdditionOverflow;
40 mutable const char *CurrentFunctionDescription;
45 struct CStringChecksFilter {
57 CStringChecksFilter Filter;
59 static void *getTag() {
static int tag;
return &tag; }
86 bool Restricted =
false,
87 bool IsMempcpy =
false)
const;
95 bool IsStrnlen =
false)
const;
104 bool isAppending)
const;
115 bool isBounded =
false,
116 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);
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);
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);
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);
696 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
698 const llvm::APSInt *maxLengthInt = BVF.
evalAPSInt(BO_Div, maxValInt,
705 state = state->set<CStringLength>(MR, strLength);
713 bool hypothetical)
const {
720 if (!Filter.CheckCStringNotNullTerm)
727 "Argument is not a null-terminated string."));
730 llvm::raw_svector_ostream os(buf);
731 assert(CurrentFunctionDescription);
732 os <<
"Argument to " << CurrentFunctionDescription
733 <<
" is the address of the label '" <<
Label->getLabel()->getName()
734 <<
"', which is not a null-terminated string";
737 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
755 case MemRegion::StringRegionKind: {
760 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
763 case MemRegion::SymbolicRegionKind:
764 case MemRegion::AllocaRegionKind:
765 case MemRegion::VarRegionKind:
766 case MemRegion::FieldRegionKind:
767 case MemRegion::ObjCIvarRegionKind:
768 return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
769 case MemRegion::CompoundLiteralRegionKind:
772 case MemRegion::ElementRegionKind:
780 if (!Filter.CheckCStringNotNullTerm)
787 "Argument is not a null-terminated string."));
790 llvm::raw_svector_ostream os(buf);
792 assert(CurrentFunctionDescription);
793 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
796 os <<
", which is not a null-terminated string";
798 os <<
"not a null-terminated string";
801 auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
812 ProgramStateRef &state,
const Expr *
expr,
SVal val)
const {
832 ProgramStateRef state,
833 const Expr *FirstBuf,
846 SVal BufVal = state->getSVal(FirstBuf, LCtx);
848 SVal LengthVal = state->getSVal(Size, LCtx);
856 svalBuilder.
evalBinOpNN(state, BO_Sub, *Length, One, sizeTy)
866 svalBuilder.
evalBinOpLN(state, BO_Add, *BufLoc, LastOffset, PtrTy);
878 "IsFirstBufInBound should only be called with char* ElementRegions");
889 ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize,
true);
891 return static_cast<bool>(StInBound);
894 ProgramStateRef CStringChecker::InvalidateBuffer(
CheckerContext &C,
895 ProgramStateRef state,
919 bool CausesPointerEscape =
false;
923 if (IsSourceBuffer) {
927 CausesPointerEscape =
true;
930 if (K == MemRegion::FieldRegionKind)
931 if (Size && IsFirstBufInBound(C, state, E, Size)) {
940 return state->invalidateRegions(R, E, C.
blockCount(), LCtx,
941 CausesPointerEscape,
nullptr,
nullptr,
948 return state->killBinding(*L);
951 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
956 case MemRegion::FunctionCodeRegionKind: {
957 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
959 os <<
"the address of the function '" << *FD <<
'\'';
961 os <<
"the address of a function";
964 case MemRegion::BlockCodeRegionKind:
967 case MemRegion::BlockDataRegionKind:
970 case MemRegion::CXXThisRegionKind:
971 case MemRegion::CXXTempObjectRegionKind:
974 case MemRegion::VarRegionKind:
977 case MemRegion::FieldRegionKind:
980 case MemRegion::ObjCIvarRegionKind:
994 ProgramStateRef state,
996 const Expr *Source,
bool Restricted,
997 bool IsMempcpy)
const {
998 CurrentFunctionDescription =
"memory copy function";
1002 SVal sizeVal = state->getSVal(Size, LCtx);
1005 ProgramStateRef stateZeroSize, stateNonZeroSize;
1006 std::tie(stateZeroSize, stateNonZeroSize) =
1007 assumeZero(C, state, sizeVal, sizeTy);
1010 SVal destVal = state->getSVal(Dest, LCtx);
1014 if (stateZeroSize && !stateNonZeroSize) {
1015 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1021 if (stateNonZeroSize) {
1022 state = stateNonZeroSize;
1026 state = checkNonNull(C, state, Dest, destVal);
1031 SVal srcVal = state->getSVal(Source, LCtx);
1035 state = checkNonNull(C, state, Source, srcVal);
1040 const char *
const writeWarning =
1041 "Memory copy function overflows destination buffer";
1042 state = CheckBufferAccess(C, state, Size, Dest, Source,
1043 writeWarning,
nullptr);
1045 state = CheckOverlap(C, state, Size, Dest, Source);
1062 CharPtrTy, Dest->
getType()).castAs<loc::MemRegionVal>();
1069 state = state->BindExpr(CE, LCtx, lastElement);
1075 state = state->BindExpr(CE, LCtx, result);
1081 state = state->BindExpr(CE, LCtx, destVal);
1090 state = InvalidateBuffer(C, state, Dest, C.
getSVal(Dest),
1095 state = InvalidateBuffer(C, state, Source, C.
getSVal(Source),
1110 ProgramStateRef state = C.
getState();
1112 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1122 ProgramStateRef state = C.
getState();
1124 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1134 ProgramStateRef state = C.
getState();
1136 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1144 evalCopyCommon(C, CE, C.
getState(),
1153 CurrentFunctionDescription =
"memory comparison function";
1159 ProgramStateRef state = C.
getState();
1164 SVal sizeVal = state->getSVal(Size, LCtx);
1167 ProgramStateRef stateZeroSize, stateNonZeroSize;
1168 std::tie(stateZeroSize, stateNonZeroSize) =
1169 assumeZero(C, state, sizeVal, sizeTy);
1173 if (stateZeroSize) {
1174 state = stateZeroSize;
1175 state = state->BindExpr(CE, LCtx,
1181 if (stateNonZeroSize) {
1182 state = stateNonZeroSize;
1193 ProgramStateRef StSameBuf, StNotSameBuf;
1194 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1200 state = CheckBufferAccess(C, state, Size, Left);
1202 state = StSameBuf->BindExpr(CE, LCtx,
1211 state = StNotSameBuf;
1212 state = CheckBufferAccess(C, state, Size, Left, Right);
1217 state = state->BindExpr(CE, LCtx, CmpV);
1230 evalstrLengthCommon(C, CE,
false);
1239 evalstrLengthCommon(C, CE,
true);
1243 bool IsStrnlen)
const {
1244 CurrentFunctionDescription =
"string length function";
1245 ProgramStateRef state = C.
getState();
1250 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1252 ProgramStateRef stateZeroSize, stateNonZeroSize;
1253 std::tie(stateZeroSize, stateNonZeroSize) =
1254 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1258 if (stateZeroSize) {
1260 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1265 if (!stateNonZeroSize)
1269 state = stateNonZeroSize;
1274 SVal ArgVal = state->getSVal(Arg, LCtx);
1276 state = checkNonNull(C, state, Arg, ArgVal);
1281 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1298 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1303 if (strLengthNL && maxlenValNL) {
1304 ProgramStateRef stateStringTooLong, stateStringNotTooLong;
1307 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1309 .
evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1312 if (stateStringTooLong && !stateStringNotTooLong) {
1314 result = *maxlenValNL;
1315 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1317 result = *strLengthNL;
1332 state, BO_LE, resultNL, *strLengthNL, cmpTy)
1338 state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1356 assert(!result.
isUnknown() &&
"Should have conjured a value by now");
1357 state = state->BindExpr(CE, LCtx, result);
1366 evalStrcpyCommon(C, CE,
1377 evalStrcpyCommon(C, CE,
1388 evalStrcpyCommon(C, CE,
1399 evalStrcpyCommon(C, CE,
1410 evalStrcpyCommon(C, CE,
1417 bool returnEnd,
bool isBounded,
1418 bool isAppending)
const {
1419 CurrentFunctionDescription =
"string copy function";
1420 ProgramStateRef state = C.
getState();
1425 SVal DstVal = state->getSVal(Dst, LCtx);
1427 state = checkNonNull(C, state, Dst, DstVal);
1433 SVal srcVal = state->getSVal(srcExpr, LCtx);
1434 state = checkNonNull(C, state, srcExpr, srcVal);
1439 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1454 const char *boundWarning =
nullptr;
1460 SVal lenVal = state->getSVal(lenExpr, LCtx);
1470 if (strLengthNL && lenValNL) {
1471 ProgramStateRef stateSourceTooLong, stateSourceNotTooLong;
1476 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1477 svalBuilder.
evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1480 if (stateSourceTooLong && !stateSourceNotTooLong) {
1483 state = stateSourceTooLong;
1484 amountCopied = lenVal;
1486 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1488 state = stateSourceNotTooLong;
1489 amountCopied = strLength;
1501 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1506 maxLastElementIndex = svalBuilder.
evalBinOpNN(state, BO_Add,
1510 boundWarning =
"Size argument is greater than the free space in the "
1511 "destination buffer";
1522 ProgramStateRef StateZeroSize, StateNonZeroSize;
1523 std::tie(StateZeroSize, StateNonZeroSize) =
1524 assumeZero(C, state, *lenValNL, sizeTy);
1527 if (StateZeroSize && !StateNonZeroSize) {
1528 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1537 maxLastElementIndex = svalBuilder.
evalBinOpNN(state, BO_Sub, *lenValNL,
1539 boundWarning =
"Size argument is greater than the length of the "
1540 "destination buffer";
1548 if (amountCopied.
isUnknown() && !isAppending) {
1551 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1552 assert(!amountCopied.
isUndef());
1561 state = state->assume(
1573 state = state->assume(
1584 amountCopied = strLength;
1600 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1608 if (srcStrLengthNL && dstStrLengthNL) {
1610 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1614 finalStrLength = svalBuilder.
evalBinOpNN(state, BO_Add, *srcStrLengthNL,
1615 *dstStrLengthNL, sizeTy);
1623 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1624 assert(!finalStrLength.
isUndef());
1627 if (srcStrLengthNL) {
1639 if (dstStrLengthNL) {
1656 finalStrLength = amountCopied;
1675 SVal maxLastElement = svalBuilder.
evalBinOpLN(state, BO_Add, *dstRegVal,
1677 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1687 *knownStrLength, ptrTy);
1690 if (!boundWarning) {
1691 const char *
const warningMsg =
1692 "String copy function overflows destination buffer";
1693 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1700 Result = lastElement;
1710 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1715 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true,
1719 if (isBounded && !isAppending) {
1724 if (amountCopied != strLength)
1725 finalStrLength = UnknownVal();
1727 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1739 state = state->BindExpr(CE, LCtx, Result);
1748 evalStrcmpCommon(C, CE,
false,
false);
1756 evalStrcmpCommon(C, CE,
true,
false);
1765 evalStrcmpCommon(C, CE,
false,
true);
1774 evalStrcmpCommon(C, CE,
true,
true);
1778 bool isBounded,
bool ignoreCase)
const {
1779 CurrentFunctionDescription =
"string comparison function";
1780 ProgramStateRef state = C.
getState();
1785 SVal s1Val = state->getSVal(s1, LCtx);
1786 state = checkNonNull(C, state, s1, s1Val);
1792 SVal s2Val = state->getSVal(s2, LCtx);
1793 state = checkNonNull(C, state, s2, s2Val);
1798 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1803 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1816 ProgramStateRef StSameBuf, StNotSameBuf;
1817 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1822 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1823 svalBuilder.makeZeroVal(CE->
getType()));
1831 assert(StNotSameBuf);
1832 state = StNotSameBuf;
1838 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1839 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1840 bool canComputeResult =
false;
1841 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1844 if (s1StrLiteral && s2StrLiteral) {
1845 StringRef s1StrRef = s1StrLiteral->
getString();
1846 StringRef s2StrRef = s2StrLiteral->
getString();
1851 SVal lenVal = state->getSVal(lenExpr, LCtx);
1854 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1856 s1StrRef = s1StrRef.substr(0, (
size_t)len->getZExtValue());
1857 s2StrRef = s2StrRef.substr(0, (
size_t)len->getZExtValue());
1858 canComputeResult =
true;
1862 canComputeResult =
true;
1865 if (canComputeResult) {
1867 size_t s1Term = s1StrRef.find(
'\0');
1868 if (s1Term != StringRef::npos)
1869 s1StrRef = s1StrRef.substr(0, s1Term);
1871 size_t s2Term = s2StrRef.find(
'\0');
1872 if (s2Term != StringRef::npos)
1873 s2StrRef = s2StrRef.substr(0, s2Term);
1876 int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
1877 : s1StrRef.compare(s2StrRef);
1881 if (compareRes == 0) {
1882 resultVal = svalBuilder.makeIntVal(compareRes, CE->
getType());
1889 SVal compareWithZero =
1890 svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
1891 svalBuilder.getConditionType());
1893 state = state->assume(compareWithZeroVal,
true);
1898 state = state->BindExpr(CE, LCtx, resultVal);
1912 if (CharPtrTy.
isNull() ||
1916 CurrentFunctionDescription =
"strsep()";
1922 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
1923 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
1929 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
1930 State = checkNonNull(C, State, DelimStr, DelimStrVal);
1938 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
1942 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
1947 State = State->bindLoc(*SearchStrLoc,
1961 State = State->BindExpr(CE, LCtx, Result);
1967 evalStdCopyCommon(C, CE);
1972 evalStdCopyCommon(C, CE);
1980 ProgramStateRef State = C.
getState();
1991 SVal DstVal = State->getSVal(Dst, LCtx);
1992 State = InvalidateBuffer(C, State, Dst, DstVal,
false,
1998 State = State->BindExpr(CE, LCtx, ResultVal);
2007 CurrentFunctionDescription =
"memory set function";
2011 ProgramStateRef State = C.
getState();
2015 SVal SizeVal = State->getSVal(Size, LCtx);
2018 ProgramStateRef StateZeroSize, StateNonZeroSize;
2019 std::tie(StateZeroSize, StateNonZeroSize) =
2020 assumeZero(C, State, SizeVal, SizeTy);
2023 SVal MemVal = State->getSVal(Mem, LCtx);
2027 if (StateZeroSize && !StateNonZeroSize) {
2028 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, MemVal);
2035 State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
2039 State = CheckBufferAccess(C, State, Size, Mem);
2042 State = InvalidateBuffer(C, State, Mem, C.
getSVal(Mem),
2047 State = State->BindExpr(CE, LCtx, MemVal);
2059 if (II->
getName().equals(Name))
2075 FnCheck evalFunction =
nullptr;
2077 evalFunction = &CStringChecker::evalMemcpy;
2079 evalFunction = &CStringChecker::evalMempcpy;
2081 evalFunction = &CStringChecker::evalMemcmp;
2083 evalFunction = &CStringChecker::evalMemmove;
2085 evalFunction = &CStringChecker::evalMemset;
2087 evalFunction = &CStringChecker::evalStrcpy;
2089 evalFunction = &CStringChecker::evalStrncpy;
2091 evalFunction = &CStringChecker::evalStpcpy;
2093 evalFunction = &CStringChecker::evalStrcat;
2095 evalFunction = &CStringChecker::evalStrncat;
2097 evalFunction = &CStringChecker::evalstrLength;
2099 evalFunction = &CStringChecker::evalstrnLength;
2101 evalFunction = &CStringChecker::evalStrcmp;
2103 evalFunction = &CStringChecker::evalStrncmp;
2105 evalFunction = &CStringChecker::evalStrcasecmp;
2107 evalFunction = &CStringChecker::evalStrncasecmp;
2109 evalFunction = &CStringChecker::evalStrsep;
2111 evalFunction = &CStringChecker::evalBcopy;
2113 evalFunction = &CStringChecker::evalMemcmp;
2115 evalFunction = &CStringChecker::evalStdCopy;
2117 evalFunction = &CStringChecker::evalStdCopyBackward;
2124 (this->*evalFunction)(C, CE);
2137 ProgramStateRef state = C.
getState();
2139 for (
const auto *
I : DS->
decls()) {
2151 if (!isa<StringLiteral>(Init))
2160 assert(StrVal.
isValid() &&
"Initializer string is unknown or undefined");
2164 state = state->set<CStringLength>(MR, strLength);
2171 CStringChecker::checkRegionChanges(ProgramStateRef state,
2177 CStringLengthTy Entries = state->get<CStringLength>();
2178 if (Entries.isEmpty())
2181 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
2182 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
2186 I = Regions.begin(), E = Regions.end();
I !=
E; ++
I) {
2188 Invalidated.insert(MR);
2190 SuperRegions.insert(MR);
2191 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2192 MR = SR->getSuperRegion();
2193 SuperRegions.insert(MR);
2197 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2200 for (CStringLengthTy::iterator
I = Entries.begin(),
2201 E = Entries.end();
I !=
E; ++
I) {
2205 if (SuperRegions.count(MR)) {
2206 Entries = F.remove(Entries, MR);
2212 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2213 Super = SR->getSuperRegion();
2214 if (Invalidated.count(Super)) {
2215 Entries = F.remove(Entries, MR);
2221 return state->set<CStringLength>(Entries);
2224 void CStringChecker::checkLiveSymbols(ProgramStateRef state,
2227 CStringLengthTy Entries = state->get<CStringLength>();
2229 for (CStringLengthTy::iterator
I = Entries.begin(), E = Entries.end();
2231 SVal Len =
I.getData();
2239 void CStringChecker::checkDeadSymbols(
SymbolReaper &SR,
2244 ProgramStateRef state = C.
getState();
2245 CStringLengthTy Entries = state->get<CStringLength>();
2246 if (Entries.isEmpty())
2249 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2250 for (CStringLengthTy::iterator
I = Entries.begin(), E = Entries.end();
2252 SVal Len =
I.getData();
2255 Entries = F.remove(Entries,
I.getKey());
2259 state = state->set<CStringLength>(Entries);
2263 #define REGISTER_CHECKER(name) \
2264 void ento::register##name(CheckerManager &mgr) { \
2265 CStringChecker *checker = mgr.registerChecker<CStringChecker>(); \
2266 checker->Filter.Check##name = true; \
2267 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
2276 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.
Stmt - This represents one statement.
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...
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.
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'.
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
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)
DefinedSVal getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, const LocationContext *LCtx, unsigned count)
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.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
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.