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; }
77 void evalMemcpy(CheckerContext &C,
const CallExpr *CE)
const;
78 void evalMempcpy(CheckerContext &C,
const CallExpr *CE)
const;
79 void evalMemmove(CheckerContext &C,
const CallExpr *CE)
const;
80 void evalBcopy(CheckerContext &C,
const CallExpr *CE)
const;
81 void evalCopyCommon(CheckerContext &C,
const CallExpr *CE,
86 bool Restricted =
false,
87 bool IsMempcpy =
false)
const;
89 void evalMemcmp(CheckerContext &C,
const CallExpr *CE)
const;
91 void evalstrLength(CheckerContext &C,
const CallExpr *CE)
const;
92 void evalstrnLength(CheckerContext &C,
const CallExpr *CE)
const;
93 void evalstrLengthCommon(CheckerContext &C,
95 bool IsStrnlen =
false)
const;
97 void evalStrcpy(CheckerContext &C,
const CallExpr *CE)
const;
98 void evalStrncpy(CheckerContext &C,
const CallExpr *CE)
const;
99 void evalStpcpy(CheckerContext &C,
const CallExpr *CE)
const;
100 void evalStrcpyCommon(CheckerContext &C,
104 bool isAppending)
const;
106 void evalStrcat(CheckerContext &C,
const CallExpr *CE)
const;
107 void evalStrncat(CheckerContext &C,
const CallExpr *CE)
const;
109 void evalStrcmp(CheckerContext &C,
const CallExpr *CE)
const;
110 void evalStrncmp(CheckerContext &C,
const CallExpr *CE)
const;
111 void evalStrcasecmp(CheckerContext &C,
const CallExpr *CE)
const;
112 void evalStrncasecmp(CheckerContext &C,
const CallExpr *CE)
const;
113 void evalStrcmpCommon(CheckerContext &C,
115 bool isBounded =
false,
116 bool ignoreCase =
false)
const;
118 void evalStrsep(CheckerContext &C,
const CallExpr *CE)
const;
120 void evalStdCopy(CheckerContext &C,
const CallExpr *CE)
const;
121 void evalStdCopyBackward(CheckerContext &C,
const CallExpr *CE)
const;
122 void evalStdCopyCommon(CheckerContext &C,
const CallExpr *CE)
const;
123 void evalMemset(CheckerContext &C,
const CallExpr *CE)
const;
126 std::pair<ProgramStateRef , ProgramStateRef >
127 static assumeZero(CheckerContext &C,
133 static SVal getCStringLengthForRegion(CheckerContext &C,
138 SVal getCStringLength(CheckerContext &C,
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;
192 void emitOverlapBug(CheckerContext &C,
195 const Stmt *Second)
const;
205 static bool IsFirstBufInBound(CheckerContext &C,
207 const Expr *FirstBuf,
219 std::pair<ProgramStateRef , ProgramStateRef >
224 return std::pair<ProgramStateRef , ProgramStateRef >(
state,
state);
228 return state->assume(svalBuilder.evalEQ(state, *val, zero));
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);
278 const char *warningMsg)
const {
299 svalBuilder.convertToArrayIndex(superReg->
getExtent(svalBuilder));
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);
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);
430 const Expr *Second)
const {
431 if (!Filter.CheckCStringBufferOverlap)
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);
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);
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);
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));
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);
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);
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);
880 "IsFirstBufInBound should only be called with char* ElementRegions");
891 ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize,
true);
893 return static_cast<bool>(StInBound);
921 bool CausesPointerEscape =
false;
925 if (IsSourceBuffer) {
929 CausesPointerEscape =
true;
932 if (K == MemRegion::FieldRegionKind)
933 if (Size && IsFirstBufInBound(C, state, E, Size)) {
942 return state->invalidateRegions(R, E, C.
blockCount(), LCtx,
943 CausesPointerEscape,
nullptr,
nullptr,
950 return state->killBinding(*L);
953 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
958 case MemRegion::FunctionCodeRegionKind: {
959 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
961 os <<
"the address of the function '" << *FD <<
'\'';
963 os <<
"the address of a function";
966 case MemRegion::BlockCodeRegionKind:
969 case MemRegion::BlockDataRegionKind:
972 case MemRegion::CXXThisRegionKind:
973 case MemRegion::CXXTempObjectRegionKind:
976 case MemRegion::VarRegionKind:
979 case MemRegion::FieldRegionKind:
982 case MemRegion::ObjCIvarRegionKind:
998 const Expr *Source,
bool Restricted,
999 bool IsMempcpy)
const {
1000 CurrentFunctionDescription =
"memory copy function";
1004 SVal sizeVal = state->getSVal(Size, LCtx);
1008 std::tie(stateZeroSize, stateNonZeroSize) =
1009 assumeZero(C, state, sizeVal, sizeTy);
1012 SVal destVal = state->getSVal(Dest, LCtx);
1016 if (stateZeroSize && !stateNonZeroSize) {
1017 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1023 if (stateNonZeroSize) {
1024 state = stateNonZeroSize;
1028 state = checkNonNull(C, state, Dest, destVal);
1033 SVal srcVal = state->getSVal(Source, LCtx);
1037 state = checkNonNull(C, state, Source, srcVal);
1042 const char *
const writeWarning =
1043 "Memory copy function overflows destination buffer";
1044 state = CheckBufferAccess(C, state, Size, Dest, Source,
1045 writeWarning,
nullptr);
1047 state = CheckOverlap(C, state, Size, Dest, Source);
1059 SVal DestRegCharVal =
1062 state, BO_Add, DestRegCharVal, sizeVal, Dest->
getType());
1070 state = state->BindExpr(CE, LCtx, lastElement);
1074 state = state->BindExpr(CE, LCtx, destVal);
1083 state = InvalidateBuffer(C, state, Dest, C.
getSVal(Dest),
1088 state = InvalidateBuffer(C, state, Source, C.
getSVal(Source),
1105 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1117 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1129 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1137 evalCopyCommon(C, CE, C.
getState(),
1146 CurrentFunctionDescription =
"memory comparison function";
1157 SVal sizeVal = state->getSVal(Size, LCtx);
1161 std::tie(stateZeroSize, stateNonZeroSize) =
1162 assumeZero(C, state, sizeVal, sizeTy);
1166 if (stateZeroSize) {
1167 state = stateZeroSize;
1168 state = state->BindExpr(CE, LCtx,
1174 if (stateNonZeroSize) {
1175 state = stateNonZeroSize;
1187 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1193 state = CheckBufferAccess(C, state, Size, Left);
1195 state = StSameBuf->BindExpr(CE, LCtx,
1204 state = StNotSameBuf;
1205 state = CheckBufferAccess(C, state, Size, Left, Right);
1210 state = state->BindExpr(CE, LCtx, CmpV);
1223 evalstrLengthCommon(C, CE,
false);
1232 evalstrLengthCommon(C, CE,
true);
1236 bool IsStrnlen)
const {
1237 CurrentFunctionDescription =
"string length function";
1243 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1246 std::tie(stateZeroSize, stateNonZeroSize) =
1247 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1251 if (stateZeroSize) {
1253 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1258 if (!stateNonZeroSize)
1262 state = stateNonZeroSize;
1267 SVal ArgVal = state->getSVal(Arg, LCtx);
1269 state = checkNonNull(C, state, Arg, ArgVal);
1274 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1291 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1296 if (strLengthNL && maxlenValNL) {
1300 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1302 .
evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1305 if (stateStringTooLong && !stateStringNotTooLong) {
1307 result = *maxlenValNL;
1308 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1310 result = *strLengthNL;
1325 state, BO_LE, resultNL, *strLengthNL, cmpTy)
1331 state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1349 assert(!result.
isUnknown() &&
"Should have conjured a value by now");
1350 state = state->BindExpr(CE, LCtx, result);
1359 evalStrcpyCommon(C, CE,
1370 evalStrcpyCommon(C, CE,
1381 evalStrcpyCommon(C, CE,
1392 evalStrcpyCommon(C, CE,
1403 evalStrcpyCommon(C, CE,
1410 bool returnEnd,
bool isBounded,
1411 bool isAppending)
const {
1412 CurrentFunctionDescription =
"string copy function";
1418 SVal DstVal = state->getSVal(Dst, LCtx);
1420 state = checkNonNull(C, state, Dst, DstVal);
1426 SVal srcVal = state->getSVal(srcExpr, LCtx);
1427 state = checkNonNull(C, state, srcExpr, srcVal);
1432 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1447 const char *boundWarning =
nullptr;
1453 SVal lenVal = state->getSVal(lenExpr, LCtx);
1463 if (strLengthNL && lenValNL) {
1469 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1470 svalBuilder.
evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1473 if (stateSourceTooLong && !stateSourceNotTooLong) {
1476 state = stateSourceTooLong;
1477 amountCopied = lenVal;
1479 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1481 state = stateSourceNotTooLong;
1482 amountCopied = strLength;
1494 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1499 maxLastElementIndex = svalBuilder.
evalBinOpNN(state, BO_Add,
1503 boundWarning =
"Size argument is greater than the free space in the " 1504 "destination buffer";
1516 std::tie(StateZeroSize, StateNonZeroSize) =
1517 assumeZero(C, state, *lenValNL, sizeTy);
1520 if (StateZeroSize && !StateNonZeroSize) {
1521 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1530 maxLastElementIndex = svalBuilder.
evalBinOpNN(state, BO_Sub, *lenValNL,
1532 boundWarning =
"Size argument is greater than the length of the " 1533 "destination buffer";
1541 if (amountCopied.
isUnknown() && !isAppending) {
1544 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1545 assert(!amountCopied.
isUndef());
1554 state = state->assume(
1566 state = state->assume(
1577 amountCopied = strLength;
1593 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1601 if (srcStrLengthNL && dstStrLengthNL) {
1603 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1607 finalStrLength = svalBuilder.
evalBinOpNN(state, BO_Add, *srcStrLengthNL,
1608 *dstStrLengthNL, sizeTy);
1616 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1617 assert(!finalStrLength.
isUndef());
1620 if (srcStrLengthNL) {
1632 if (dstStrLengthNL) {
1649 finalStrLength = amountCopied;
1668 SVal maxLastElement = svalBuilder.
evalBinOpLN(state, BO_Add, *dstRegVal,
1670 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1680 *knownStrLength, ptrTy);
1683 if (!boundWarning) {
1684 const char *
const warningMsg =
1685 "String copy function overflows destination buffer";
1686 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1693 Result = lastElement;
1703 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1708 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true,
1712 if (isBounded && !isAppending) {
1717 if (amountCopied != strLength)
1718 finalStrLength = UnknownVal();
1720 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1732 state = state->BindExpr(CE, LCtx, Result);
1741 evalStrcmpCommon(C, CE,
false,
false);
1749 evalStrcmpCommon(C, CE,
true,
false);
1758 evalStrcmpCommon(C, CE,
false,
true);
1767 evalStrcmpCommon(C, CE,
true,
true);
1771 bool isBounded,
bool ignoreCase)
const {
1772 CurrentFunctionDescription =
"string comparison function";
1778 SVal s1Val = state->getSVal(s1, LCtx);
1779 state = checkNonNull(C, state, s1, s1Val);
1785 SVal s2Val = state->getSVal(s2, LCtx);
1786 state = checkNonNull(C, state, s2, s2Val);
1791 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1796 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1810 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1815 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1816 svalBuilder.makeZeroVal(CE->
getType()));
1824 assert(StNotSameBuf);
1825 state = StNotSameBuf;
1831 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1832 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1833 bool canComputeResult =
false;
1834 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
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);
1869 int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
1870 : s1StrRef.compare(s2StrRef);
1874 if (compareRes == 0) {
1875 resultVal = svalBuilder.makeIntVal(compareRes, CE->
getType());
1882 SVal compareWithZero =
1883 svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
1884 svalBuilder.getConditionType());
1886 state = state->assume(compareWithZeroVal,
true);
1891 state = state->BindExpr(CE, LCtx, resultVal);
1905 if (CharPtrTy.
isNull() ||
1909 CurrentFunctionDescription =
"strsep()";
1915 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
1916 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
1922 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
1923 State = checkNonNull(C, State, DelimStr, DelimStrVal);
1931 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
1935 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
1940 State = State->bindLoc(*SearchStrLoc,
1954 State = State->BindExpr(CE, LCtx, Result);
1960 evalStdCopyCommon(C, CE);
1965 evalStdCopyCommon(C, CE);
1984 SVal DstVal = State->getSVal(Dst, LCtx);
1985 State = InvalidateBuffer(C, State, Dst, DstVal,
false,
1991 State = State->BindExpr(CE, LCtx, ResultVal);
2000 CurrentFunctionDescription =
"memory set function";
2008 SVal SizeVal = State->getSVal(Size, LCtx);
2012 std::tie(StateZeroSize, StateNonZeroSize) =
2013 assumeZero(C, State, SizeVal, SizeTy);
2016 SVal MemVal = State->getSVal(Mem, LCtx);
2020 if (StateZeroSize && !StateNonZeroSize) {
2021 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, MemVal);
2028 State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
2032 State = CheckBufferAccess(C, State, Size, Mem);
2035 State = InvalidateBuffer(C, State, Mem, C.
getSVal(Mem),
2040 State = State->BindExpr(CE, LCtx, MemVal);
2052 if (II->
getName().equals(Name))
2068 FnCheck evalFunction =
nullptr;
2070 evalFunction = &CStringChecker::evalMemcpy;
2072 evalFunction = &CStringChecker::evalMempcpy;
2074 evalFunction = &CStringChecker::evalMemcmp;
2076 evalFunction = &CStringChecker::evalMemmove;
2078 evalFunction = &CStringChecker::evalMemset;
2080 evalFunction = &CStringChecker::evalStrcpy;
2082 evalFunction = &CStringChecker::evalStrncpy;
2084 evalFunction = &CStringChecker::evalStpcpy;
2086 evalFunction = &CStringChecker::evalStrcat;
2088 evalFunction = &CStringChecker::evalStrncat;
2090 evalFunction = &CStringChecker::evalstrLength;
2092 evalFunction = &CStringChecker::evalstrnLength;
2094 evalFunction = &CStringChecker::evalStrcmp;
2096 evalFunction = &CStringChecker::evalStrncmp;
2098 evalFunction = &CStringChecker::evalStrcasecmp;
2100 evalFunction = &CStringChecker::evalStrncasecmp;
2102 evalFunction = &CStringChecker::evalStrsep;
2104 evalFunction = &CStringChecker::evalBcopy;
2106 evalFunction = &CStringChecker::evalMemcmp;
2108 evalFunction = &CStringChecker::evalStdCopy;
2110 evalFunction = &CStringChecker::evalStdCopyBackward;
2117 (this->*evalFunction)(C, CE);
2132 for (
const auto *I : DS->
decls()) {
2144 if (!isa<StringLiteral>(Init))
2153 assert(StrVal.
isValid() &&
"Initializer string is unknown or undefined");
2157 state = state->set<CStringLength>(MR, strLength);
2170 CStringLengthTy Entries = state->get<CStringLength>();
2171 if (Entries.isEmpty())
2174 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
2175 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
2179 I = Regions.begin(), E = Regions.end(); I != E; ++I) {
2181 Invalidated.insert(MR);
2183 SuperRegions.insert(MR);
2184 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2185 MR = SR->getSuperRegion();
2186 SuperRegions.insert(MR);
2190 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2193 for (CStringLengthTy::iterator I = Entries.begin(),
2194 E = Entries.end(); I != E; ++I) {
2198 if (SuperRegions.count(MR)) {
2199 Entries = F.remove(Entries, MR);
2205 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2206 Super = SR->getSuperRegion();
2207 if (Invalidated.count(Super)) {
2208 Entries = F.remove(Entries, MR);
2214 return state->set<CStringLength>(Entries);
2220 CStringLengthTy Entries = state->get<CStringLength>();
2222 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2224 SVal Len = I.getData();
2232 void CStringChecker::checkDeadSymbols(
SymbolReaper &SR,
2238 CStringLengthTy Entries = state->get<CStringLength>();
2239 if (Entries.isEmpty())
2242 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2243 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2245 SVal Len = I.getData();
2248 Entries = F.remove(Entries, I.getKey());
2252 state = state->set<CStringLength>(Entries);
2256 #define REGISTER_CHECKER(name) \ 2257 void ento::register##name(CheckerManager &mgr) { \ 2258 CStringChecker *checker = mgr.registerChecker<CStringChecker>(); \ 2259 checker->Filter.Check##name = true; \ 2260 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \ 2269 registerCStringNullArg(Mgr);
Suppress pointer-escaping of a region.
An instance of this class is created to represent a function declaration or definition.
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.
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Information about invalidation for a particular region/symbol.
A helper class which wraps a boolean value set to false by default.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
virtual QualType getValueType() const =0
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...
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
void setTrait(SymbolRef Sym, InvalidationKinds IK)
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
const char *const UnixAPI
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
const MemRegion * getSuperRegion() 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 ...
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
virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const
getExtent - Returns the size of the region in bytes.
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 LocationContext * getLocationContext() const
static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name)
A record of the "type" of an APSInt, used for conversions.
const StringLiteral * getStringLiteral() const
SymExpr::symbol_iterator symbol_end() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
StringRef getString() 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.
bool hasDeadSymbols() const
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
Expr - This represents one expression.
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.
QualType getConditionType() const
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.
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
const MemRegion * StripCasts(bool StripBaseCasts=true) const
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
const MemRegion * getAsRegion() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
ASTContext & getContext()
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.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
StringRef getName() const
Return the actual identifier string.
llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
const Expr * getInit() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
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)
unsigned getByteLength() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
BasicValueFactory & getBasicValueFactory()
SubRegion - A region that subsets another larger region.
const ProgramStateRef & getState() const
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
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const MemRegion * getBaseRegion() const
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.
LLVM_READONLY char toUppercase(char c)
Converts the given ASCII character to its uppercase equivalent.
ElementRegin is used to represent both array elements and casts.
SymExpr::symbol_iterator symbol_begin() const
NamedDecl - This represents a decl with a name.
const LocationContext * getLocationContext() const
bool isDifferent()
Check if the checker changed the state of the execution; ex: added a new transition or a bug report...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
Iterator over symbols that the current symbol depends on.