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 {
46 DefaultBool CheckCStringNullArg;
47 DefaultBool CheckCStringOutOfBounds;
48 DefaultBool CheckCStringBufferOverlap;
49 DefaultBool CheckCStringNotNullTerm;
51 CheckName CheckNameCStringNullArg;
52 CheckName CheckNameCStringOutOfBounds;
53 CheckName CheckNameCStringBufferOverlap;
54 CheckName CheckNameCStringNotNullTerm;
57 CStringChecksFilter
Filter;
59 static void *getTag() {
static int tag;
return &tag; }
61 bool evalCall(
const CallExpr *CE, CheckerContext &C)
const;
62 void checkPreStmt(
const DeclStmt *DS, CheckerContext &C)
const;
64 void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C)
const;
74 typedef void (CStringChecker::*FnCheck)(CheckerContext &,
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 evalStrlcpy(CheckerContext &C,
const CallExpr *CE)
const;
101 void evalStrcpyCommon(CheckerContext &C,
106 bool returnPtr =
true)
const;
108 void evalStrcat(CheckerContext &C,
const CallExpr *CE)
const;
109 void evalStrncat(CheckerContext &C,
const CallExpr *CE)
const;
110 void evalStrlcat(CheckerContext &C,
const CallExpr *CE)
const;
112 void evalStrcmp(CheckerContext &C,
const CallExpr *CE)
const;
113 void evalStrncmp(CheckerContext &C,
const CallExpr *CE)
const;
114 void evalStrcasecmp(CheckerContext &C,
const CallExpr *CE)
const;
115 void evalStrncasecmp(CheckerContext &C,
const CallExpr *CE)
const;
116 void evalStrcmpCommon(CheckerContext &C,
118 bool isBounded =
false,
119 bool ignoreCase =
false)
const;
121 void evalStrsep(CheckerContext &C,
const CallExpr *CE)
const;
123 void evalStdCopy(CheckerContext &C,
const CallExpr *CE)
const;
124 void evalStdCopyBackward(CheckerContext &C,
const CallExpr *CE)
const;
125 void evalStdCopyCommon(CheckerContext &C,
const CallExpr *CE)
const;
126 void evalMemset(CheckerContext &C,
const CallExpr *CE)
const;
127 void evalBzero(CheckerContext &C,
const CallExpr *CE)
const;
130 std::pair<ProgramStateRef , ProgramStateRef >
131 static assumeZero(CheckerContext &C,
137 static SVal getCStringLengthForRegion(CheckerContext &C,
142 SVal getCStringLength(CheckerContext &C,
146 bool hypothetical =
false)
const;
155 const Expr *Ex, SVal V,
159 static bool SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
160 const MemRegion *MR);
162 static bool memsetAux(
const Expr *DstBuffer, SVal CharE,
163 const Expr *Size, CheckerContext &C,
175 const char *message =
nullptr)
const;
179 const Expr *FirstBuf,
180 const Expr *SecondBuf,
181 const char *firstMessage =
nullptr,
182 const char *secondMessage =
nullptr,
183 bool WarnAboutSize =
false)
const;
189 const char *message =
nullptr,
190 bool WarnAboutSize =
false)
const {
192 return CheckBufferAccess(C, state, Size, Buf,
nullptr, message,
nullptr,
199 const Expr *Second)
const;
200 void emitOverlapBug(CheckerContext &C,
203 const Stmt *Second)
const;
206 StringRef WarningMsg)
const;
208 const Stmt *S, StringRef WarningMsg)
const;
210 const Stmt *S, StringRef WarningMsg)
const;
221 static bool IsFirstBufInBound(CheckerContext &C,
223 const Expr *FirstBuf,
235 std::pair<ProgramStateRef , ProgramStateRef >
240 return std::pair<ProgramStateRef , ProgramStateRef >(
state,
state);
242 SValBuilder &svalBuilder = C.getSValBuilder();
243 DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty);
244 return state->assume(svalBuilder.evalEQ(state, *val, zero));
249 const Expr *S, SVal l)
const {
255 std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->
getType());
257 if (stateNull && !stateNonNull) {
258 if (
Filter.CheckCStringNullArg) {
260 llvm::raw_svector_ostream os(buf);
261 assert(CurrentFunctionDescription);
262 os <<
"Null pointer argument in call to " << CurrentFunctionDescription;
264 emitNullArgBug(C, stateNull, S, os.str());
270 assert(stateNonNull);
277 const Expr *S, SVal l,
278 const char *warningMsg)
const {
284 const MemRegion *R = l.getAsRegion();
288 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
292 if (ER->getValueType() != C.getASTContext().CharTy)
296 const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
297 SValBuilder &svalBuilder = C.getSValBuilder();
299 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
300 DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>();
303 DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
307 if (StOutBound && !StInBound) {
311 if (!
Filter.CheckCStringOutOfBounds)
315 emitOutOfBoundsBug(C, StOutBound, S, warningMsg);
317 assert(CurrentFunctionDescription);
318 assert(CurrentFunctionDescription[0] !=
'\0');
321 llvm::raw_svector_ostream os(buf);
323 << &CurrentFunctionDescription[1]
324 <<
" accesses out-of-bound array element";
325 emitOutOfBoundsBug(C, StOutBound, S, os.str());
338 const Expr *FirstBuf,
339 const Expr *SecondBuf,
340 const char *firstMessage,
341 const char *secondMessage,
342 bool WarnAboutSize)
const {
347 SValBuilder &svalBuilder = C.getSValBuilder();
355 SVal BufVal = C.getSVal(FirstBuf);
356 state = checkNonNull(C, state, FirstBuf, BufVal);
361 if (!
Filter.CheckCStringOutOfBounds)
367 SVal LengthVal = C.getSVal(Size);
373 NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
374 SVal
Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy);
375 if (Offset.isUnknown())
377 NonLoc LastOffset = Offset.castAs<NonLoc>();
380 SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->
getType());
382 const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
384 SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
386 state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
395 BufVal = state->getSVal(SecondBuf, LCtx);
396 state = checkNonNull(C, state, SecondBuf, BufVal);
400 BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->
getType());
402 const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
404 SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
406 state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
418 const Expr *Second)
const {
419 if (!
Filter.CheckCStringBufferOverlap)
434 SVal firstVal = state->getSVal(First, LCtx);
435 SVal secondVal = state->getSVal(Second, LCtx);
446 SValBuilder &svalBuilder = C.getSValBuilder();
447 std::tie(stateTrue, stateFalse) =
448 state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));
450 if (stateTrue && !stateFalse) {
452 emitOverlapBug(C, stateTrue, First, Second);
461 QualType cmpTy = svalBuilder.getConditionType();
462 SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT,
463 *firstLoc, *secondLoc, cmpTy);
465 reverse.getAs<DefinedOrUnknownSVal>();
469 std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
476 std::swap(firstLoc, secondLoc);
479 std::swap(First, Second);
484 SVal LengthVal = state->getSVal(Size, LCtx);
493 SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy,
500 SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add,
501 *FirstStartLoc, *Length, CharPtrTy);
507 SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT,
508 *FirstEndLoc, *secondLoc, cmpTy);
510 Overlap.getAs<DefinedOrUnknownSVal>();
514 std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
516 if (stateTrue && !stateFalse) {
518 emitOverlapBug(C, stateTrue, First, Second);
527 void CStringChecker::emitOverlapBug(CheckerContext &C,
ProgramStateRef state,
528 const Stmt *First,
const Stmt *Second)
const {
529 ExplodedNode *N = C.generateErrorNode(state);
534 BT_Overlap.reset(
new BugType(
Filter.CheckNameCStringBufferOverlap,
538 auto report = llvm::make_unique<BugReport>(
539 *BT_Overlap,
"Arguments must not be overlapping buffers", N);
543 C.emitReport(std::move(report));
547 const Stmt *S, StringRef WarningMsg)
const {
548 if (ExplodedNode *N = C.generateErrorNode(State)) {
550 BT_Null.reset(
new BuiltinBug(
552 "Null pointer argument in call to byte string function"));
554 BuiltinBug *BT =
static_cast<BuiltinBug *
>(BT_Null.get());
555 auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
557 if (
const auto *Ex = dyn_cast<Expr>(S))
558 bugreporter::trackExpressionValue(N, Ex, *Report);
559 C.emitReport(std::move(Report));
563 void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
565 StringRef WarningMsg)
const {
566 if (ExplodedNode *N = C.generateErrorNode(State)) {
568 BT_Bounds.reset(
new BuiltinBug(
569 Filter.CheckCStringOutOfBounds ?
Filter.CheckNameCStringOutOfBounds
570 :
Filter.CheckNameCStringNullArg,
571 "Out-of-bound array access",
572 "Byte string function accesses out-of-bound array element"));
574 BuiltinBug *BT =
static_cast<BuiltinBug *
>(BT_Bounds.get());
579 auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
581 C.emitReport(std::move(Report));
585 void CStringChecker::emitNotCStringBug(CheckerContext &C,
ProgramStateRef State,
587 StringRef WarningMsg)
const {
588 if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) {
590 BT_NotCString.reset(
new BuiltinBug(
592 "Argument is not a null-terminated string."));
594 auto Report = llvm::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
597 C.emitReport(std::move(Report));
601 void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
603 if (ExplodedNode *N = C.generateErrorNode(State)) {
606 new BuiltinBug(
Filter.CheckNameCStringOutOfBounds,
"API",
607 "Sum of expressions causes overflow."));
612 const char *WarningMsg =
613 "This expression will create a string whose length is too big to " 614 "be represented as a size_t";
616 auto Report = llvm::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
617 C.emitReport(std::move(Report));
621 ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
624 NonLoc right)
const {
626 if (!
Filter.CheckCStringOutOfBounds)
633 SValBuilder &svalBuilder = C.getSValBuilder();
634 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
636 QualType sizeTy = svalBuilder.getContext().getSizeType();
637 const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
638 NonLoc maxVal = svalBuilder.makeIntVal(maxValInt);
641 if (right.getAs<nonloc::ConcreteInt>()) {
642 maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right,
647 maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left,
653 QualType cmpTy = svalBuilder.getConditionType();
655 SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
656 *maxMinusRightNL, cmpTy);
659 std::tie(stateOverflow, stateOkay) =
660 state->assume(willOverflow.castAs<DefinedOrUnknownSVal>());
662 if (stateOverflow && !stateOkay) {
664 emitAdditionOverflowBug(C, stateOverflow);
679 assert(!strLength.isUndef() &&
"Attempt to set an undefined string length");
681 MR = MR->StripCasts();
683 switch (MR->getKind()) {
684 case MemRegion::StringRegionKind:
689 case MemRegion::SymbolicRegionKind:
690 case MemRegion::AllocaRegionKind:
691 case MemRegion::VarRegionKind:
692 case MemRegion::FieldRegionKind:
693 case MemRegion::ObjCIvarRegionKind:
697 case MemRegion::ElementRegionKind:
710 if (strLength.isUnknown())
711 return state->remove<CStringLength>(MR);
713 return state->set<CStringLength>(MR, strLength);
716 SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
723 const SVal *Recorded = state->get<CStringLength>(MR);
729 SValBuilder &svalBuilder = C.getSValBuilder();
730 QualType sizeTy = svalBuilder.getContext().getSizeType();
731 SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
733 C.getLocationContext(),
739 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
740 const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
741 llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4);
742 const llvm::APSInt *maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt,
744 NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt);
745 SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn,
747 state = state->assume(evalLength.castAs<DefinedOrUnknownSVal>(),
true);
749 state = state->set<CStringLength>(MR, strLength);
755 SVal CStringChecker::getCStringLength(CheckerContext &C,
ProgramStateRef &state,
756 const Expr *Ex, SVal Buf,
757 bool hypothetical)
const {
758 const MemRegion *MR = Buf.getAsRegion();
764 if (
Filter.CheckCStringNotNullTerm) {
766 llvm::raw_svector_ostream os(buf);
767 assert(CurrentFunctionDescription);
768 os <<
"Argument to " << CurrentFunctionDescription
769 <<
" is the address of the label '" <<
Label->getLabel()->getName()
770 <<
"', which is not a null-terminated string";
772 emitNotCStringBug(C, state, Ex, os.str());
774 return UndefinedVal();
783 MR = MR->StripCasts();
785 switch (MR->getKind()) {
786 case MemRegion::StringRegionKind: {
789 SValBuilder &svalBuilder = C.getSValBuilder();
790 QualType sizeTy = svalBuilder.getContext().getSizeType();
791 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
792 return svalBuilder.makeIntVal(strLit->
getByteLength(), sizeTy);
794 case MemRegion::SymbolicRegionKind:
795 case MemRegion::AllocaRegionKind:
796 case MemRegion::VarRegionKind:
797 case MemRegion::FieldRegionKind:
798 case MemRegion::ObjCIvarRegionKind:
799 return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
800 case MemRegion::CompoundLiteralRegionKind:
803 case MemRegion::ElementRegionKind:
811 if (
Filter.CheckCStringNotNullTerm) {
813 llvm::raw_svector_ostream os(buf);
815 assert(CurrentFunctionDescription);
816 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
818 if (SummarizeRegion(os, C.getASTContext(), MR))
819 os <<
", which is not a null-terminated string";
821 os <<
"not a null-terminated string";
823 emitNotCStringBug(C, state, Ex, os.str());
825 return UndefinedVal();
829 const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
833 const MemRegion *bufRegion = val.getAsRegion();
838 bufRegion = bufRegion->StripCasts();
841 const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);
846 return strRegion->getStringLiteral();
849 bool CStringChecker::IsFirstBufInBound(CheckerContext &C,
851 const Expr *FirstBuf,
858 SValBuilder &svalBuilder = C.getSValBuilder();
864 SVal BufVal = state->getSVal(FirstBuf, LCtx);
866 SVal LengthVal = state->getSVal(Size, LCtx);
872 NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
873 SVal Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy);
874 if (Offset.isUnknown())
876 NonLoc LastOffset = Offset.castAs<NonLoc>();
879 SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->
getType());
885 svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, LastOffset, PtrTy);
888 const MemRegion *R = BufEnd.getAsRegion();
892 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
898 assert(ER->getValueType() == C.getASTContext().CharTy &&
899 "IsFirstBufInBound should only be called with char* ElementRegions");
902 const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
904 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
905 DefinedOrUnknownSVal ExtentSize = Extent.castAs<DefinedOrUnknownSVal>();
908 DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
910 ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize,
true);
912 return static_cast<bool>(StInBound);
917 const Expr *E, SVal V,
928 const MemRegion *R = MR->getRegion()->StripCasts();
932 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
933 R = ER->getSuperRegion();
938 const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
940 bool CausesPointerEscape =
false;
941 RegionAndSymbolInvalidationTraits ITraits;
944 if (IsSourceBuffer) {
945 ITraits.setTrait(R->getBaseRegion(),
948 CausesPointerEscape =
true;
951 if (K == MemRegion::FieldRegionKind)
952 if (Size && IsFirstBufInBound(C, state, E, Size)) {
961 return state->invalidateRegions(R, E, C.blockCount(), LCtx,
962 CausesPointerEscape,
nullptr,
nullptr,
969 return state->killBinding(*L);
972 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
973 const MemRegion *MR) {
974 const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
976 switch (MR->getKind()) {
977 case MemRegion::FunctionCodeRegionKind: {
978 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
980 os <<
"the address of the function '" << *FD <<
'\'';
982 os <<
"the address of a function";
985 case MemRegion::BlockCodeRegionKind:
988 case MemRegion::BlockDataRegionKind:
991 case MemRegion::CXXThisRegionKind:
992 case MemRegion::CXXTempObjectRegionKind:
993 os <<
"a C++ temp object of type " << TVR->getValueType().getAsString();
995 case MemRegion::VarRegionKind:
996 os <<
"a variable of type" << TVR->getValueType().getAsString();
998 case MemRegion::FieldRegionKind:
999 os <<
"a field of type " << TVR->getValueType().getAsString();
1001 case MemRegion::ObjCIvarRegionKind:
1002 os <<
"an instance variable of type " << TVR->getValueType().getAsString();
1009 bool CStringChecker::memsetAux(
const Expr *DstBuffer, SVal CharVal,
1010 const Expr *Size, CheckerContext &C,
1012 SVal MemVal = C.getSVal(DstBuffer);
1013 SVal SizeVal = C.getSVal(Size);
1014 const MemRegion *MR = MemVal.getAsRegion();
1022 RegionOffset Offset = MR->getAsOffset();
1023 const MemRegion *BR = Offset.getRegion();
1029 SValBuilder &svalBuilder = C.getSValBuilder();
1034 if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
1035 Offset.getOffset() == 0) {
1037 auto *SubReg = cast<SubRegion>(BR);
1038 DefinedOrUnknownSVal Extent = SubReg->getExtent(svalBuilder);
1041 std::tie(StateWholeReg, StateNotWholeReg) =
1042 State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL));
1049 std::tie(StateNullChar, StateNonNullChar) =
1052 if (StateWholeReg && !StateNotWholeReg && StateNullChar &&
1053 !StateNonNullChar) {
1060 State = State->bindDefaultZero(svalBuilder.makeLoc(BR),
1061 C.getLocationContext());
1065 State = InvalidateBuffer(C, State, DstBuffer, MemVal,
1069 if (StateNullChar && !StateNonNullChar) {
1072 State = setCStringLength(State, MR,
1074 }
else if (!StateNullChar && StateNonNullChar) {
1075 SVal NewStrLen = svalBuilder.getMetadataSymbolVal(
1076 CStringChecker::getTag(), MR, DstBuffer, Ctx.
getSizeType(),
1077 C.getLocationContext(), C.blockCount());
1081 SVal NewStrLenGESize = svalBuilder.evalBinOp(
1082 State, BO_GE, NewStrLen, SizeVal, svalBuilder.getConditionType());
1084 State = setCStringLength(
1085 State->assume(NewStrLenGESize.castAs<DefinedOrUnknownSVal>(),
true),
1091 State = InvalidateBuffer(C, State, DstBuffer, MemVal,
1101 void CStringChecker::evalCopyCommon(CheckerContext &C,
1104 const Expr *Size,
const Expr *Dest,
1105 const Expr *Source,
bool Restricted,
1106 bool IsMempcpy)
const {
1107 CurrentFunctionDescription =
"memory copy function";
1111 SVal sizeVal = state->getSVal(Size, LCtx);
1115 std::tie(stateZeroSize, stateNonZeroSize) =
1116 assumeZero(C, state, sizeVal, sizeTy);
1119 SVal destVal = state->getSVal(Dest, LCtx);
1123 if (stateZeroSize && !stateNonZeroSize) {
1124 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1125 C.addTransition(stateZeroSize);
1130 if (stateNonZeroSize) {
1131 state = stateNonZeroSize;
1135 state = checkNonNull(C, state, Dest, destVal);
1140 SVal srcVal = state->getSVal(Source, LCtx);
1144 state = checkNonNull(C, state, Source, srcVal);
1149 const char *
const writeWarning =
1150 "Memory copy function overflows destination buffer";
1151 state = CheckBufferAccess(C, state, Size, Dest, Source,
1152 writeWarning,
nullptr);
1154 state = CheckOverlap(C, state, Size, Dest, Source);
1163 SValBuilder &SvalBuilder = C.getSValBuilder();
1166 SVal DestRegCharVal =
1167 SvalBuilder.evalCast(destVal, CharPtrTy, Dest->
getType());
1168 SVal lastElement = C.getSValBuilder().evalBinOp(
1169 state, BO_Add, DestRegCharVal, sizeVal, Dest->
getType());
1172 if (lastElement.isUnknown())
1173 lastElement = C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1177 state = state->BindExpr(CE, LCtx, lastElement);
1181 state = state->BindExpr(CE, LCtx, destVal);
1190 state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest),
1195 state = InvalidateBuffer(C, state, Source, C.getSVal(Source),
1198 C.addTransition(state);
1203 void CStringChecker::evalMemcpy(CheckerContext &C,
const CallExpr *CE)
const {
1212 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1215 void CStringChecker::evalMempcpy(CheckerContext &C,
const CallExpr *CE)
const {
1224 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1227 void CStringChecker::evalMemmove(CheckerContext &C,
const CallExpr *CE)
const {
1236 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1239 void CStringChecker::evalBcopy(CheckerContext &C,
const CallExpr *CE)
const {
1244 evalCopyCommon(C, CE, C.getState(),
1248 void CStringChecker::evalMemcmp(CheckerContext &C,
const CallExpr *CE)
const {
1253 CurrentFunctionDescription =
"memory comparison function";
1260 SValBuilder &svalBuilder = C.getSValBuilder();
1264 SVal sizeVal = state->getSVal(Size, LCtx);
1268 std::tie(stateZeroSize, stateNonZeroSize) =
1269 assumeZero(C, state, sizeVal, sizeTy);
1273 if (stateZeroSize) {
1274 state = stateZeroSize;
1275 state = state->BindExpr(CE, LCtx,
1276 svalBuilder.makeZeroVal(CE->
getType()));
1277 C.addTransition(state);
1281 if (stateNonZeroSize) {
1282 state = stateNonZeroSize;
1286 DefinedOrUnknownSVal LV =
1287 state->getSVal(Left, LCtx).castAs<DefinedOrUnknownSVal>();
1288 DefinedOrUnknownSVal RV =
1289 state->getSVal(Right, LCtx).castAs<DefinedOrUnknownSVal>();
1292 DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
1294 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1300 state = CheckBufferAccess(C, state, Size, Left);
1302 state = StSameBuf->BindExpr(CE, LCtx,
1303 svalBuilder.makeZeroVal(CE->
getType()));
1304 C.addTransition(state);
1311 state = StNotSameBuf;
1312 state = CheckBufferAccess(C, state, Size, Left, Right);
1315 SVal CmpV = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1317 state = state->BindExpr(CE, LCtx, CmpV);
1318 C.addTransition(state);
1324 void CStringChecker::evalstrLength(CheckerContext &C,
1330 evalstrLengthCommon(C, CE,
false);
1333 void CStringChecker::evalstrnLength(CheckerContext &C,
1339 evalstrLengthCommon(C, CE,
true);
1342 void CStringChecker::evalstrLengthCommon(CheckerContext &C,
const CallExpr *CE,
1343 bool IsStrnlen)
const {
1344 CurrentFunctionDescription =
"string length function";
1350 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1353 std::tie(stateZeroSize, stateNonZeroSize) =
1354 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1358 if (stateZeroSize) {
1359 SVal zero = C.getSValBuilder().makeZeroVal(CE->
getType());
1360 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1361 C.addTransition(stateZeroSize);
1365 if (!stateNonZeroSize)
1369 state = stateNonZeroSize;
1374 SVal ArgVal = state->getSVal(Arg, LCtx);
1376 state = checkNonNull(C, state, Arg, ArgVal);
1381 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1385 if (strLength.isUndef())
1388 DefinedOrUnknownSVal result = UnknownVal();
1393 QualType cmpTy = C.getSValBuilder().getConditionType();
1398 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1403 if (strLengthNL && maxlenValNL) {
1407 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1409 .evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1410 .castAs<DefinedOrUnknownSVal>());
1412 if (stateStringTooLong && !stateStringNotTooLong) {
1414 result = *maxlenValNL;
1415 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1417 result = *strLengthNL;
1421 if (result.isUnknown()) {
1426 result = C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1428 NonLoc resultNL = result.castAs<NonLoc>();
1431 state = state->assume(C.getSValBuilder().evalBinOpNN(
1432 state, BO_LE, resultNL, *strLengthNL, cmpTy)
1433 .castAs<DefinedOrUnknownSVal>(),
true);
1437 state = state->assume(C.getSValBuilder().evalBinOpNN(
1438 state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1439 .castAs<DefinedOrUnknownSVal>(),
true);
1445 result = strLength.castAs<DefinedOrUnknownSVal>();
1449 if (result.isUnknown()) {
1450 result = C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1456 assert(!result.isUnknown() &&
"Should have conjured a value by now");
1457 state = state->BindExpr(CE, LCtx, result);
1458 C.addTransition(state);
1461 void CStringChecker::evalStrcpy(CheckerContext &C,
const CallExpr *CE)
const {
1466 evalStrcpyCommon(C, CE,
1472 void CStringChecker::evalStrncpy(CheckerContext &C,
const CallExpr *CE)
const {
1477 evalStrcpyCommon(C, CE,
1483 void CStringChecker::evalStpcpy(CheckerContext &C,
const CallExpr *CE)
const {
1488 evalStrcpyCommon(C, CE,
1494 void CStringChecker::evalStrlcpy(CheckerContext &C,
const CallExpr *CE)
const {
1499 evalStrcpyCommon(C, CE,
1506 void CStringChecker::evalStrcat(CheckerContext &C,
const CallExpr *CE)
const {
1511 evalStrcpyCommon(C, CE,
1517 void CStringChecker::evalStrncat(CheckerContext &C,
const CallExpr *CE)
const {
1522 evalStrcpyCommon(C, CE,
1528 void CStringChecker::evalStrlcat(CheckerContext &C,
const CallExpr *CE)
const {
1533 evalStrcpyCommon(C, CE,
1540 void CStringChecker::evalStrcpyCommon(CheckerContext &C,
const CallExpr *CE,
1541 bool returnEnd,
bool isBounded,
1542 bool isAppending,
bool returnPtr)
const {
1543 CurrentFunctionDescription =
"string copy function";
1549 SVal DstVal = state->getSVal(Dst, LCtx);
1551 state = checkNonNull(C, state, Dst, DstVal);
1557 SVal srcVal = state->getSVal(srcExpr, LCtx);
1558 state = checkNonNull(C, state, srcExpr, srcVal);
1563 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1566 if (strLength.isUndef())
1569 SValBuilder &svalBuilder = C.getSValBuilder();
1570 QualType cmpTy = svalBuilder.getConditionType();
1571 QualType sizeTy = svalBuilder.getContext().getSizeType();
1576 SVal amountCopied = UnknownVal();
1577 SVal maxLastElementIndex = UnknownVal();
1578 const char *boundWarning =
nullptr;
1580 state = CheckOverlap(C, state, isBounded ? CE->
getArg(2) : CE->
getArg(1), Dst, srcExpr);
1589 SVal lenVal = state->getSVal(lenExpr, LCtx);
1592 lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->
getType());
1599 if (strLengthNL && lenValNL) {
1605 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1606 svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1607 .castAs<DefinedOrUnknownSVal>());
1609 if (stateSourceTooLong && !stateSourceNotTooLong) {
1612 state = stateSourceTooLong;
1613 amountCopied = lenVal;
1615 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1617 state = stateSourceNotTooLong;
1618 amountCopied = strLength;
1630 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1631 if (dstStrLength.isUndef())
1635 maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add,
1639 boundWarning =
"Size argument is greater than the free space in the " 1640 "destination buffer";
1652 std::tie(StateZeroSize, StateNonZeroSize) =
1653 assumeZero(C, state, *lenValNL, sizeTy);
1656 if (StateZeroSize && !StateNonZeroSize) {
1658 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1660 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, *lenValNL);
1662 C.addTransition(StateZeroSize);
1669 NonLoc one = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
1670 maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL,
1672 boundWarning =
"Size argument is greater than the length of the " 1673 "destination buffer";
1681 if (amountCopied.isUnknown() && !isAppending) {
1684 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1685 assert(!amountCopied.isUndef());
1690 SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE,
1694 state = state->assume(
1695 copiedLessThanBound.castAs<DefinedOrUnknownSVal>(),
true);
1702 SVal copiedLessThanSrc = svalBuilder.evalBinOpNN(state, BO_LE,
1706 state = state->assume(
1707 copiedLessThanSrc.castAs<DefinedOrUnknownSVal>(),
true);
1717 amountCopied = strLength;
1725 SVal finalStrLength = UnknownVal();
1733 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1734 if (dstStrLength.isUndef())
1741 if (srcStrLengthNL && dstStrLengthNL) {
1743 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1747 finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL,
1748 *dstStrLengthNL, sizeTy);
1753 if (finalStrLength.isUnknown()) {
1756 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1757 assert(!finalStrLength.isUndef());
1760 if (srcStrLengthNL) {
1762 SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE,
1766 state = state->assume(sourceInResult.castAs<DefinedOrUnknownSVal>(),
1772 if (dstStrLengthNL) {
1774 SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE,
1779 state->assume(destInResult.castAs<DefinedOrUnknownSVal>(),
true);
1789 finalStrLength = amountCopied;
1797 Result = (returnEnd ? UnknownVal() : DstVal);
1799 Result = finalStrLength;
1807 DstVal.getAs<loc::MemRegionVal>()) {
1814 SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
1816 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1825 SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
1826 *knownStrLength, ptrTy);
1829 if (!boundWarning) {
1830 const char *
const warningMsg =
1831 "String copy function overflows destination buffer";
1832 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1838 if (returnPtr && returnEnd)
1839 Result = lastElement;
1849 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1854 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true,
1858 if (isBounded && !isAppending) {
1863 if (amountCopied != strLength)
1864 finalStrLength = UnknownVal();
1866 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1874 if (returnEnd && Result.isUnknown()) {
1875 Result = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx, C.blockCount());
1879 state = state->BindExpr(CE, LCtx, Result);
1880 C.addTransition(state);
1883 void CStringChecker::evalStrcmp(CheckerContext &C,
const CallExpr *CE)
const {
1888 evalStrcmpCommon(C, CE,
false,
false);
1891 void CStringChecker::evalStrncmp(CheckerContext &C,
const CallExpr *CE)
const {
1896 evalStrcmpCommon(C, CE,
true,
false);
1899 void CStringChecker::evalStrcasecmp(CheckerContext &C,
1905 evalStrcmpCommon(C, CE,
false,
true);
1908 void CStringChecker::evalStrncasecmp(CheckerContext &C,
1914 evalStrcmpCommon(C, CE,
true,
true);
1917 void CStringChecker::evalStrcmpCommon(CheckerContext &C,
const CallExpr *CE,
1918 bool isBounded,
bool ignoreCase)
const {
1919 CurrentFunctionDescription =
"string comparison function";
1925 SVal s1Val = state->getSVal(s1, LCtx);
1926 state = checkNonNull(C, state, s1, s1Val);
1932 SVal s2Val = state->getSVal(s2, LCtx);
1933 state = checkNonNull(C, state, s2, s2Val);
1938 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1939 if (s1Length.isUndef())
1943 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1944 if (s2Length.isUndef())
1950 DefinedOrUnknownSVal LV = s1Val.castAs<DefinedOrUnknownSVal>();
1951 DefinedOrUnknownSVal RV = s2Val.castAs<DefinedOrUnknownSVal>();
1954 SValBuilder &svalBuilder = C.getSValBuilder();
1955 DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
1957 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1962 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1963 svalBuilder.makeZeroVal(CE->
getType()));
1964 C.addTransition(StSameBuf);
1971 assert(StNotSameBuf);
1972 state = StNotSameBuf;
1978 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1979 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1980 bool canComputeResult =
false;
1981 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1984 if (s1StrLiteral && s2StrLiteral) {
1985 StringRef s1StrRef = s1StrLiteral->
getString();
1986 StringRef s2StrRef = s2StrLiteral->
getString();
1991 SVal lenVal = state->getSVal(lenExpr, LCtx);
1994 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1996 s1StrRef = s1StrRef.substr(0, (
size_t)len->getZExtValue());
1997 s2StrRef = s2StrRef.substr(0, (
size_t)len->getZExtValue());
1998 canComputeResult =
true;
2002 canComputeResult =
true;
2005 if (canComputeResult) {
2007 size_t s1Term = s1StrRef.find(
'\0');
2008 if (s1Term != StringRef::npos)
2009 s1StrRef = s1StrRef.substr(0, s1Term);
2011 size_t s2Term = s2StrRef.find(
'\0');
2012 if (s2Term != StringRef::npos)
2013 s2StrRef = s2StrRef.substr(0, s2Term);
2016 int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
2017 : s1StrRef.compare(s2StrRef);
2021 if (compareRes == 0) {
2022 resultVal = svalBuilder.makeIntVal(compareRes, CE->
getType());
2025 DefinedSVal zeroVal = svalBuilder.makeIntVal(0, CE->
getType());
2029 SVal compareWithZero =
2030 svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
2031 svalBuilder.getConditionType());
2032 DefinedSVal compareWithZeroVal = compareWithZero.castAs<DefinedSVal>();
2033 state = state->assume(compareWithZeroVal,
true);
2038 state = state->BindExpr(CE, LCtx, resultVal);
2041 C.addTransition(state);
2044 void CStringChecker::evalStrsep(CheckerContext &C,
const CallExpr *CE)
const {
2052 if (CharPtrTy.
isNull() ||
2056 CurrentFunctionDescription =
"strsep()";
2062 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
2063 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
2069 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
2070 State = checkNonNull(C, State, DelimStr, DelimStrVal);
2074 SValBuilder &SVB = C.getSValBuilder();
2076 if (
Optional<Loc> SearchStrLoc = SearchStrVal.getAs<Loc>()) {
2078 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
2082 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
2087 State = State->bindLoc(*SearchStrLoc,
2088 SVB.conjureSymbolVal(getTag(),
2095 assert(SearchStrVal.isUnknown());
2097 Result = SVB.conjureSymbolVal(
nullptr, CE, LCtx, C.blockCount());
2101 State = State->BindExpr(CE, LCtx, Result);
2102 C.addTransition(State);
2106 void CStringChecker::evalStdCopy(CheckerContext &C,
const CallExpr *CE)
const {
2107 evalStdCopyCommon(C, CE);
2110 void CStringChecker::evalStdCopyBackward(CheckerContext &C,
2112 evalStdCopyCommon(C, CE);
2115 void CStringChecker::evalStdCopyCommon(CheckerContext &C,
2131 SVal DstVal = State->getSVal(Dst, LCtx);
2132 State = InvalidateBuffer(C, State, Dst, DstVal,
false,
2135 SValBuilder &SVB = C.getSValBuilder();
2137 SVal ResultVal = SVB.conjureSymbolVal(
nullptr, CE, LCtx, C.blockCount());
2138 State = State->BindExpr(CE, LCtx, ResultVal);
2140 C.addTransition(State);
2143 void CStringChecker::evalMemset(CheckerContext &C,
const CallExpr *CE)
const {
2147 CurrentFunctionDescription =
"memory set function";
2156 SVal SizeVal = State->getSVal(Size, LCtx);
2160 std::tie(StateZeroSize, StateNonZeroSize) =
2161 assumeZero(C, State, SizeVal, SizeTy);
2164 SVal MemVal = State->getSVal(Mem, LCtx);
2168 if (StateZeroSize && !StateNonZeroSize) {
2169 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, MemVal);
2170 C.addTransition(StateZeroSize);
2176 State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
2180 State = CheckBufferAccess(C, State, Size, Mem);
2187 if (!memsetAux(Mem, C.getSVal(CharE), Size, C,
State))
2190 State = State->BindExpr(CE, LCtx, MemVal);
2191 C.addTransition(State);
2194 void CStringChecker::evalBzero(CheckerContext &C,
const CallExpr *CE)
const {
2198 CurrentFunctionDescription =
"memory clearance function";
2202 SVal Zero = C.getSValBuilder().makeZeroVal(C.getASTContext().IntTy);
2207 SVal SizeVal = C.getSVal(Size);
2211 std::tie(StateZeroSize, StateNonZeroSize) =
2212 assumeZero(C, State, SizeVal, SizeTy);
2216 if (StateZeroSize && !StateNonZeroSize) {
2217 C.addTransition(StateZeroSize);
2222 SVal MemVal = C.getSVal(Mem);
2226 State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
2230 State = CheckBufferAccess(C, State, Size, Mem);
2234 if (!memsetAux(Mem, Zero, Size, C, State))
2237 C.addTransition(State);
2248 if (II->
getName().equals(Name))
2258 CheckerContext &C) {
2269 return &CStringChecker::evalStdCopy;
2273 return &CStringChecker::evalStdCopyBackward;
2284 if (C.isCLibraryFunction(FDecl,
"memcpy"))
2285 return &CStringChecker::evalMemcpy;
2286 else if (C.isCLibraryFunction(FDecl,
"mempcpy"))
2287 return &CStringChecker::evalMempcpy;
2288 else if (C.isCLibraryFunction(FDecl,
"memcmp"))
2289 return &CStringChecker::evalMemcmp;
2290 else if (C.isCLibraryFunction(FDecl,
"memmove"))
2291 return &CStringChecker::evalMemmove;
2292 else if (C.isCLibraryFunction(FDecl,
"memset") ||
2293 C.isCLibraryFunction(FDecl,
"explicit_memset"))
2294 return &CStringChecker::evalMemset;
2295 else if (C.isCLibraryFunction(FDecl,
"strcpy"))
2296 return &CStringChecker::evalStrcpy;
2297 else if (C.isCLibraryFunction(FDecl,
"strncpy"))
2298 return &CStringChecker::evalStrncpy;
2299 else if (C.isCLibraryFunction(FDecl,
"stpcpy"))
2300 return &CStringChecker::evalStpcpy;
2301 else if (C.isCLibraryFunction(FDecl,
"strlcpy"))
2302 return &CStringChecker::evalStrlcpy;
2303 else if (C.isCLibraryFunction(FDecl,
"strcat"))
2304 return &CStringChecker::evalStrcat;
2305 else if (C.isCLibraryFunction(FDecl,
"strncat"))
2306 return &CStringChecker::evalStrncat;
2307 else if (C.isCLibraryFunction(FDecl,
"strlcat"))
2308 return &CStringChecker::evalStrlcat;
2309 else if (C.isCLibraryFunction(FDecl,
"strlen"))
2310 return &CStringChecker::evalstrLength;
2311 else if (C.isCLibraryFunction(FDecl,
"strnlen"))
2312 return &CStringChecker::evalstrnLength;
2313 else if (C.isCLibraryFunction(FDecl,
"strcmp"))
2314 return &CStringChecker::evalStrcmp;
2315 else if (C.isCLibraryFunction(FDecl,
"strncmp"))
2316 return &CStringChecker::evalStrncmp;
2317 else if (C.isCLibraryFunction(FDecl,
"strcasecmp"))
2318 return &CStringChecker::evalStrcasecmp;
2319 else if (C.isCLibraryFunction(FDecl,
"strncasecmp"))
2320 return &CStringChecker::evalStrncasecmp;
2321 else if (C.isCLibraryFunction(FDecl,
"strsep"))
2322 return &CStringChecker::evalStrsep;
2323 else if (C.isCLibraryFunction(FDecl,
"bcopy"))
2324 return &CStringChecker::evalBcopy;
2325 else if (C.isCLibraryFunction(FDecl,
"bcmp"))
2326 return &CStringChecker::evalMemcmp;
2327 else if (C.isCLibraryFunction(FDecl,
"bzero") ||
2328 C.isCLibraryFunction(FDecl,
"explicit_bzero"))
2329 return &CStringChecker::evalBzero;
2334 bool CStringChecker::evalCall(
const CallExpr *CE, CheckerContext &C)
const {
2343 (this->*evalFunction)(C, CE);
2351 return C.isDifferent();
2354 void CStringChecker::checkPreStmt(
const DeclStmt *DS, CheckerContext &C)
const {
2358 for (
const auto *I : DS->
decls()) {
2370 if (!isa<StringLiteral>(Init))
2373 Loc VarLoc = state->getLValue(D, C.getLocationContext());
2374 const MemRegion *MR = VarLoc.getAsRegion();
2378 SVal StrVal = C.getSVal(Init);
2379 assert(StrVal.isValid() &&
"Initializer string is unknown or undefined");
2380 DefinedOrUnknownSVal strLength =
2381 getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>();
2383 state = state->set<CStringLength>(MR, strLength);
2386 C.addTransition(state);
2396 CStringLengthTy Entries = state->get<CStringLength>();
2397 if (Entries.isEmpty())
2400 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
2401 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
2405 I = Regions.begin(), E = Regions.end(); I != E; ++I) {
2406 const MemRegion *MR = *I;
2407 Invalidated.insert(MR);
2409 SuperRegions.insert(MR);
2410 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2411 MR = SR->getSuperRegion();
2412 SuperRegions.insert(MR);
2416 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2419 for (CStringLengthTy::iterator I = Entries.begin(),
2420 E = Entries.end(); I != E; ++I) {
2421 const MemRegion *MR = I.getKey();
2424 if (SuperRegions.count(MR)) {
2425 Entries = F.remove(Entries, MR);
2430 const MemRegion *Super = MR;
2431 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2432 Super = SR->getSuperRegion();
2433 if (Invalidated.count(Super)) {
2434 Entries = F.remove(Entries, MR);
2440 return state->set<CStringLength>(Entries);
2444 SymbolReaper &SR)
const {
2446 CStringLengthTy Entries = state->get<CStringLength>();
2448 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2450 SVal Len = I.getData();
2452 for (SymExpr::symbol_iterator si = Len.symbol_begin(),
2453 se = Len.symbol_end(); si != se; ++si)
2458 void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
2459 CheckerContext &C)
const {
2461 CStringLengthTy Entries = state->get<CStringLength>();
2462 if (Entries.isEmpty())
2465 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2466 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2468 SVal Len = I.getData();
2469 if (
SymbolRef Sym = Len.getAsSymbol()) {
2471 Entries = F.remove(Entries, I.getKey());
2475 state = state->set<CStringLength>(Entries);
2476 C.addTransition(state);
2479 #define REGISTER_CHECKER(name) \ 2480 void ento::register##name(CheckerManager &mgr) { \ 2481 CStringChecker *checker = mgr.registerChecker<CStringChecker>(); \ 2482 checker->Filter.Check##name = true; \ 2483 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \ 2492 Mgr.registerChecker<CStringChecker>();
Suppress pointer-escaping of a region.
Represents a function declaration or definition.
A (possibly-)qualified type.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
const SymExpr * SymbolRef
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
static CStringChecker::FnCheck identifyCall(const CallExpr *CE, CheckerContext &C)
Represents a variable declaration or definition.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const char *const UnixAPI
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
One of these records is kept for each identifier that is lexed.
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
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
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.
static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name)
CanQualType UnsignedCharTy
StringRef getString() const
#define REGISTER_CHECKER(name)
This represents one expression.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Tells that a region's contents is not changed.
StringRef getName() const
Return the actual identifier string.
Dataflow Directional Tag Classes.
const Expr * getInit() const
unsigned getByteLength() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
StringLiteral - This represents a string literal expression, e.g.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
LLVM_READONLY char toUppercase(char c)
Converts the given ASCII character to its uppercase equivalent.
bool isPointerType() const
This represents a decl that may have a name.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.