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 CallEvent &Call, 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 &,
105 StdCopyBackward{{
"std",
"copy_backward"}, 3};
107 FnCheck identifyCall(
const CallEvent &Call, CheckerContext &C)
const;
108 void evalMemcpy(CheckerContext &C,
const CallExpr *CE)
const;
109 void evalMempcpy(CheckerContext &C,
const CallExpr *CE)
const;
110 void evalMemmove(CheckerContext &C,
const CallExpr *CE)
const;
111 void evalBcopy(CheckerContext &C,
const CallExpr *CE)
const;
112 void evalCopyCommon(CheckerContext &C,
const CallExpr *CE,
117 bool Restricted =
false,
118 bool IsMempcpy =
false)
const;
120 void evalMemcmp(CheckerContext &C,
const CallExpr *CE)
const;
122 void evalstrLength(CheckerContext &C,
const CallExpr *CE)
const;
123 void evalstrnLength(CheckerContext &C,
const CallExpr *CE)
const;
124 void evalstrLengthCommon(CheckerContext &C,
126 bool IsStrnlen =
false)
const;
128 void evalStrcpy(CheckerContext &C,
const CallExpr *CE)
const;
129 void evalStrncpy(CheckerContext &C,
const CallExpr *CE)
const;
130 void evalStpcpy(CheckerContext &C,
const CallExpr *CE)
const;
131 void evalStrlcpy(CheckerContext &C,
const CallExpr *CE)
const;
132 void evalStrcpyCommon(CheckerContext &C,
137 bool returnPtr =
true)
const;
139 void evalStrcat(CheckerContext &C,
const CallExpr *CE)
const;
140 void evalStrncat(CheckerContext &C,
const CallExpr *CE)
const;
141 void evalStrlcat(CheckerContext &C,
const CallExpr *CE)
const;
143 void evalStrcmp(CheckerContext &C,
const CallExpr *CE)
const;
144 void evalStrncmp(CheckerContext &C,
const CallExpr *CE)
const;
145 void evalStrcasecmp(CheckerContext &C,
const CallExpr *CE)
const;
146 void evalStrncasecmp(CheckerContext &C,
const CallExpr *CE)
const;
147 void evalStrcmpCommon(CheckerContext &C,
149 bool isBounded =
false,
150 bool ignoreCase =
false)
const;
152 void evalStrsep(CheckerContext &C,
const CallExpr *CE)
const;
154 void evalStdCopy(CheckerContext &C,
const CallExpr *CE)
const;
155 void evalStdCopyBackward(CheckerContext &C,
const CallExpr *CE)
const;
156 void evalStdCopyCommon(CheckerContext &C,
const CallExpr *CE)
const;
157 void evalMemset(CheckerContext &C,
const CallExpr *CE)
const;
158 void evalBzero(CheckerContext &C,
const CallExpr *CE)
const;
161 std::pair<ProgramStateRef , ProgramStateRef >
162 static assumeZero(CheckerContext &C,
168 static SVal getCStringLengthForRegion(CheckerContext &C,
173 SVal getCStringLength(CheckerContext &C,
177 bool hypothetical =
false)
const;
186 const Expr *Ex, SVal
V,
190 static bool SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
191 const MemRegion *MR);
193 static bool memsetAux(
const Expr *DstBuffer, SVal CharE,
194 const Expr *Size, CheckerContext &C,
206 const char *message =
nullptr)
const;
210 const Expr *FirstBuf,
211 const Expr *SecondBuf,
212 const char *firstMessage =
nullptr,
213 const char *secondMessage =
nullptr,
214 bool WarnAboutSize =
false)
const;
220 const char *message =
nullptr,
221 bool WarnAboutSize =
false)
const {
223 return CheckBufferAccess(C, state, Size, Buf,
nullptr, message,
nullptr,
230 const Expr *Second)
const;
231 void emitOverlapBug(CheckerContext &C,
234 const Stmt *Second)
const;
237 StringRef WarningMsg)
const;
239 const Stmt *S, StringRef WarningMsg)
const;
241 const Stmt *S, StringRef WarningMsg)
const;
252 static bool IsFirstBufInBound(CheckerContext &C,
254 const Expr *FirstBuf,
266 std::pair<ProgramStateRef , ProgramStateRef >
271 return std::pair<ProgramStateRef , ProgramStateRef >(
state,
state);
273 SValBuilder &svalBuilder = C.getSValBuilder();
274 DefinedOrUnknownSVal
zero = svalBuilder.makeZeroVal(Ty);
275 return state->assume(svalBuilder.evalEQ(state, *val, zero));
280 const Expr *S, SVal l)
const {
286 std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->
getType());
288 if (stateNull && !stateNonNull) {
289 if (
Filter.CheckCStringNullArg) {
291 llvm::raw_svector_ostream os(buf);
292 assert(CurrentFunctionDescription);
293 os <<
"Null pointer argument in call to " << CurrentFunctionDescription;
295 emitNullArgBug(C, stateNull, S, os.str());
301 assert(stateNonNull);
308 const Expr *S, SVal l,
309 const char *warningMsg)
const {
315 const MemRegion *R = l.getAsRegion();
319 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
323 if (ER->getValueType() != C.getASTContext().CharTy)
327 const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
328 SValBuilder &svalBuilder = C.getSValBuilder();
330 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
331 DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>();
334 DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
338 if (StOutBound && !StInBound) {
342 if (!
Filter.CheckCStringOutOfBounds)
346 emitOutOfBoundsBug(C, StOutBound, S, warningMsg);
348 assert(CurrentFunctionDescription);
349 assert(CurrentFunctionDescription[0] !=
'\0');
352 llvm::raw_svector_ostream os(buf);
354 << &CurrentFunctionDescription[1]
355 <<
" accesses out-of-bound array element";
356 emitOutOfBoundsBug(C, StOutBound, S, os.str());
369 const Expr *FirstBuf,
370 const Expr *SecondBuf,
371 const char *firstMessage,
372 const char *secondMessage,
373 bool WarnAboutSize)
const {
378 SValBuilder &svalBuilder = C.getSValBuilder();
386 SVal BufVal = C.getSVal(FirstBuf);
387 state = checkNonNull(C, state, FirstBuf, BufVal);
392 if (!
Filter.CheckCStringOutOfBounds)
398 SVal LengthVal = C.getSVal(Size);
404 NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
405 SVal
Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy);
406 if (Offset.isUnknown())
408 NonLoc LastOffset = Offset.castAs<NonLoc>();
411 SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->
getType());
413 const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
415 SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
417 state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
426 BufVal = state->getSVal(SecondBuf, LCtx);
427 state = checkNonNull(C, state, SecondBuf, BufVal);
431 BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->
getType());
433 const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
435 SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
437 state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
449 const Expr *Second)
const {
450 if (!
Filter.CheckCStringBufferOverlap)
465 SVal firstVal = state->getSVal(First, LCtx);
466 SVal secondVal = state->getSVal(Second, LCtx);
477 SValBuilder &svalBuilder = C.getSValBuilder();
478 std::tie(stateTrue, stateFalse) =
479 state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));
481 if (stateTrue && !stateFalse) {
483 emitOverlapBug(C, stateTrue, First, Second);
492 QualType cmpTy = svalBuilder.getConditionType();
493 SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT,
494 *firstLoc, *secondLoc, cmpTy);
496 reverse.getAs<DefinedOrUnknownSVal>();
500 std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
507 std::swap(firstLoc, secondLoc);
510 std::swap(First, Second);
515 SVal LengthVal = state->getSVal(Size, LCtx);
524 SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy,
531 SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add,
532 *FirstStartLoc, *Length, CharPtrTy);
538 SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT,
539 *FirstEndLoc, *secondLoc, cmpTy);
541 Overlap.getAs<DefinedOrUnknownSVal>();
545 std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
547 if (stateTrue && !stateFalse) {
549 emitOverlapBug(C, stateTrue, First, Second);
558 void CStringChecker::emitOverlapBug(CheckerContext &C,
ProgramStateRef state,
559 const Stmt *First,
const Stmt *Second)
const {
560 ExplodedNode *N = C.generateErrorNode(state);
565 BT_Overlap.reset(
new BugType(
Filter.CheckNameCStringBufferOverlap,
569 auto report = llvm::make_unique<BugReport>(
570 *BT_Overlap,
"Arguments must not be overlapping buffers", N);
574 C.emitReport(std::move(report));
578 const Stmt *S, StringRef WarningMsg)
const {
579 if (ExplodedNode *N = C.generateErrorNode(State)) {
581 BT_Null.reset(
new BuiltinBug(
583 "Null pointer argument in call to byte string function"));
585 BuiltinBug *BT =
static_cast<BuiltinBug *
>(BT_Null.get());
586 auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
588 if (
const auto *Ex = dyn_cast<Expr>(S))
589 bugreporter::trackExpressionValue(N, Ex, *Report);
590 C.emitReport(std::move(Report));
594 void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
596 StringRef WarningMsg)
const {
597 if (ExplodedNode *N = C.generateErrorNode(State)) {
599 BT_Bounds.reset(
new BuiltinBug(
600 Filter.CheckCStringOutOfBounds ?
Filter.CheckNameCStringOutOfBounds
601 :
Filter.CheckNameCStringNullArg,
602 "Out-of-bound array access",
603 "Byte string function accesses out-of-bound array element"));
605 BuiltinBug *BT =
static_cast<BuiltinBug *
>(BT_Bounds.get());
610 auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
612 C.emitReport(std::move(Report));
616 void CStringChecker::emitNotCStringBug(CheckerContext &C,
ProgramStateRef State,
618 StringRef WarningMsg)
const {
619 if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) {
621 BT_NotCString.reset(
new BuiltinBug(
623 "Argument is not a null-terminated string."));
625 auto Report = llvm::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
628 C.emitReport(std::move(Report));
632 void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
634 if (ExplodedNode *N = C.generateErrorNode(State)) {
637 new BuiltinBug(
Filter.CheckNameCStringOutOfBounds,
"API",
638 "Sum of expressions causes overflow."));
643 const char *WarningMsg =
644 "This expression will create a string whose length is too big to " 645 "be represented as a size_t";
647 auto Report = llvm::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
648 C.emitReport(std::move(Report));
652 ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
655 NonLoc right)
const {
657 if (!
Filter.CheckCStringOutOfBounds)
664 SValBuilder &svalBuilder = C.getSValBuilder();
665 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
667 QualType sizeTy = svalBuilder.getContext().getSizeType();
668 const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
669 NonLoc maxVal = svalBuilder.makeIntVal(maxValInt);
672 if (right.getAs<nonloc::ConcreteInt>()) {
673 maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right,
678 maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left,
684 QualType cmpTy = svalBuilder.getConditionType();
686 SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
687 *maxMinusRightNL, cmpTy);
690 std::tie(stateOverflow, stateOkay) =
691 state->assume(willOverflow.castAs<DefinedOrUnknownSVal>());
693 if (stateOverflow && !stateOkay) {
695 emitAdditionOverflowBug(C, stateOverflow);
710 assert(!strLength.isUndef() &&
"Attempt to set an undefined string length");
712 MR = MR->StripCasts();
714 switch (MR->getKind()) {
715 case MemRegion::StringRegionKind:
720 case MemRegion::SymbolicRegionKind:
721 case MemRegion::AllocaRegionKind:
722 case MemRegion::VarRegionKind:
723 case MemRegion::FieldRegionKind:
724 case MemRegion::ObjCIvarRegionKind:
728 case MemRegion::ElementRegionKind:
741 if (strLength.isUnknown())
742 return state->remove<CStringLength>(MR);
744 return state->set<CStringLength>(MR, strLength);
747 SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
754 const SVal *Recorded = state->get<CStringLength>(MR);
760 SValBuilder &svalBuilder = C.getSValBuilder();
761 QualType sizeTy = svalBuilder.getContext().getSizeType();
762 SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
764 C.getLocationContext(),
770 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
771 const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
772 llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4);
773 const llvm::APSInt *maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt,
775 NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt);
776 SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn,
778 state = state->assume(evalLength.castAs<DefinedOrUnknownSVal>(),
true);
780 state = state->set<CStringLength>(MR, strLength);
786 SVal CStringChecker::getCStringLength(CheckerContext &C,
ProgramStateRef &state,
787 const Expr *Ex, SVal Buf,
788 bool hypothetical)
const {
789 const MemRegion *MR = Buf.getAsRegion();
795 if (
Filter.CheckCStringNotNullTerm) {
797 llvm::raw_svector_ostream os(buf);
798 assert(CurrentFunctionDescription);
799 os <<
"Argument to " << CurrentFunctionDescription
800 <<
" is the address of the label '" <<
Label->getLabel()->getName()
801 <<
"', which is not a null-terminated string";
803 emitNotCStringBug(C, state, Ex, os.str());
805 return UndefinedVal();
814 MR = MR->StripCasts();
816 switch (MR->getKind()) {
817 case MemRegion::StringRegionKind: {
820 SValBuilder &svalBuilder = C.getSValBuilder();
821 QualType sizeTy = svalBuilder.getContext().getSizeType();
822 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
823 return svalBuilder.makeIntVal(strLit->
getByteLength(), sizeTy);
825 case MemRegion::SymbolicRegionKind:
826 case MemRegion::AllocaRegionKind:
827 case MemRegion::VarRegionKind:
828 case MemRegion::FieldRegionKind:
829 case MemRegion::ObjCIvarRegionKind:
830 return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
831 case MemRegion::CompoundLiteralRegionKind:
834 case MemRegion::ElementRegionKind:
842 if (
Filter.CheckCStringNotNullTerm) {
844 llvm::raw_svector_ostream os(buf);
846 assert(CurrentFunctionDescription);
847 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
849 if (SummarizeRegion(os, C.getASTContext(), MR))
850 os <<
", which is not a null-terminated string";
852 os <<
"not a null-terminated string";
854 emitNotCStringBug(C, state, Ex, os.str());
856 return UndefinedVal();
860 const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
864 const MemRegion *bufRegion = val.getAsRegion();
869 bufRegion = bufRegion->StripCasts();
872 const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);
877 return strRegion->getStringLiteral();
880 bool CStringChecker::IsFirstBufInBound(CheckerContext &C,
882 const Expr *FirstBuf,
889 SValBuilder &svalBuilder = C.getSValBuilder();
895 SVal BufVal = state->getSVal(FirstBuf, LCtx);
897 SVal LengthVal = state->getSVal(Size, LCtx);
903 NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
904 SVal Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy);
905 if (Offset.isUnknown())
907 NonLoc LastOffset = Offset.castAs<NonLoc>();
910 SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->
getType());
916 svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, LastOffset, PtrTy);
919 const MemRegion *R = BufEnd.getAsRegion();
923 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
929 assert(ER->getValueType() == C.getASTContext().CharTy &&
930 "IsFirstBufInBound should only be called with char* ElementRegions");
933 const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
935 svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
936 DefinedOrUnknownSVal ExtentSize = Extent.castAs<DefinedOrUnknownSVal>();
939 DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
941 ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize,
true);
943 return static_cast<bool>(StInBound);
948 const Expr *E, SVal V,
959 const MemRegion *R = MR->getRegion()->StripCasts();
963 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
964 R = ER->getSuperRegion();
969 const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
971 bool CausesPointerEscape =
false;
972 RegionAndSymbolInvalidationTraits ITraits;
975 if (IsSourceBuffer) {
976 ITraits.setTrait(R->getBaseRegion(),
979 CausesPointerEscape =
true;
982 if (K == MemRegion::FieldRegionKind)
983 if (Size && IsFirstBufInBound(C, state, E, Size)) {
992 return state->invalidateRegions(R, E, C.blockCount(), LCtx,
993 CausesPointerEscape,
nullptr,
nullptr,
1000 return state->killBinding(*L);
1003 bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
1004 const MemRegion *MR) {
1005 const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
1007 switch (MR->getKind()) {
1008 case MemRegion::FunctionCodeRegionKind: {
1009 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
1011 os <<
"the address of the function '" << *FD <<
'\'';
1013 os <<
"the address of a function";
1016 case MemRegion::BlockCodeRegionKind:
1019 case MemRegion::BlockDataRegionKind:
1022 case MemRegion::CXXThisRegionKind:
1023 case MemRegion::CXXTempObjectRegionKind:
1024 os <<
"a C++ temp object of type " << TVR->getValueType().getAsString();
1026 case MemRegion::VarRegionKind:
1027 os <<
"a variable of type" << TVR->getValueType().getAsString();
1029 case MemRegion::FieldRegionKind:
1030 os <<
"a field of type " << TVR->getValueType().getAsString();
1032 case MemRegion::ObjCIvarRegionKind:
1033 os <<
"an instance variable of type " << TVR->getValueType().getAsString();
1040 bool CStringChecker::memsetAux(
const Expr *DstBuffer, SVal CharVal,
1041 const Expr *Size, CheckerContext &C,
1043 SVal MemVal = C.getSVal(DstBuffer);
1044 SVal SizeVal = C.getSVal(Size);
1045 const MemRegion *MR = MemVal.getAsRegion();
1053 RegionOffset Offset = MR->getAsOffset();
1054 const MemRegion *BR = Offset.getRegion();
1060 SValBuilder &svalBuilder = C.getSValBuilder();
1065 if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
1066 Offset.getOffset() == 0) {
1068 auto *SubReg = cast<SubRegion>(BR);
1069 DefinedOrUnknownSVal Extent = SubReg->getExtent(svalBuilder);
1072 std::tie(StateWholeReg, StateNotWholeReg) =
1073 State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL));
1080 std::tie(StateNullChar, StateNonNullChar) =
1083 if (StateWholeReg && !StateNotWholeReg && StateNullChar &&
1084 !StateNonNullChar) {
1091 State = State->bindDefaultZero(svalBuilder.makeLoc(BR),
1092 C.getLocationContext());
1096 State = InvalidateBuffer(C, State, DstBuffer, MemVal,
1100 if (StateNullChar && !StateNonNullChar) {
1103 State = setCStringLength(State, MR,
1105 }
else if (!StateNullChar && StateNonNullChar) {
1106 SVal NewStrLen = svalBuilder.getMetadataSymbolVal(
1107 CStringChecker::getTag(), MR, DstBuffer, Ctx.
getSizeType(),
1108 C.getLocationContext(), C.blockCount());
1112 SVal NewStrLenGESize = svalBuilder.evalBinOp(
1113 State, BO_GE, NewStrLen, SizeVal, svalBuilder.getConditionType());
1115 State = setCStringLength(
1116 State->assume(NewStrLenGESize.castAs<DefinedOrUnknownSVal>(),
true),
1122 State = InvalidateBuffer(C, State, DstBuffer, MemVal,
1132 void CStringChecker::evalCopyCommon(CheckerContext &C,
1135 const Expr *Size,
const Expr *Dest,
1136 const Expr *Source,
bool Restricted,
1137 bool IsMempcpy)
const {
1138 CurrentFunctionDescription =
"memory copy function";
1142 SVal sizeVal = state->getSVal(Size, LCtx);
1146 std::tie(stateZeroSize, stateNonZeroSize) =
1147 assumeZero(C, state, sizeVal, sizeTy);
1150 SVal destVal = state->getSVal(Dest, LCtx);
1154 if (stateZeroSize && !stateNonZeroSize) {
1155 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1156 C.addTransition(stateZeroSize);
1161 if (stateNonZeroSize) {
1162 state = stateNonZeroSize;
1166 state = checkNonNull(C, state, Dest, destVal);
1171 SVal srcVal = state->getSVal(Source, LCtx);
1175 state = checkNonNull(C, state, Source, srcVal);
1180 const char *
const writeWarning =
1181 "Memory copy function overflows destination buffer";
1182 state = CheckBufferAccess(C, state, Size, Dest, Source,
1183 writeWarning,
nullptr);
1185 state = CheckOverlap(C, state, Size, Dest, Source);
1194 SValBuilder &SvalBuilder = C.getSValBuilder();
1197 SVal DestRegCharVal =
1198 SvalBuilder.evalCast(destVal, CharPtrTy, Dest->
getType());
1199 SVal lastElement = C.getSValBuilder().evalBinOp(
1200 state, BO_Add, DestRegCharVal, sizeVal, Dest->
getType());
1203 if (lastElement.isUnknown())
1204 lastElement = C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1208 state = state->BindExpr(CE, LCtx, lastElement);
1212 state = state->BindExpr(CE, LCtx, destVal);
1221 state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest),
1226 state = InvalidateBuffer(C, state, Source, C.getSVal(Source),
1229 C.addTransition(state);
1234 void CStringChecker::evalMemcpy(CheckerContext &C,
const CallExpr *CE)
const {
1240 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true);
1243 void CStringChecker::evalMempcpy(CheckerContext &C,
const CallExpr *CE)
const {
1249 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1),
true,
true);
1252 void CStringChecker::evalMemmove(CheckerContext &C,
const CallExpr *CE)
const {
1258 evalCopyCommon(C, CE, state, CE->
getArg(2), Dest, CE->
getArg(1));
1261 void CStringChecker::evalBcopy(CheckerContext &C,
const CallExpr *CE)
const {
1263 evalCopyCommon(C, CE, C.getState(),
1267 void CStringChecker::evalMemcmp(CheckerContext &C,
const CallExpr *CE)
const {
1269 CurrentFunctionDescription =
"memory comparison function";
1276 SValBuilder &svalBuilder = C.getSValBuilder();
1280 SVal sizeVal = state->getSVal(Size, LCtx);
1284 std::tie(stateZeroSize, stateNonZeroSize) =
1285 assumeZero(C, state, sizeVal, sizeTy);
1289 if (stateZeroSize) {
1290 state = stateZeroSize;
1291 state = state->BindExpr(CE, LCtx,
1292 svalBuilder.makeZeroVal(CE->
getType()));
1293 C.addTransition(state);
1297 if (stateNonZeroSize) {
1298 state = stateNonZeroSize;
1302 DefinedOrUnknownSVal LV =
1303 state->getSVal(Left, LCtx).castAs<DefinedOrUnknownSVal>();
1304 DefinedOrUnknownSVal RV =
1305 state->getSVal(Right, LCtx).castAs<DefinedOrUnknownSVal>();
1308 DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
1310 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1316 state = CheckBufferAccess(C, state, Size, Left);
1318 state = StSameBuf->BindExpr(CE, LCtx,
1319 svalBuilder.makeZeroVal(CE->
getType()));
1320 C.addTransition(state);
1327 state = StNotSameBuf;
1328 state = CheckBufferAccess(C, state, Size, Left, Right);
1331 SVal CmpV = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1333 state = state->BindExpr(CE, LCtx, CmpV);
1334 C.addTransition(state);
1340 void CStringChecker::evalstrLength(CheckerContext &C,
1343 evalstrLengthCommon(C, CE,
false);
1346 void CStringChecker::evalstrnLength(CheckerContext &C,
1349 evalstrLengthCommon(C, CE,
true);
1352 void CStringChecker::evalstrLengthCommon(CheckerContext &C,
const CallExpr *CE,
1353 bool IsStrnlen)
const {
1354 CurrentFunctionDescription =
"string length function";
1360 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1363 std::tie(stateZeroSize, stateNonZeroSize) =
1364 assumeZero(C, state, maxlenVal, maxlenExpr->
getType());
1368 if (stateZeroSize) {
1369 SVal zero = C.getSValBuilder().makeZeroVal(CE->
getType());
1370 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1371 C.addTransition(stateZeroSize);
1375 if (!stateNonZeroSize)
1379 state = stateNonZeroSize;
1384 SVal ArgVal = state->getSVal(Arg, LCtx);
1386 state = checkNonNull(C, state, Arg, ArgVal);
1391 SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1395 if (strLength.isUndef())
1398 DefinedOrUnknownSVal
result = UnknownVal();
1403 QualType cmpTy = C.getSValBuilder().getConditionType();
1408 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1413 if (strLengthNL && maxlenValNL) {
1417 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1419 .evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1420 .castAs<DefinedOrUnknownSVal>());
1422 if (stateStringTooLong && !stateStringNotTooLong) {
1424 result = *maxlenValNL;
1425 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1427 result = *strLengthNL;
1431 if (result.isUnknown()) {
1436 result = C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1438 NonLoc resultNL = result.castAs<NonLoc>();
1441 state = state->assume(C.getSValBuilder().evalBinOpNN(
1442 state, BO_LE, resultNL, *strLengthNL, cmpTy)
1443 .castAs<DefinedOrUnknownSVal>(),
true);
1447 state = state->assume(C.getSValBuilder().evalBinOpNN(
1448 state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1449 .castAs<DefinedOrUnknownSVal>(),
true);
1455 result = strLength.castAs<DefinedOrUnknownSVal>();
1459 if (result.isUnknown()) {
1460 result = C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1466 assert(!result.isUnknown() &&
"Should have conjured a value by now");
1467 state = state->BindExpr(CE, LCtx, result);
1468 C.addTransition(state);
1471 void CStringChecker::evalStrcpy(CheckerContext &C,
const CallExpr *CE)
const {
1473 evalStrcpyCommon(C, CE,
1479 void CStringChecker::evalStrncpy(CheckerContext &C,
const CallExpr *CE)
const {
1481 evalStrcpyCommon(C, CE,
1487 void CStringChecker::evalStpcpy(CheckerContext &C,
const CallExpr *CE)
const {
1489 evalStrcpyCommon(C, CE,
1495 void CStringChecker::evalStrlcpy(CheckerContext &C,
const CallExpr *CE)
const {
1497 evalStrcpyCommon(C, CE,
1504 void CStringChecker::evalStrcat(CheckerContext &C,
const CallExpr *CE)
const {
1506 evalStrcpyCommon(C, CE,
1512 void CStringChecker::evalStrncat(CheckerContext &C,
const CallExpr *CE)
const {
1514 evalStrcpyCommon(C, CE,
1520 void CStringChecker::evalStrlcat(CheckerContext &C,
const CallExpr *CE)
const {
1526 evalStrcpyCommon(C, CE,
1533 void CStringChecker::evalStrcpyCommon(CheckerContext &C,
const CallExpr *CE,
1534 bool returnEnd,
bool isBounded,
1535 bool isAppending,
bool returnPtr)
const {
1536 CurrentFunctionDescription =
"string copy function";
1542 SVal DstVal = state->getSVal(Dst, LCtx);
1544 state = checkNonNull(C, state, Dst, DstVal);
1550 SVal srcVal = state->getSVal(srcExpr, LCtx);
1551 state = checkNonNull(C, state, srcExpr, srcVal);
1556 SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1559 if (strLength.isUndef())
1562 SValBuilder &svalBuilder = C.getSValBuilder();
1563 QualType cmpTy = svalBuilder.getConditionType();
1564 QualType sizeTy = svalBuilder.getContext().getSizeType();
1569 SVal amountCopied = UnknownVal();
1570 SVal maxLastElementIndex = UnknownVal();
1571 const char *boundWarning =
nullptr;
1573 state = CheckOverlap(C, state, isBounded ? CE->
getArg(2) : CE->
getArg(1), Dst, srcExpr);
1582 SVal lenVal = state->getSVal(lenExpr, LCtx);
1585 lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->
getType());
1592 if (strLengthNL && lenValNL) {
1598 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1599 svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1600 .castAs<DefinedOrUnknownSVal>());
1602 if (stateSourceTooLong && !stateSourceNotTooLong) {
1605 state = stateSourceTooLong;
1606 amountCopied = lenVal;
1608 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1610 state = stateSourceNotTooLong;
1611 amountCopied = strLength;
1623 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1624 if (dstStrLength.isUndef())
1628 maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add,
1632 boundWarning =
"Size argument is greater than the free space in the " 1633 "destination buffer";
1645 std::tie(StateZeroSize, StateNonZeroSize) =
1646 assumeZero(C, state, *lenValNL, sizeTy);
1649 if (StateZeroSize && !StateNonZeroSize) {
1651 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1653 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, *lenValNL);
1655 C.addTransition(StateZeroSize);
1662 NonLoc one = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
1663 maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL,
1665 boundWarning =
"Size argument is greater than the length of the " 1666 "destination buffer";
1674 if (amountCopied.isUnknown() && !isAppending) {
1677 amountCopied = getCStringLength(C, state, lenExpr, srcVal,
true);
1678 assert(!amountCopied.isUndef());
1683 SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE,
1687 state = state->assume(
1688 copiedLessThanBound.castAs<DefinedOrUnknownSVal>(),
true);
1695 SVal copiedLessThanSrc = svalBuilder.evalBinOpNN(state, BO_LE,
1699 state = state->assume(
1700 copiedLessThanSrc.castAs<DefinedOrUnknownSVal>(),
true);
1710 amountCopied = strLength;
1718 SVal finalStrLength = UnknownVal();
1726 SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1727 if (dstStrLength.isUndef())
1734 if (srcStrLengthNL && dstStrLengthNL) {
1736 state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1740 finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL,
1741 *dstStrLengthNL, sizeTy);
1746 if (finalStrLength.isUnknown()) {
1749 finalStrLength = getCStringLength(C, state, CE, DstVal,
true);
1750 assert(!finalStrLength.isUndef());
1753 if (srcStrLengthNL) {
1755 SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE,
1759 state = state->assume(sourceInResult.castAs<DefinedOrUnknownSVal>(),
1765 if (dstStrLengthNL) {
1767 SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE,
1772 state->assume(destInResult.castAs<DefinedOrUnknownSVal>(),
true);
1782 finalStrLength = amountCopied;
1790 Result = (returnEnd ? UnknownVal() : DstVal);
1792 Result = finalStrLength;
1800 DstVal.getAs<loc::MemRegionVal>()) {
1807 SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
1809 state = CheckLocation(C, state, CE->
getArg(2), maxLastElement,
1818 SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
1819 *knownStrLength, ptrTy);
1822 if (!boundWarning) {
1823 const char *
const warningMsg =
1824 "String copy function overflows destination buffer";
1825 state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1831 if (returnPtr && returnEnd)
1832 Result = lastElement;
1842 state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1847 state = InvalidateBuffer(C, state, srcExpr, srcVal,
true,
1851 if (isBounded && !isAppending) {
1856 if (amountCopied != strLength)
1857 finalStrLength = UnknownVal();
1859 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1867 if (returnEnd && Result.isUnknown()) {
1868 Result = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx, C.blockCount());
1872 state = state->BindExpr(CE, LCtx, Result);
1873 C.addTransition(state);
1876 void CStringChecker::evalStrcmp(CheckerContext &C,
const CallExpr *CE)
const {
1878 evalStrcmpCommon(C, CE,
false,
false);
1881 void CStringChecker::evalStrncmp(CheckerContext &C,
const CallExpr *CE)
const {
1883 evalStrcmpCommon(C, CE,
true,
false);
1886 void CStringChecker::evalStrcasecmp(CheckerContext &C,
1889 evalStrcmpCommon(C, CE,
false,
true);
1892 void CStringChecker::evalStrncasecmp(CheckerContext &C,
1895 evalStrcmpCommon(C, CE,
true,
true);
1898 void CStringChecker::evalStrcmpCommon(CheckerContext &C,
const CallExpr *CE,
1899 bool isBounded,
bool ignoreCase)
const {
1900 CurrentFunctionDescription =
"string comparison function";
1906 SVal s1Val = state->getSVal(s1, LCtx);
1907 state = checkNonNull(C, state, s1, s1Val);
1913 SVal s2Val = state->getSVal(s2, LCtx);
1914 state = checkNonNull(C, state, s2, s2Val);
1919 SVal s1Length = getCStringLength(C, state, s1, s1Val);
1920 if (s1Length.isUndef())
1924 SVal s2Length = getCStringLength(C, state, s2, s2Val);
1925 if (s2Length.isUndef())
1931 DefinedOrUnknownSVal LV = s1Val.castAs<DefinedOrUnknownSVal>();
1932 DefinedOrUnknownSVal RV = s2Val.castAs<DefinedOrUnknownSVal>();
1935 SValBuilder &svalBuilder = C.getSValBuilder();
1936 DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
1938 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1943 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1944 svalBuilder.makeZeroVal(CE->
getType()));
1945 C.addTransition(StSameBuf);
1952 assert(StNotSameBuf);
1953 state = StNotSameBuf;
1959 const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1960 const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1961 bool canComputeResult =
false;
1962 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
1965 if (s1StrLiteral && s2StrLiteral) {
1966 StringRef s1StrRef = s1StrLiteral->
getString();
1967 StringRef s2StrRef = s2StrLiteral->
getString();
1972 SVal lenVal = state->getSVal(lenExpr, LCtx);
1975 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1977 s1StrRef = s1StrRef.substr(0, (
size_t)len->getZExtValue());
1978 s2StrRef = s2StrRef.substr(0, (
size_t)len->getZExtValue());
1979 canComputeResult =
true;
1983 canComputeResult =
true;
1986 if (canComputeResult) {
1988 size_t s1Term = s1StrRef.find(
'\0');
1989 if (s1Term != StringRef::npos)
1990 s1StrRef = s1StrRef.substr(0, s1Term);
1992 size_t s2Term = s2StrRef.find(
'\0');
1993 if (s2Term != StringRef::npos)
1994 s2StrRef = s2StrRef.substr(0, s2Term);
1997 int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
1998 : s1StrRef.compare(s2StrRef);
2002 if (compareRes == 0) {
2003 resultVal = svalBuilder.makeIntVal(compareRes, CE->
getType());
2006 DefinedSVal zeroVal = svalBuilder.makeIntVal(0, CE->
getType());
2010 SVal compareWithZero =
2011 svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
2012 svalBuilder.getConditionType());
2013 DefinedSVal compareWithZeroVal = compareWithZero.castAs<DefinedSVal>();
2014 state = state->assume(compareWithZeroVal,
true);
2019 state = state->BindExpr(CE, LCtx, resultVal);
2022 C.addTransition(state);
2025 void CStringChecker::evalStrsep(CheckerContext &C,
const CallExpr *CE)
const {
2030 if (CharPtrTy.
isNull() ||
2034 CurrentFunctionDescription =
"strsep()";
2040 SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
2041 State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
2047 SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
2048 State = checkNonNull(C, State, DelimStr, DelimStrVal);
2052 SValBuilder &SVB = C.getSValBuilder();
2054 if (
Optional<Loc> SearchStrLoc = SearchStrVal.getAs<Loc>()) {
2056 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
2060 State = InvalidateBuffer(C, State, SearchStrPtr, Result,
2065 State = State->bindLoc(*SearchStrLoc,
2066 SVB.conjureSymbolVal(getTag(),
2073 assert(SearchStrVal.isUnknown());
2075 Result = SVB.conjureSymbolVal(
nullptr, CE, LCtx, C.blockCount());
2079 State = State->BindExpr(CE, LCtx, Result);
2080 C.addTransition(State);
2084 void CStringChecker::evalStdCopy(CheckerContext &C,
const CallExpr *CE)
const {
2085 evalStdCopyCommon(C, CE);
2088 void CStringChecker::evalStdCopyBackward(CheckerContext &C,
2090 evalStdCopyCommon(C, CE);
2093 void CStringChecker::evalStdCopyCommon(CheckerContext &C,
2109 SVal DstVal = State->getSVal(Dst, LCtx);
2110 State = InvalidateBuffer(C, State, Dst, DstVal,
false,
2113 SValBuilder &SVB = C.getSValBuilder();
2115 SVal ResultVal = SVB.conjureSymbolVal(
nullptr, CE, LCtx, C.blockCount());
2116 State = State->BindExpr(CE, LCtx, ResultVal);
2118 C.addTransition(State);
2121 void CStringChecker::evalMemset(CheckerContext &C,
const CallExpr *CE)
const {
2122 CurrentFunctionDescription =
"memory set function";
2131 SVal SizeVal = State->getSVal(Size, LCtx);
2135 std::tie(StateZeroSize, StateNonZeroSize) =
2136 assumeZero(C, State, SizeVal, SizeTy);
2139 SVal MemVal = State->getSVal(Mem, LCtx);
2143 if (StateZeroSize && !StateNonZeroSize) {
2144 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, MemVal);
2145 C.addTransition(StateZeroSize);
2151 State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
2155 State = CheckBufferAccess(C, State, Size, Mem);
2162 if (!memsetAux(Mem, C.getSVal(CharE), Size, C,
State))
2165 State = State->BindExpr(CE, LCtx, MemVal);
2166 C.addTransition(State);
2169 void CStringChecker::evalBzero(CheckerContext &C,
const CallExpr *CE)
const {
2170 CurrentFunctionDescription =
"memory clearance function";
2174 SVal Zero = C.getSValBuilder().makeZeroVal(C.getASTContext().IntTy);
2179 SVal SizeVal = C.getSVal(Size);
2183 std::tie(StateZeroSize, StateNonZeroSize) =
2184 assumeZero(C, State, SizeVal, SizeTy);
2188 if (StateZeroSize && !StateNonZeroSize) {
2189 C.addTransition(StateZeroSize);
2194 SVal MemVal = C.getSVal(Mem);
2198 State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
2202 State = CheckBufferAccess(C, State, Size, Mem);
2206 if (!memsetAux(Mem, Zero, Size, C, State))
2209 C.addTransition(State);
2216 CStringChecker::FnCheck CStringChecker::identifyCall(
const CallEvent &Call,
2217 CheckerContext &C)
const {
2218 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
2222 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
2226 if (Call.isCalled(StdCopy)) {
2227 return &CStringChecker::evalStdCopy;
2228 }
else if (Call.isCalled(StdCopyBackward)) {
2229 return &CStringChecker::evalStdCopyBackward;
2242 const FnCheck *Callback = Callbacks.lookup(Call);
2249 bool CStringChecker::evalCall(
const CallEvent &Call, CheckerContext &C)
const {
2250 FnCheck Callback = identifyCall(Call, C);
2257 const auto *CE = cast<CallExpr>(Call.getOriginExpr());
2258 (this->*Callback)(C, CE);
2266 return C.isDifferent();
2269 void CStringChecker::checkPreStmt(
const DeclStmt *DS, CheckerContext &C)
const {
2273 for (
const auto *I : DS->
decls()) {
2285 if (!isa<StringLiteral>(Init))
2288 Loc VarLoc = state->getLValue(D, C.getLocationContext());
2289 const MemRegion *MR = VarLoc.getAsRegion();
2293 SVal StrVal = C.getSVal(Init);
2294 assert(StrVal.isValid() &&
"Initializer string is unknown or undefined");
2295 DefinedOrUnknownSVal strLength =
2296 getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>();
2298 state = state->set<CStringLength>(MR, strLength);
2301 C.addTransition(state);
2311 CStringLengthTy Entries = state->get<CStringLength>();
2312 if (Entries.isEmpty())
2315 llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
2316 llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
2320 I = Regions.begin(), E = Regions.end(); I != E; ++I) {
2321 const MemRegion *MR = *I;
2322 Invalidated.insert(MR);
2324 SuperRegions.insert(MR);
2325 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2326 MR = SR->getSuperRegion();
2327 SuperRegions.insert(MR);
2331 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2334 for (CStringLengthTy::iterator I = Entries.begin(),
2335 E = Entries.end(); I != E; ++I) {
2336 const MemRegion *MR = I.getKey();
2339 if (SuperRegions.count(MR)) {
2340 Entries = F.remove(Entries, MR);
2345 const MemRegion *Super = MR;
2346 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2347 Super = SR->getSuperRegion();
2348 if (Invalidated.count(Super)) {
2349 Entries = F.remove(Entries, MR);
2355 return state->set<CStringLength>(Entries);
2359 SymbolReaper &SR)
const {
2361 CStringLengthTy Entries = state->get<CStringLength>();
2363 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2365 SVal Len = I.getData();
2367 for (SymExpr::symbol_iterator si = Len.symbol_begin(),
2368 se = Len.symbol_end(); si != se; ++si)
2373 void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
2374 CheckerContext &C)
const {
2376 CStringLengthTy Entries = state->get<CStringLength>();
2377 if (Entries.isEmpty())
2380 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2381 for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2383 SVal Len = I.getData();
2384 if (
SymbolRef Sym = Len.getAsSymbol()) {
2386 Entries = F.remove(Entries, I.getKey());
2390 state = state->set<CStringLength>(Entries);
2391 C.addTransition(state);
2394 void ento::registerCStringModeling(CheckerManager &Mgr) {
2395 Mgr.registerChecker<CStringChecker>();
2398 bool ento::shouldRegisterCStringModeling(
const LangOptions &LO) {
2402 #define REGISTER_CHECKER(name) \ 2403 void ento::register##name(CheckerManager &mgr) { \ 2404 CStringChecker *checker = mgr.getChecker<CStringChecker>(); \ 2405 checker->Filter.Check##name = true; \ 2406 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \ 2409 bool ento::shouldRegister##name(const LangOptions &LO) { \ 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.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Represents a variable declaration or definition.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const char *const UnixAPI
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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.
This class represents a description of a function call using the number of arguments and the name of ...
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.
Dataflow Directional Tag Classes.
const Expr * getInit() const
Describes a C standard function that is sometimes implemented as a macro that expands to a compiler b...
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.
An immutable map from CallDescriptions to arbitrary data.
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>.