26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/SmallString.h"
28#include "llvm/ADT/StringExtras.h"
29#include "llvm/Support/raw_ostream.h"
35using namespace std::placeholders;
40 unsigned ArgumentIndex;
42struct SourceArgExpr : AnyArgExpr {};
43struct DestinationArgExpr : AnyArgExpr {};
44struct SizeArgExpr : AnyArgExpr {};
47enum class AccessKind { write, read };
49static ErrorMessage createOutOfBoundErrorMsg(StringRef FunctionDescription,
52 llvm::raw_svector_ostream Os(Message);
56 << &FunctionDescription.data()[1];
58 if (Access == AccessKind::write) {
59 Os <<
" overflows the destination buffer";
61 Os <<
" accesses out-of-bound array element";
67enum class ConcatFnKind { none = 0, strcat = 1, strlcat = 2 };
69enum class CharKind { Regular = 0,
Wide };
70constexpr CharKind CK_Regular = CharKind::Regular;
71constexpr CharKind CK_Wide = CharKind::Wide;
78class CStringChecker :
public Checker< eval::Call,
79 check::PreStmt<DeclStmt>,
84 mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap,
85 BT_NotCString, BT_AdditionOverflow, BT_UninitRead;
87 mutable const char *CurrentFunctionDescription =
nullptr;
92 struct CStringChecksFilter {
93 bool CheckCStringNullArg =
false;
94 bool CheckCStringOutOfBounds =
false;
95 bool CheckCStringBufferOverlap =
false;
96 bool CheckCStringNotNullTerm =
false;
97 bool CheckCStringUninitializedRead =
false;
106 CStringChecksFilter
Filter;
108 static void *getTag() {
static int tag;
return &tag; }
123 using FnCheck = std::function<void(
const CStringChecker *,
CheckerContext &,
128 std::bind(&CStringChecker::evalMemcpy, _1,
_2, _3, CK_Regular)},
130 std::bind(&CStringChecker::evalMemcpy, _1,
_2, _3, CK_Wide)},
132 std::bind(&CStringChecker::evalMempcpy, _1,
_2, _3, CK_Regular)},
134 std::bind(&CStringChecker::evalMempcpy, _1,
_2, _3, CK_Wide)},
136 std::bind(&CStringChecker::evalMemcmp, _1,
_2, _3, CK_Regular)},
138 std::bind(&CStringChecker::evalMemcmp, _1,
_2, _3, CK_Wide)},
140 std::bind(&CStringChecker::evalMemmove, _1,
_2, _3, CK_Regular)},
142 std::bind(&CStringChecker::evalMemmove, _1,
_2, _3, CK_Wide)},
160 &CStringChecker::evalStrncasecmp},
164 std::bind(&CStringChecker::evalMemcmp, _1,
_2, _3, CK_Regular)},
173 StdCopyBackward{{
"std",
"copy_backward"}, 3};
182 DestinationArgExpr Dest, SourceArgExpr Source,
183 bool Restricted,
bool IsMempcpy, CharKind CK)
const;
191 bool IsStrnlen =
false)
const;
198 bool IsBounded, ConcatFnKind appendK,
199 bool returnPtr =
true)
const;
211 bool IsBounded =
false,
212 bool IgnoreCase =
false)
const;
225 bool IsBuiltin)
const;
228 std::pair<ProgramStateRef , ProgramStateRef >
244 bool hypothetical =
false)
const;
263 static ProgramStateRef invalidateDestinationBufferAlwaysEscapeSuperRegion(
278 InvalidationTraitOperations);
280 static bool SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
283 static bool memsetAux(
const Expr *DstBuffer,
SVal CharE,
289 AnyArgExpr Arg,
SVal l)
const;
291 AnyArgExpr Buffer,
SVal Element,
293 CharKind CK = CharKind::Regular)
const;
295 AnyArgExpr Buffer, SizeArgExpr Size,
297 CharKind CK = CharKind::Regular)
const;
299 SizeArgExpr Size, AnyArgExpr
First,
301 CharKind CK = CharKind::Regular)
const;
305 const Stmt *Second)
const;
308 StringRef WarningMsg)
const;
310 const Stmt *S, StringRef WarningMsg)
const;
312 const Stmt *S, StringRef WarningMsg)
const;
315 const Expr *E)
const;
337std::pair<ProgramStateRef , ProgramStateRef >
340 std::optional<DefinedSVal> val =
V.getAs<
DefinedSVal>();
342 return std::pair<ProgramStateRef , ProgramStateRef >(state, state);
346 return state->assume(svalBuilder.
evalEQ(state, *val, zero));
351 AnyArgExpr Arg,
SVal l)
const {
357 std::tie(stateNull, stateNonNull) =
358 assumeZero(
C, State, l, Arg.Expression->getType());
360 if (stateNull && !stateNonNull) {
361 if (
Filter.CheckCStringNullArg) {
363 llvm::raw_svector_ostream OS(buf);
364 assert(CurrentFunctionDescription);
365 OS <<
"Null pointer passed as " << (Arg.ArgumentIndex + 1)
366 << llvm::getOrdinalSuffix(Arg.ArgumentIndex + 1) <<
" argument to "
367 << CurrentFunctionDescription;
369 emitNullArgBug(
C, stateNull, Arg.Expression, OS.str());
375 assert(stateNonNull);
382 AnyArgExpr Buffer,
SVal Element,
391 const MemRegion *R = Element.getAsRegion();
395 const auto *ER = dyn_cast<ElementRegion>(R);
403 NonLoc Idx = ER->getIndex();
405 if (CK == CharKind::Regular) {
406 if (ER->getValueType() != Ctx.
CharTy)
418 SVal Offset = svalBuilder.
evalBinOpNN(state, BO_Mul, Idx, WideSize, SizeTy);
419 if (Offset.isUnknown())
421 Idx = Offset.castAs<
NonLoc>();
425 const auto *superReg = cast<SubRegion>(ER->getSuperRegion());
430 std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, Size);
431 if (StOutBound && !StInBound) {
435 if (!
Filter.CheckCStringOutOfBounds)
439 ErrorMessage Message =
440 createOutOfBoundErrorMsg(CurrentFunctionDescription, Access);
441 emitOutOfBoundsBug(
C, StOutBound, Buffer.Expression, Message);
446 if (Access == AccessKind::read) {
447 if (
Filter.CheckCStringUninitializedRead &&
448 StInBound->getSVal(ER).isUndef()) {
449 emitUninitializedReadBug(
C, StInBound, Buffer.Expression);
461 AnyArgExpr Buffer, SizeArgExpr Size,
462 AccessKind Access, CharKind CK)
const {
471 QualType PtrTy = getCharPtrType(Ctx, CK);
474 SVal BufVal =
C.getSVal(Buffer.Expression);
475 State = checkNonNull(
C, State, Buffer, BufVal);
480 if (!
Filter.CheckCStringOutOfBounds)
484 svalBuilder.
evalCast(BufVal, PtrTy, Buffer.Expression->getType());
487 State = CheckLocation(
C, State, Buffer, BufStart, Access, CK);
494 SVal LengthVal =
C.getSVal(
Size.Expression);
495 std::optional<NonLoc> Length = LengthVal.
getAs<
NonLoc>();
501 SVal Offset = svalBuilder.
evalBinOpNN(State, BO_Sub, *Length, One, SizeTy);
502 if (Offset.isUnknown())
507 if (std::optional<Loc> BufLoc = BufStart.
getAs<
Loc>()) {
510 svalBuilder.
evalBinOpLN(State, BO_Add, *BufLoc, LastOffset, PtrTy);
511 State = CheckLocation(
C, State, Buffer, BufEnd, Access, CK);
524 SizeArgExpr Size, AnyArgExpr
First,
527 if (!
Filter.CheckCStringBufferOverlap)
541 if (
First.Expression->getType()->getPointeeType().getAddressSpace() !=
542 Second.Expression->getType()->getPointeeType().getAddressSpace())
547 SVal firstVal = state->getSVal(
First.Expression, LCtx);
548 SVal secondVal = state->getSVal(Second.Expression, LCtx);
550 std::optional<Loc> firstLoc = firstVal.
getAs<
Loc>();
554 std::optional<Loc> secondLoc = secondVal.
getAs<
Loc>();
560 std::tie(stateTrue, stateFalse) =
561 state->assume(svalBuilder.
evalEQ(state, *firstLoc, *secondLoc));
563 if (stateTrue && !stateFalse) {
565 emitOverlapBug(
C, stateTrue,
First.Expression, Second.Expression);
576 svalBuilder.
evalBinOpLL(state, BO_GT, *firstLoc, *secondLoc, cmpTy);
577 std::optional<DefinedOrUnknownSVal> reverseTest =
582 std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
589 std::swap(firstLoc, secondLoc);
592 std::swap(
First, Second);
597 SVal LengthVal = state->getSVal(
Size.Expression, LCtx);
598 std::optional<NonLoc> Length = LengthVal.
getAs<
NonLoc>();
605 QualType CharPtrTy = getCharPtrType(Ctx, CK);
607 svalBuilder.
evalCast(*firstLoc, CharPtrTy,
First.Expression->getType());
608 std::optional<Loc> FirstStartLoc = FirstStart.
getAs<
Loc>();
615 std::optional<Loc> FirstEndLoc = FirstEnd.
getAs<
Loc>();
621 svalBuilder.
evalBinOpLL(state, BO_GT, *FirstEndLoc, *secondLoc, cmpTy);
622 std::optional<DefinedOrUnknownSVal> OverlapTest =
627 std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
629 if (stateTrue && !stateFalse) {
631 emitOverlapBug(
C, stateTrue,
First.Expression, Second.Expression);
647 BT_Overlap.reset(
new BugType(
Filter.CheckNameCStringBufferOverlap,
651 auto report = std::make_unique<PathSensitiveBugReport>(
652 *BT_Overlap,
"Arguments must not be overlapping buffers", N);
653 report->addRange(
First->getSourceRange());
656 C.emitReport(std::move(report));
660 const Stmt *S, StringRef WarningMsg)
const {
670 std::make_unique<PathSensitiveBugReport>(*BT_Null, WarningMsg, N);
671 Report->addRange(S->getSourceRange());
672 if (
const auto *Ex = dyn_cast<Expr>(S))
674 C.emitReport(std::move(Report));
680 const Expr *E)
const {
683 "Bytes string function accesses uninitialized/garbage values";
685 BT_UninitRead.reset(
new BugType(
Filter.CheckNameCStringUninitializedRead,
686 "Accessing unitialized/garbage values"));
689 std::make_unique<PathSensitiveBugReport>(*BT_UninitRead, Msg, N);
692 C.emitReport(std::move(Report));
698 StringRef WarningMsg)
const {
702 ?
Filter.CheckNameCStringOutOfBounds
703 :
Filter.CheckNameCStringNullArg,
704 "Out-of-bound array access"));
710 std::make_unique<PathSensitiveBugReport>(*BT_Bounds, WarningMsg, N);
711 Report->addRange(S->getSourceRange());
712 C.emitReport(std::move(Report));
718 StringRef WarningMsg)
const {
720 if (!BT_NotCString) {
728 std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N);
730 Report->addRange(S->getSourceRange());
731 C.emitReport(std::move(Report));
738 if (!BT_AdditionOverflow) {
742 BT_AdditionOverflow.reset(
749 const char *WarningMsg =
750 "This expression will create a string whose length is too big to "
751 "be represented as a size_t";
753 auto Report = std::make_unique<PathSensitiveBugReport>(*BT_AdditionOverflow,
755 C.emitReport(std::move(Report));
764 if (!
Filter.CheckCStringOutOfBounds)
775 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
779 if (isa<nonloc::ConcreteInt>(right)) {
780 maxMinusRight = svalBuilder.
evalBinOpNN(state, BO_Sub, maxVal, right,
785 maxMinusRight = svalBuilder.
evalBinOpNN(state, BO_Sub, maxVal, left,
790 if (std::optional<NonLoc> maxMinusRightNL = maxMinusRight.
getAs<
NonLoc>()) {
794 *maxMinusRightNL, cmpTy);
797 std::tie(stateOverflow, stateOkay) =
800 if (stateOverflow && !stateOkay) {
802 emitAdditionOverflowBug(
C, stateOverflow);
817 assert(!strLength.
isUndef() &&
"Attempt to set an undefined string length");
822 case MemRegion::StringRegionKind:
827 case MemRegion::SymbolicRegionKind:
828 case MemRegion::AllocaRegionKind:
829 case MemRegion::NonParamVarRegionKind:
830 case MemRegion::ParamVarRegionKind:
831 case MemRegion::FieldRegionKind:
832 case MemRegion::ObjCIvarRegionKind:
836 case MemRegion::ElementRegionKind:
850 return state->remove<CStringLength>(MR);
852 return state->set<CStringLength>(MR, strLength);
862 const SVal *Recorded = state->get<CStringLength>(MR);
872 C.getLocationContext(),
876 if (std::optional<NonLoc> strLn = strLength.
getAs<
NonLoc>()) {
879 const llvm::APSInt &maxValInt = BVF.
getMaxValue(sizeTy);
881 const llvm::APSInt *maxLengthInt = BVF.
evalAPSInt(BO_Div, maxValInt,
884 SVal evalLength = svalBuilder.
evalBinOpNN(state, BO_LE, *strLn, maxLength,
888 state = state->set<CStringLength>(MR, strLength);
896 bool hypothetical)
const {
903 if (
Filter.CheckCStringNotNullTerm) {
905 llvm::raw_svector_ostream os(buf);
906 assert(CurrentFunctionDescription);
907 os <<
"Argument to " << CurrentFunctionDescription
908 <<
" is the address of the label '" <<
Label->getLabel()->getName()
909 <<
"', which is not a null-terminated string";
911 emitNotCStringBug(
C, state, Ex, os.str());
925 case MemRegion::StringRegionKind: {
930 const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
933 case MemRegion::NonParamVarRegionKind: {
936 const VarDecl *
Decl = cast<NonParamVarRegion>(MR)->getDecl();
937 if (
Decl->getType().isConstQualified() &&
Decl->hasGlobalStorage()) {
939 if (
auto *StrLit = dyn_cast<StringLiteral>(
Init)) {
942 return SvalBuilder.
makeIntVal(StrLit->getLength(), SizeTy);
948 case MemRegion::SymbolicRegionKind:
949 case MemRegion::AllocaRegionKind:
950 case MemRegion::ParamVarRegionKind:
951 case MemRegion::FieldRegionKind:
952 case MemRegion::ObjCIvarRegionKind:
953 return getCStringLengthForRegion(
C, state, Ex, MR, hypothetical);
954 case MemRegion::CompoundLiteralRegionKind:
957 case MemRegion::ElementRegionKind:
965 if (
Filter.CheckCStringNotNullTerm) {
967 llvm::raw_svector_ostream os(buf);
969 assert(CurrentFunctionDescription);
970 os <<
"Argument to " << CurrentFunctionDescription <<
" is ";
972 if (SummarizeRegion(os,
C.getASTContext(), MR))
973 os <<
", which is not a null-terminated string";
975 os <<
"not a null-terminated string";
977 emitNotCStringBug(
C, state, Ex, os.str());
995 const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);
1019 std::optional<NonLoc> Length = LengthVal.
getAs<
NonLoc>();
1026 if (Offset.isUnknown())
1032 std::optional<Loc> BufLoc = BufStart.
getAs<
Loc>();
1036 SVal BufEnd = SB.
evalBinOpLN(State, BO_Add, *BufLoc, LastOffset, PtrTy);
1050 "isFirstBufInBound should only be called with char* ElementRegions");
1061 return static_cast<bool>(StInBound);
1067 auto InvalidationTraitOperations =
1068 [&
C, S, BufTy = BufE->
getType(), BufV, SizeV,
1072 if (MemRegion::FieldRegionKind == R->
getKind() &&
1073 isFirstBufInBound(
C, S, BufV, BufTy, SizeV, SizeTy)) {
1081 return invalidateBufferAux(
C, S, BufE, BufV, InvalidationTraitOperations);
1085CStringChecker::invalidateDestinationBufferAlwaysEscapeSuperRegion(
1089 return isa<FieldRegion>(R);
1092 return invalidateBufferAux(
C, S, BufE, BufV, InvalidationTraitOperations);
1095ProgramStateRef CStringChecker::invalidateDestinationBufferNeverOverflows(
1097 auto InvalidationTraitOperations =
1099 if (MemRegion::FieldRegionKind == R->
getKind())
1106 return invalidateBufferAux(
C, S, BufE, BufV, InvalidationTraitOperations);
1113 auto InvalidationTraitOperations =
1123 return invalidateBufferAux(
C, S, BufE, BufV, InvalidationTraitOperations);
1130 InvalidationTraitOperations) {
1131 std::optional<Loc> L =
V.getAs<
Loc>();
1151 bool CausesPointerEscape = InvalidationTraitOperations(ITraits, R);
1153 return State->invalidateRegions(R, E,
C.blockCount(), LCtx,
1154 CausesPointerEscape,
nullptr,
nullptr,
1161 return State->killBinding(*L);
1164bool CStringChecker::SummarizeRegion(raw_ostream &os,
ASTContext &Ctx,
1167 case MemRegion::FunctionCodeRegionKind: {
1168 if (
const auto *FD = cast<FunctionCodeRegion>(MR)->getDecl())
1169 os <<
"the address of the function '" << *FD <<
'\'';
1171 os <<
"the address of a function";
1174 case MemRegion::BlockCodeRegionKind:
1177 case MemRegion::BlockDataRegionKind:
1180 case MemRegion::CXXThisRegionKind:
1181 case MemRegion::CXXTempObjectRegionKind:
1182 os <<
"a C++ temp object of type "
1183 << cast<TypedValueRegion>(MR)->getValueType();
1185 case MemRegion::NonParamVarRegionKind:
1186 os <<
"a variable of type" << cast<TypedValueRegion>(MR)->getValueType();
1188 case MemRegion::ParamVarRegionKind:
1189 os <<
"a parameter of type" << cast<TypedValueRegion>(MR)->getValueType();
1191 case MemRegion::FieldRegionKind:
1192 os <<
"a field of type " << cast<TypedValueRegion>(MR)->getValueType();
1194 case MemRegion::ObjCIvarRegionKind:
1195 os <<
"an instance variable of type "
1196 << cast<TypedValueRegion>(MR)->getValueType();
1203bool CStringChecker::memsetAux(
const Expr *DstBuffer,
SVal CharVal,
1206 SVal MemVal =
C.getSVal(DstBuffer);
1207 SVal SizeVal =
C.getSVal(Size);
1217 const MemRegion *BR = Offset.getRegion();
1219 std::optional<NonLoc> SizeNL = SizeVal.
getAs<
NonLoc>();
1228 if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
1229 Offset.getOffset() == 0) {
1234 std::tie(StateWholeReg, StateNotWholeReg) =
1235 State->assume(svalBuilder.
evalEQ(State, SizeDV, *SizeNL));
1242 std::tie(StateNullChar, StateNonNullChar) =
1245 if (StateWholeReg && !StateNotWholeReg && StateNullChar &&
1246 !StateNonNullChar) {
1253 State = State->bindDefaultZero(svalBuilder.
makeLoc(BR),
1254 C.getLocationContext());
1258 State = invalidateDestinationBufferBySize(
C, State, DstBuffer, MemVal,
1259 SizeVal,
Size->getType());
1262 if (StateNullChar && !StateNonNullChar) {
1265 State = setCStringLength(State, MR,
1267 }
else if (!StateNullChar && StateNonNullChar) {
1269 CStringChecker::getTag(), MR, DstBuffer, Ctx.
getSizeType(),
1270 C.getLocationContext(),
C.blockCount());
1277 State = setCStringLength(
1284 State = invalidateDestinationBufferBySize(
C, State, DstBuffer, MemVal,
1285 SizeVal,
Size->getType());
1296 DestinationArgExpr Dest,
1297 SourceArgExpr Source,
bool Restricted,
1298 bool IsMempcpy, CharKind CK)
const {
1299 CurrentFunctionDescription =
"memory copy function";
1303 SVal sizeVal = state->getSVal(
Size.Expression, LCtx);
1307 std::tie(stateZeroSize, stateNonZeroSize) =
1308 assumeZero(
C, state, sizeVal, sizeTy);
1311 SVal destVal = state->getSVal(Dest.Expression, LCtx);
1315 if (stateZeroSize && !stateNonZeroSize) {
1316 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
1317 C.addTransition(stateZeroSize);
1322 if (stateNonZeroSize) {
1323 state = stateNonZeroSize;
1327 state = checkNonNull(
C, state, Dest, destVal);
1332 SVal srcVal = state->getSVal(Source.Expression, LCtx);
1336 state = checkNonNull(
C, state, Source, srcVal);
1341 state = CheckBufferAccess(
C, state, Dest, Size, AccessKind::write, CK);
1342 state = CheckBufferAccess(
C, state, Source, Size, AccessKind::read, CK);
1345 state = CheckOverlap(
C, state, Size, Dest, Source, CK);
1356 QualType CharPtrTy = getCharPtrType(Ctx, CK);
1357 SVal DestRegCharVal =
1358 SvalBuilder.
evalCast(destVal, CharPtrTy, Dest.Expression->getType());
1359 SVal lastElement =
C.getSValBuilder().evalBinOp(
1360 state, BO_Add, DestRegCharVal, sizeVal, Dest.Expression->getType());
1364 lastElement =
C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1368 state = state->BindExpr(CE, LCtx, lastElement);
1372 state = state->BindExpr(CE, LCtx, destVal);
1381 state = invalidateDestinationBufferBySize(
1382 C, state, Dest.Expression,
C.getSVal(Dest.Expression), sizeVal,
1383 Size.Expression->getType());
1387 state = invalidateSourceBuffer(
C, state, Source.Expression,
1388 C.getSVal(Source.Expression));
1390 C.addTransition(state);
1395 CharKind CK)
const {
1398 DestinationArgExpr Dest = {{CE->
getArg(0), 0}};
1399 SourceArgExpr Src = {{CE->
getArg(1), 1}};
1404 constexpr bool IsRestricted =
true;
1405 constexpr bool IsMempcpy =
false;
1406 evalCopyCommon(
C, CE, State, Size, Dest, Src, IsRestricted, IsMempcpy, CK);
1410 CharKind CK)
const {
1413 DestinationArgExpr Dest = {{CE->
getArg(0), 0}};
1414 SourceArgExpr Src = {{CE->
getArg(1), 1}};
1417 constexpr bool IsRestricted =
true;
1418 constexpr bool IsMempcpy =
true;
1419 evalCopyCommon(
C, CE,
C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy,
1424 CharKind CK)
const {
1427 DestinationArgExpr Dest = {{CE->
getArg(0), 0}};
1428 SourceArgExpr Src = {{CE->
getArg(1), 1}};
1431 constexpr bool IsRestricted =
false;
1432 constexpr bool IsMempcpy =
false;
1433 evalCopyCommon(
C, CE,
C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy,
1439 SourceArgExpr Src{{CE->
getArg(0), 0}};
1440 DestinationArgExpr Dest = {{CE->
getArg(1), 1}};
1443 constexpr bool IsRestricted =
false;
1444 constexpr bool IsMempcpy =
false;
1445 evalCopyCommon(
C, CE,
C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy,
1450 CharKind CK)
const {
1452 CurrentFunctionDescription =
"memory comparison function";
1454 AnyArgExpr Left = {CE->
getArg(0), 0};
1455 AnyArgExpr Right = {CE->
getArg(1), 1};
1463 SVal sizeVal = State->getSVal(
Size.Expression, LCtx);
1467 std::tie(stateZeroSize, stateNonZeroSize) =
1468 assumeZero(
C, State, sizeVal, sizeTy);
1472 if (stateZeroSize) {
1473 State = stateZeroSize;
1474 State = State->BindExpr(CE, LCtx, Builder.makeZeroVal(CE->
getType()));
1475 C.addTransition(State);
1479 if (stateNonZeroSize) {
1480 State = stateNonZeroSize;
1491 std::tie(SameBuffer, NotSameBuffer) =
1492 State->assume(Builder.evalEQ(State, LV, RV));
1496 if (SameBuffer && !NotSameBuffer) {
1498 State = CheckBufferAccess(
C, State, Left, Size, AccessKind::read);
1501 SameBuffer->BindExpr(CE, LCtx, Builder.makeZeroVal(CE->
getType()));
1502 C.addTransition(State);
1509 assert(NotSameBuffer);
1510 State = CheckBufferAccess(
C, State, Right, Size, AccessKind::read, CK);
1511 State = CheckBufferAccess(
C, State, Left, Size, AccessKind::read, CK);
1514 SVal CmpV = Builder.conjureSymbolVal(
nullptr, CE, LCtx,
C.blockCount());
1515 State = State->BindExpr(CE, LCtx, CmpV);
1516 C.addTransition(State);
1524 evalstrLengthCommon(
C, CE,
false);
1530 evalstrLengthCommon(
C, CE,
true);
1534 bool IsStrnlen)
const {
1535 CurrentFunctionDescription =
"string length function";
1541 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1544 std::tie(stateZeroSize, stateNonZeroSize) =
1545 assumeZero(
C, state, maxlenVal, maxlenExpr->
getType());
1549 if (stateZeroSize) {
1550 SVal zero =
C.getSValBuilder().makeZeroVal(CE->
getType());
1551 stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1552 C.addTransition(stateZeroSize);
1556 if (!stateNonZeroSize)
1560 state = stateNonZeroSize;
1564 AnyArgExpr Arg = {CE->
getArg(0), 0};
1565 SVal ArgVal = state->getSVal(Arg.Expression, LCtx);
1566 state = checkNonNull(
C, state, Arg, ArgVal);
1571 SVal strLength = getCStringLength(
C, state, Arg.Expression, ArgVal);
1583 QualType cmpTy =
C.getSValBuilder().getConditionType();
1588 SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1590 std::optional<NonLoc> strLengthNL = strLength.
getAs<
NonLoc>();
1591 std::optional<NonLoc> maxlenValNL = maxlenVal.
getAs<
NonLoc>();
1593 if (strLengthNL && maxlenValNL) {
1597 std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume(
1599 .evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1602 if (stateStringTooLong && !stateStringNotTooLong) {
1604 result = *maxlenValNL;
1605 }
else if (stateStringNotTooLong && !stateStringTooLong) {
1607 result = *strLengthNL;
1616 result =
C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1621 state = state->assume(
C.getSValBuilder().evalBinOpNN(
1622 state, BO_LE, resultNL, *strLengthNL, cmpTy)
1627 state = state->assume(
C.getSValBuilder().evalBinOpNN(
1628 state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1640 result =
C.getSValBuilder().conjureSymbolVal(
nullptr, CE, LCtx,
1646 assert(!result.
isUnknown() &&
"Should have conjured a value by now");
1647 state = state->BindExpr(CE, LCtx, result);
1648 C.addTransition(state);
1653 evalStrcpyCommon(
C, CE,
1656 ConcatFnKind::none);
1661 evalStrcpyCommon(
C, CE,
1664 ConcatFnKind::none);
1669 evalStrcpyCommon(
C, CE,
1672 ConcatFnKind::none);
1677 evalStrcpyCommon(
C, CE,
1686 evalStrcpyCommon(
C, CE,
1689 ConcatFnKind::strcat);
1694 evalStrcpyCommon(
C, CE,
1697 ConcatFnKind::strcat);
1704 evalStrcpyCommon(
C, CE,
1707 ConcatFnKind::strlcat,
1712 bool ReturnEnd,
bool IsBounded,
1713 ConcatFnKind appendK,
1714 bool returnPtr)
const {
1715 if (appendK == ConcatFnKind::none)
1716 CurrentFunctionDescription =
"string copy function";
1718 CurrentFunctionDescription =
"string concatenation function";
1724 DestinationArgExpr Dst = {{CE->
getArg(0), 0}};
1725 SVal DstVal = state->getSVal(Dst.Expression, LCtx);
1726 state = checkNonNull(
C, state, Dst, DstVal);
1731 SourceArgExpr srcExpr = {{CE->
getArg(1), 1}};
1732 SVal srcVal = state->getSVal(srcExpr.Expression, LCtx);
1733 state = checkNonNull(
C, state, srcExpr, srcVal);
1738 SVal strLength = getCStringLength(
C, state, srcExpr.Expression, srcVal);
1739 std::optional<NonLoc> strLengthNL = strLength.
getAs<
NonLoc>();
1742 SVal dstStrLength = getCStringLength(
C, state, Dst.Expression, DstVal);
1743 std::optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<
NonLoc>();
1758 const char *boundWarning =
nullptr;
1762 SizeArgExpr SrcExprAsSizeDummy = {
1763 {srcExpr.Expression, srcExpr.ArgumentIndex}};
1764 state = CheckOverlap(
1766 (IsBounded ? SizeArgExpr{{CE->
getArg(2), 2}} : SrcExprAsSizeDummy), Dst,
1775 SizeArgExpr lenExpr = {{CE->
getArg(2), 2}};
1776 SVal lenVal = state->getSVal(lenExpr.Expression, LCtx);
1780 svalBuilder.
evalCast(lenVal, sizeTy, lenExpr.Expression->getType());
1782 std::optional<NonLoc> lenValNL = lenVal.
getAs<
NonLoc>();
1786 if (strLengthNL && lenValNL) {
1788 case ConcatFnKind::none:
1789 case ConcatFnKind::strcat: {
1794 std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1796 .evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1797 .castAs<DefinedOrUnknownSVal>());
1799 if (stateSourceTooLong && !stateSourceNotTooLong) {
1802 state = stateSourceTooLong;
1803 amountCopied = lenVal;
1805 }
else if (!stateSourceTooLong && stateSourceNotTooLong) {
1807 state = stateSourceNotTooLong;
1808 amountCopied = strLength;
1812 case ConcatFnKind::strlcat:
1813 if (!dstStrLengthNL)
1818 *dstStrLengthNL, sizeTy);
1819 if (!isa<NonLoc>(freeSpace))
1822 svalBuilder.
evalBinOp(state, BO_Sub, freeSpace,
1824 std::optional<NonLoc> freeSpaceNL = freeSpace.
getAs<
NonLoc>();
1831 state, BO_LE, *strLengthNL, *freeSpaceNL, cmpTy);
1834 std::tie(TrueState, FalseState) =
1838 if (TrueState && !FalseState) {
1839 amountCopied = strLength;
1843 if (!TrueState && FalseState) {
1844 amountCopied = freeSpace;
1847 if (TrueState && FalseState)
1855 case ConcatFnKind::strcat:
1861 if (dstStrLength.isUndef())
1864 if (dstStrLengthNL) {
1866 state, BO_Add, *lenValNL, *dstStrLengthNL, sizeTy);
1868 boundWarning =
"Size argument is greater than the free space in the "
1869 "destination buffer";
1872 case ConcatFnKind::none:
1873 case ConcatFnKind::strlcat:
1883 std::tie(StateZeroSize, StateNonZeroSize) =
1884 assumeZero(
C, state, *lenValNL, sizeTy);
1887 if (StateZeroSize && !StateNonZeroSize) {
1889 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1891 if (appendK == ConcatFnKind::none) {
1893 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, strLength);
1897 state, BO_Add, strLength, dstStrLength, sizeTy);
1898 StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, retSize);
1901 C.addTransition(StateZeroSize);
1909 maxLastElementIndex =
1910 svalBuilder.
evalBinOpNN(state, BO_Sub, *lenValNL, one, sizeTy);
1911 boundWarning =
"Size argument is greater than the length of the "
1912 "destination buffer";
1919 amountCopied = strLength;
1930 if (appendK == ConcatFnKind::none && !returnPtr) {
1932 strlRetVal = strLength;
1938 if (appendK != ConcatFnKind::none) {
1941 if (dstStrLength.isUndef())
1944 if (appendK == ConcatFnKind::strlcat && dstStrLengthNL && strLengthNL) {
1945 strlRetVal = svalBuilder.
evalBinOpNN(state, BO_Add, *strLengthNL,
1946 *dstStrLengthNL, sizeTy);
1949 std::optional<NonLoc> amountCopiedNL = amountCopied.
getAs<
NonLoc>();
1952 if (amountCopiedNL && dstStrLengthNL) {
1954 state = checkAdditionOverflow(
C, state, *amountCopiedNL, *dstStrLengthNL);
1958 finalStrLength = svalBuilder.
evalBinOpNN(state, BO_Add, *amountCopiedNL,
1959 *dstStrLengthNL, sizeTy);
1967 finalStrLength = getCStringLength(
C, state, CE, DstVal,
true);
1968 assert(!finalStrLength.
isUndef());
1970 if (std::optional<NonLoc> finalStrLengthNL =
1972 if (amountCopiedNL && appendK == ConcatFnKind::none) {
1976 state, BO_GE, *finalStrLengthNL, *amountCopiedNL, cmpTy);
1983 if (dstStrLengthNL && appendK != ConcatFnKind::none) {
2001 finalStrLength = amountCopied;
2009 Result = (ReturnEnd ?
UnknownVal() : DstVal);
2011 if (appendK == ConcatFnKind::strlcat || appendK == ConcatFnKind::none)
2013 Result = strlRetVal;
2015 Result = finalStrLength;
2022 if (std::optional<loc::MemRegionVal> dstRegVal =
2024 QualType ptrTy = Dst.Expression->getType();
2028 if (std::optional<NonLoc> maxLastNL = maxLastElementIndex.
getAs<
NonLoc>()) {
2029 SVal maxLastElement =
2030 svalBuilder.
evalBinOpLN(state, BO_Add, *dstRegVal, *maxLastNL, ptrTy);
2033 state = CheckLocation(
C, state, Dst, DstVal, AccessKind::write);
2037 state = CheckLocation(
C, state, Dst, maxLastElement, AccessKind::write);
2043 if (std::optional<NonLoc> knownStrLength = finalStrLength.
getAs<
NonLoc>()) {
2045 *knownStrLength, ptrTy);
2048 if (!boundWarning) {
2050 state = CheckLocation(
C, state, Dst, DstVal, AccessKind::write);
2054 state = CheckLocation(
C, state, Dst, lastElement, AccessKind::write);
2060 if (returnPtr && ReturnEnd)
2061 Result = lastElement;
2071 state = invalidateDestinationBufferBySize(
C, state, Dst.Expression,
2072 *dstRegVal, amountCopied,
2073 C.getASTContext().getSizeType());
2077 state = invalidateSourceBuffer(
C, state, srcExpr.Expression, srcVal);
2080 if (IsBounded && (appendK == ConcatFnKind::none)) {
2085 if (amountCopied != strLength)
2088 state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
2096 if (ReturnEnd && Result.isUnknown()) {
2101 state = state->BindExpr(CE, LCtx, Result);
2102 C.addTransition(state);
2107 evalStrcmpCommon(
C, CE,
false,
false);
2112 evalStrcmpCommon(
C, CE,
true,
false);
2118 evalStrcmpCommon(
C, CE,
false,
true);
2124 evalStrcmpCommon(
C, CE,
true,
true);
2128 bool IsBounded,
bool IgnoreCase)
const {
2129 CurrentFunctionDescription =
"string comparison function";
2134 AnyArgExpr Left = {CE->
getArg(0), 0};
2135 SVal LeftVal = state->getSVal(Left.Expression, LCtx);
2136 state = checkNonNull(
C, state, Left, LeftVal);
2141 AnyArgExpr Right = {CE->
getArg(1), 1};
2142 SVal RightVal = state->getSVal(Right.Expression, LCtx);
2143 state = checkNonNull(
C, state, Right, RightVal);
2148 SVal LeftLength = getCStringLength(
C, state, Left.Expression, LeftVal);
2153 SVal RightLength = getCStringLength(
C, state, Right.Expression, RightVal);
2167 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
2172 StSameBuf = StSameBuf->BindExpr(CE, LCtx,
2173 svalBuilder.makeZeroVal(CE->
getType()));
2174 C.addTransition(StSameBuf);
2181 assert(StNotSameBuf);
2182 state = StNotSameBuf;
2189 getCStringLiteral(
C, state, Left.Expression, LeftVal);
2191 getCStringLiteral(
C, state, Right.Expression, RightVal);
2192 bool canComputeResult =
false;
2193 SVal resultVal = svalBuilder.conjureSymbolVal(
nullptr, CE, LCtx,
2196 if (LeftStrLiteral && RightStrLiteral) {
2197 StringRef LeftStrRef = LeftStrLiteral->
getString();
2198 StringRef RightStrRef = RightStrLiteral->
getString();
2203 SVal lenVal = state->getSVal(lenExpr, LCtx);
2206 if (
const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
2208 LeftStrRef = LeftStrRef.substr(0, (
size_t)len->getZExtValue());
2209 RightStrRef = RightStrRef.substr(0, (
size_t)len->getZExtValue());
2210 canComputeResult =
true;
2214 canComputeResult =
true;
2217 if (canComputeResult) {
2219 size_t s1Term = LeftStrRef.find(
'\0');
2220 if (s1Term != StringRef::npos)
2221 LeftStrRef = LeftStrRef.substr(0, s1Term);
2223 size_t s2Term = RightStrRef.find(
'\0');
2224 if (s2Term != StringRef::npos)
2225 RightStrRef = RightStrRef.substr(0, s2Term);
2228 int compareRes = IgnoreCase ? LeftStrRef.compare_insensitive(RightStrRef)
2229 : LeftStrRef.compare(RightStrRef);
2233 if (compareRes == 0) {
2234 resultVal = svalBuilder.makeIntVal(compareRes, CE->
getType());
2241 SVal compareWithZero =
2242 svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
2243 svalBuilder.getConditionType());
2245 state = state->assume(compareWithZeroVal,
true);
2250 state = state->BindExpr(CE, LCtx, resultVal);
2253 C.addTransition(state);
2259 SourceArgExpr SearchStrPtr = {{CE->
getArg(0), 0}};
2262 if (CharPtrTy.
isNull() ||
2266 CurrentFunctionDescription =
"strsep()";
2272 SVal SearchStrVal = State->getSVal(SearchStrPtr.Expression, LCtx);
2273 State = checkNonNull(
C, State, SearchStrPtr, SearchStrVal);
2278 AnyArgExpr DelimStr = {CE->
getArg(1), 1};
2279 SVal DelimStrVal = State->getSVal(DelimStr.Expression, LCtx);
2280 State = checkNonNull(
C, State, DelimStr, DelimStrVal);
2286 if (std::optional<Loc> SearchStrLoc = SearchStrVal.
getAs<
Loc>()) {
2288 Result = State->getSVal(*SearchStrLoc, CharPtrTy);
2293 State = invalidateDestinationBufferNeverOverflows(
2294 C, State, SearchStrPtr.Expression, Result);
2298 State = State->bindLoc(*SearchStrLoc,
2312 State = State->BindExpr(CE, LCtx, Result);
2313 C.addTransition(State);
2318 evalStdCopyCommon(
C, CE);
2323 evalStdCopyCommon(
C, CE);
2342 SVal DstVal = State->getSVal(Dst, LCtx);
2346 invalidateDestinationBufferAlwaysEscapeSuperRegion(
C, State, Dst, DstVal);
2351 State = State->BindExpr(CE, LCtx, ResultVal);
2353 C.addTransition(State);
2358 CurrentFunctionDescription =
"memory set function";
2360 DestinationArgExpr Buffer = {{CE->
getArg(0), 0}};
2361 AnyArgExpr CharE = {CE->
getArg(1), 1};
2368 SVal SizeVal =
C.getSVal(
Size.Expression);
2372 std::tie(ZeroSize, NonZeroSize) = assumeZero(
C, State, SizeVal, SizeTy);
2375 SVal BufferPtrVal =
C.getSVal(Buffer.Expression);
2379 if (ZeroSize && !NonZeroSize) {
2380 ZeroSize = ZeroSize->BindExpr(CE, LCtx, BufferPtrVal);
2381 C.addTransition(ZeroSize);
2387 State = checkNonNull(
C, NonZeroSize, Buffer, BufferPtrVal);
2391 State = CheckBufferAccess(
C, State, Buffer, Size, AccessKind::write);
2398 if (!memsetAux(Buffer.Expression,
C.getSVal(CharE.Expression),
2399 Size.Expression,
C, State))
2402 State = State->BindExpr(CE, LCtx, BufferPtrVal);
2403 C.addTransition(State);
2407 CurrentFunctionDescription =
"memory clearance function";
2409 DestinationArgExpr Buffer = {{CE->
getArg(0), 0}};
2411 SVal Zero =
C.getSValBuilder().makeZeroVal(
C.getASTContext().IntTy);
2416 SVal SizeVal =
C.getSVal(
Size.Expression);
2420 std::tie(StateZeroSize, StateNonZeroSize) =
2421 assumeZero(
C, State, SizeVal, SizeTy);
2425 if (StateZeroSize && !StateNonZeroSize) {
2426 C.addTransition(StateZeroSize);
2431 SVal MemVal =
C.getSVal(Buffer.Expression);
2435 State = checkNonNull(
C, StateNonZeroSize, Buffer, MemVal);
2439 State = CheckBufferAccess(
C, State, Buffer, Size, AccessKind::write);
2443 if (!memsetAux(Buffer.Expression, Zero,
Size.Expression,
C, State))
2446 C.addTransition(State);
2450 CurrentFunctionDescription =
"'sprintf'";
2452 evalSprintfCommon(
C, CE,
false, IsBI);
2456 CurrentFunctionDescription =
"'snprintf'";
2458 evalSprintfCommon(
C, CE,
true, IsBI);
2462 bool IsBounded,
bool IsBuiltin)
const {
2464 DestinationArgExpr Dest = {{CE->
getArg(0), 0}};
2469 const auto AllArguments =
2471 const auto VariadicArguments = drop_begin(enumerate(AllArguments), NumParams);
2473 for (
const auto &[ArgIdx, ArgExpr] : VariadicArguments) {
2476 !
type->isAnyPointerType() ||
2477 !
type->getPointeeType()->isAnyCharacterType())
2479 SourceArgExpr Source = {{ArgExpr,
unsigned(ArgIdx)}};
2482 SizeArgExpr SrcExprAsSizeDummy = {
2483 {Source.Expression, Source.ArgumentIndex}};
2484 State = CheckOverlap(
2486 (IsBounded ? SizeArgExpr{{CE->
getArg(1), 1}} : SrcExprAsSizeDummy),
2492 C.addTransition(State);
2499CStringChecker::FnCheck CStringChecker::identifyCall(
const CallEvent &
Call,
2501 const auto *CE = dyn_cast_or_null<CallExpr>(
Call.getOriginExpr());
2509 if (StdCopy.matches(
Call))
2510 return &CStringChecker::evalStdCopy;
2511 if (StdCopyBackward.matches(
Call))
2512 return &CStringChecker::evalStdCopyBackward;
2524 const FnCheck *Callback = Callbacks.lookup(
Call);
2532 FnCheck Callback = identifyCall(
Call,
C);
2539 const auto *CE = cast<CallExpr>(
Call.getOriginExpr());
2540 Callback(
this,
C, CE);
2548 return C.isDifferent();
2555 for (
const auto *I : DS->
decls()) {
2556 const VarDecl *D = dyn_cast<VarDecl>(I);
2567 if (!isa<StringLiteral>(
Init))
2570 Loc VarLoc = state->getLValue(D,
C.getLocationContext());
2576 assert(StrVal.
isValid() &&
"Initializer string is unknown or undefined");
2580 state = state->set<CStringLength>(MR, strLength);
2583 C.addTransition(state);
2593 CStringLengthTy Entries = state->get<CStringLength>();
2594 if (Entries.isEmpty())
2602 Invalidated.insert(MR);
2604 SuperRegions.insert(MR);
2605 while (
const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
2606 MR = SR->getSuperRegion();
2607 SuperRegions.insert(MR);
2611 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2614 for (
const MemRegion *MR : llvm::make_first_range(Entries)) {
2616 if (SuperRegions.count(MR)) {
2617 Entries = F.remove(Entries, MR);
2623 while (
const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2624 Super = SR->getSuperRegion();
2625 if (Invalidated.count(Super)) {
2626 Entries = F.remove(Entries, MR);
2632 return state->set<CStringLength>(Entries);
2638 CStringLengthTy Entries = state->get<CStringLength>();
2640 for (
SVal Len : llvm::make_second_range(Entries)) {
2649 CStringLengthTy Entries = state->get<CStringLength>();
2650 if (Entries.isEmpty())
2653 CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2654 for (
auto [Reg, Len] : Entries) {
2655 if (
SymbolRef Sym = Len.getAsSymbol()) {
2657 Entries = F.remove(Entries, Reg);
2661 state = state->set<CStringLength>(Entries);
2662 C.addTransition(state);
2669bool ento::shouldRegisterCStringModeling(
const CheckerManager &mgr) {
2673#define REGISTER_CHECKER(name) \
2674 void ento::register##name(CheckerManager &mgr) { \
2675 CStringChecker *checker = mgr.getChecker<CStringChecker>(); \
2676 checker->Filter.Check##name = true; \
2677 checker->Filter.CheckName##name = mgr.getCurrentCheckerName(); \
2680 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
Defines enum values for all the target-independent builtin functions.
#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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedCharTy
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
This represents one expression.
Represents a function declaration or definition.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Stmt - This represents one statement.
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.
unsigned getLength() const
StringRef getString() const
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Represents a variable declaration or definition.
const Expr * getInit() const
A record of the "type" of an APSInt, used for conversions.
llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
const llvm::APSInt * evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)
An immutable map from CallDescriptions to arbitrary data.
This class represents a description of a function call using the number of arguments and the name of ...
Represents an abstract call to a function or method along a particular path.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
ElementRegion is used to represent both array elements and casts.
QualType getValueType() const override
MemRegion - The root abstract class for all memory regions.
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
Information about invalidation for a particular region/symbol.
@ TK_PreserveContents
Tells that a region's contents is not changed.
@ TK_DoNotInvalidateSuperRegion
@ TK_SuppressEscape
Suppress pointer-escaping of a region.
void setTrait(SymbolRef Sym, InvalidationKinds IK)
Represent a region's offset within the top level base region.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
BasicValueFactory & getBasicValueFactory()
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...
DefinedSVal getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, const LocationContext *LCtx, unsigned count)
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.
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
loc::MemRegionVal makeLoc(SymbolRef sym)
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.
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
QualType getConditionType() const
SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs)
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
StringRegion - Region associated with a StringLiteral.
LLVM_ATTRIBUTE_RETURNS_NONNULL const StringLiteral * getStringLiteral() const
SubRegion - A region that subsets another larger region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
llvm::iterator_range< symbol_iterator > symbols() const
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
void markInUse(SymbolRef sym)
Marks a symbol as important to a checker.
__inline void unsigned int _2
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
const char *const UnixAPI
@ CDF_MaybeBuiltin
Describes a C standard function that is sometimes implemented as a macro that expands to a compiler b...
DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB)
bool Zero(InterpState &S, CodePtr OpPC)
LLVM_READONLY char toUppercase(char c)
Converts the given ASCII character to its uppercase equivalent.