;
33using namespacestd::placeholders;
49structStreamErrorState {
57 boolisNoError()
const{
returnNoError && !FEof && !FError; }
58 boolisFEof()
const{
return!NoError && FEof && !FError; }
59 boolisFError()
const{
return!NoError && !FEof && FError; }
61 bool operator==(
constStreamErrorState &ES)
const{
62 returnNoError == ES.NoError && FEof == ES.FEof && FError == ES.FError;
65 bool operator!=(
constStreamErrorState &ES)
const{
return!(*
this== ES); }
67StreamErrorState
operator|(
constStreamErrorState &
E)
const{
68 return{NoError ||
E.NoError, FEof ||
E.FEof, FError ||
E.FError};
71StreamErrorState
operator&(
constStreamErrorState &
E)
const{
72 return{NoError &&
E.NoError, FEof &&
E.FEof, FError &&
E.FError};
75StreamErrorState
operator~()
const{
return{!NoError, !FEof, !FError}; }
78 operator bool()
const{
returnNoError || FEof || FError; }
80LLVM_DUMP_METHOD
void dump()
const{ dumpToStream(llvm::errs()); }
81LLVM_DUMP_METHOD
voiddumpToStream(llvm::raw_ostream &os)
const{
82os <<
"NoError: "<< NoError <<
", FEof: "<< FEof
83<<
", FError: "<< FError;
86 voidProfile(llvm::FoldingSetNodeID &ID)
const{
87 ID.AddBoolean(NoError);
89 ID.AddBoolean(FError);
93constStreamErrorState ErrorNone{
true,
false,
false};
94constStreamErrorState ErrorFEof{
false,
true,
false};
95constStreamErrorState ErrorFError{
false,
false,
true};
101 constFnDescription *LastOperation;
110StringRef getKindStr()
const{
117 return "OpenFailed";
119llvm_unreachable(
"Unknown StreamState!");
124StreamErrorState
constErrorState;
134 bool constFilePositionIndeterminate =
false;
136StreamState(
constFnDescription *L, KindTy S,
constStreamErrorState &ES,
137 boolIsFilePositionIndeterminate)
138: LastOperation(L), State(S), ErrorState(ES),
139FilePositionIndeterminate(IsFilePositionIndeterminate) {
140assert((!ES.isFEof() || !IsFilePositionIndeterminate) &&
141 "FilePositionIndeterminate should be false in FEof case.");
142assert((State == Opened || ErrorState.isNoError()) &&
143 "ErrorState should be None in non-opened stream state.");
146 boolisOpened()
const{
returnState == Opened; }
147 boolisClosed()
const{
returnState ==
Closed; }
148 boolisOpenFailed()
const{
returnState == OpenFailed; }
153 returnLastOperation ==
X.LastOperation && State ==
X.State &&
154ErrorState ==
X.ErrorState &&
155FilePositionIndeterminate ==
X.FilePositionIndeterminate;
158 staticStreamState getOpened(
constFnDescription *L,
159 constStreamErrorState &ES = ErrorNone,
160 boolIsFilePositionIndeterminate =
false) {
161 returnStreamState{L, Opened, ES, IsFilePositionIndeterminate};
163 staticStreamState getClosed(
constFnDescription *L) {
164 returnStreamState{L,
Closed, {},
false};
166 staticStreamState getOpenFailed(
constFnDescription *L) {
167 returnStreamState{L, OpenFailed, {},
false};
170LLVM_DUMP_METHOD
void dump()
const{ dumpToStream(llvm::errs()); }
171LLVM_DUMP_METHOD
voiddumpToStream(llvm::raw_ostream &os)
const;
173 voidProfile(llvm::FoldingSetNodeID &ID)
const{
174 ID.AddPointer(LastOperation);
175 ID.AddInteger(State);
176ErrorState.Profile(ID);
177 ID.AddBoolean(FilePositionIndeterminate);
195usingFnCheck = std::function<void(
constStreamChecker *,
constFnDescription *,
198usingArgNoTy =
unsigned int;
199static constArgNoTy ArgNone = std::numeric_limits<ArgNoTy>::max();
201const char*FeofNote =
"Assuming stream reaches end-of-file here";
202const char*FerrorNote =
"Assuming this stream operation fails";
204structFnDescription {
210LLVM_DUMP_METHOD
voidStreamState::dumpToStream(llvm::raw_ostream &os)
const{
211os <<
"{Kind: "<< getKindStr() <<
", Last operation: "<< LastOperation
212<<
", ErrorState: ";
213ErrorState.dumpToStream(os);
214os <<
", FilePos: "<< (FilePositionIndeterminate ?
"Indeterminate":
"OK")
221assert(Desc && Desc->StreamArgNo != ArgNone &&
222 "Try to get a non-existing stream argument.");
223 return Call.getArgSVal(Desc->StreamArgNo);
228assert(CE &&
"Expecting a call expression.");
231 return C.getSValBuilder()
232.conjureSymbolVal(
nullptr, CE, LCtx,
C.blockCount())
239State = State->BindExpr(CE,
C.getLocationContext(), RetVal);
240State = State->assume(RetVal,
true);
241assert(State &&
"Assumption on new value should not fail.");
247State = State->BindExpr(CE,
C.getLocationContext(),
252inline voidassertStreamStateOpened(
constStreamState *SS) {
253assert(SS->isOpened() &&
"Stream is expected to be opened");
256classStreamChecker :
public Checker<check::PreCall, eval::Call,
257check::DeadSymbols, check::PointerEscape,
258check::ASTDecl<TranslationUnitDecl>> {
259 BugTypeBT_FileNull{
this,
"NULL stream pointer",
"Stream handling error"};
260 BugTypeBT_UseAfterClose{
this,
"Closed stream",
"Stream handling error"};
261 BugTypeBT_UseAfterOpenFailed{
this,
"Invalid stream",
262 "Stream handling error"};
263 BugTypeBT_IndeterminatePosition{
this,
"Invalid stream state",
264 "Stream handling error"};
265 BugTypeBT_IllegalWhence{
this,
"Illegal whence argument",
266 "Stream handling error"};
267 BugTypeBT_StreamEof{
this,
"Stream already in EOF",
"Stream handling error"};
268 BugTypeBT_ResourceLeak{
this,
"Resource leak",
"Stream handling error",
284 const BugType*getBT_StreamEof()
const{
return&BT_StreamEof; }
285 const BugType*getBT_IndeterminatePosition()
const{
286 return&BT_IndeterminatePosition;
299&BR.
getBugType() != this->getBT_StreamEof())
312&BR.
getBugType() != this->getBT_IndeterminatePosition())
328BR.markNotInteresting(StreamSym);
331 if(&BR.
getBugType() == this->getBT_IndeterminatePosition()) {
332BR.markNotInteresting(StreamSym);
341 boolTestMode =
false;
344 boolPedanticMode =
false;
350{{CDM::CLibrary, {
"fopen"}, 2},
351{
nullptr, &StreamChecker::evalFopen, ArgNone}},
352{{CDM::CLibrary, {
"fdopen"}, 2},
353{
nullptr, &StreamChecker::evalFopen, ArgNone}},
354{{CDM::CLibrary, {
"freopen"}, 3},
355{&StreamChecker::preFreopen, &StreamChecker::evalFreopen, 2}},
356{{CDM::CLibrary, {
"tmpfile"}, 0},
357{
nullptr, &StreamChecker::evalFopen, ArgNone}},
358{FCloseDesc, {&StreamChecker::preDefault, &StreamChecker::evalFclose, 0}},
359{{CDM::CLibrary, {
"fread"}, 4},
360{&StreamChecker::preRead,
361std::bind(&StreamChecker::evalFreadFwrite, _1,
_2, _3, _4,
true), 3}},
362{{CDM::CLibrary, {
"fwrite"}, 4},
363{&StreamChecker::preWrite,
364std::bind(&StreamChecker::evalFreadFwrite, _1,
_2, _3, _4,
false), 3}},
365{{CDM::CLibrary, {
"fgetc"}, 1},
366{&StreamChecker::preRead,
367std::bind(&StreamChecker::evalFgetx, _1,
_2, _3, _4,
true), 0}},
368{{CDM::CLibrary, {
"fgets"}, 3},
369{&StreamChecker::preRead,
370std::bind(&StreamChecker::evalFgetx, _1,
_2, _3, _4,
false), 2}},
371{{CDM::CLibrary, {
"getc"}, 1},
372{&StreamChecker::preRead,
373std::bind(&StreamChecker::evalFgetx, _1,
_2, _3, _4,
true), 0}},
374{{CDM::CLibrary, {
"fputc"}, 2},
375{&StreamChecker::preWrite,
376std::bind(&StreamChecker::evalFputx, _1,
_2, _3, _4,
true), 1}},
377{{CDM::CLibrary, {
"fputs"}, 2},
378{&StreamChecker::preWrite,
379std::bind(&StreamChecker::evalFputx, _1,
_2, _3, _4,
false), 1}},
380{{CDM::CLibrary, {
"putc"}, 2},
381{&StreamChecker::preWrite,
382std::bind(&StreamChecker::evalFputx, _1,
_2, _3, _4,
true), 1}},
383{{CDM::CLibrary, {
"fprintf"}},
384{&StreamChecker::preWrite,
385std::bind(&StreamChecker::evalFprintf, _1,
_2, _3, _4), 0}},
386{{CDM::CLibrary, {
"vfprintf"}, 3},
387{&StreamChecker::preWrite,
388std::bind(&StreamChecker::evalFprintf, _1,
_2, _3, _4), 0}},
389{{CDM::CLibrary, {
"fscanf"}},
390{&StreamChecker::preRead,
391std::bind(&StreamChecker::evalFscanf, _1,
_2, _3, _4), 0}},
392{{CDM::CLibrary, {
"vfscanf"}, 3},
393{&StreamChecker::preRead,
394std::bind(&StreamChecker::evalFscanf, _1,
_2, _3, _4), 0}},
395{{CDM::CLibrary, {
"ungetc"}, 2},
396{&StreamChecker::preWrite,
397std::bind(&StreamChecker::evalUngetc, _1,
_2, _3, _4), 1}},
398{{CDM::CLibrary, {
"getdelim"}, 4},
399{&StreamChecker::preRead,
400std::bind(&StreamChecker::evalGetdelim, _1,
_2, _3, _4), 3}},
401{{CDM::CLibrary, {
"getline"}, 3},
402{&StreamChecker::preRead,
403std::bind(&StreamChecker::evalGetdelim, _1,
_2, _3, _4), 2}},
404{{CDM::CLibrary, {
"fseek"}, 3},
405{&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
406{{CDM::CLibrary, {
"fseeko"}, 3},
407{&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
408{{CDM::CLibrary, {
"ftell"}, 1},
409{&StreamChecker::preWrite, &StreamChecker::evalFtell, 0}},
410{{CDM::CLibrary, {
"ftello"}, 1},
411{&StreamChecker::preWrite, &StreamChecker::evalFtell, 0}},
412{{CDM::CLibrary, {
"fflush"}, 1},
413{&StreamChecker::preFflush, &StreamChecker::evalFflush, 0}},
414{{CDM::CLibrary, {
"rewind"}, 1},
415{&StreamChecker::preDefault, &StreamChecker::evalRewind, 0}},
416{{CDM::CLibrary, {
"fgetpos"}, 2},
417{&StreamChecker::preWrite, &StreamChecker::evalFgetpos, 0}},
418{{CDM::CLibrary, {
"fsetpos"}, 2},
419{&StreamChecker::preDefault, &StreamChecker::evalFsetpos, 0}},
420{{CDM::CLibrary, {
"clearerr"}, 1},
421{&StreamChecker::preDefault, &StreamChecker::evalClearerr, 0}},
422{{CDM::CLibrary, {
"feof"}, 1},
423{&StreamChecker::preDefault,
424std::bind(&StreamChecker::evalFeofFerror, _1,
_2, _3, _4, ErrorFEof),
426{{CDM::CLibrary, {
"ferror"}, 1},
427{&StreamChecker::preDefault,
428std::bind(&StreamChecker::evalFeofFerror, _1,
_2, _3, _4, ErrorFError),
430{{CDM::CLibrary, {
"fileno"}, 1},
431{&StreamChecker::preDefault, &StreamChecker::evalFileno, 0}},
435{{CDM::SimpleFunc, {
"StreamTesterChecker_make_feof_stream"}, 1},
437std::bind(&StreamChecker::evalSetFeofFerror, _1,
_2, _3, _4, ErrorFEof,
440{{CDM::SimpleFunc, {
"StreamTesterChecker_make_ferror_stream"}, 1},
442std::bind(&StreamChecker::evalSetFeofFerror, _1,
_2, _3, _4,
443ErrorFError,
false),
446{
"StreamTesterChecker_make_ferror_indeterminate_stream"},
449std::bind(&StreamChecker::evalSetFeofFerror, _1,
_2, _3, _4,
455 mutablestd::optional<int> EofVal;
457 mutable intSeekSetVal = 0;
459 mutable intSeekCurVal = 1;
461 mutable intSeekEndVal = 2;
465 mutable const VarDecl*StdinDecl =
nullptr;
466 mutable const VarDecl*StdoutDecl =
nullptr;
467 mutable const VarDecl*StderrDecl =
nullptr;
469 voidevalFopen(
constFnDescription *Desc,
const CallEvent&
Call,
472 voidpreFreopen(
constFnDescription *Desc,
const CallEvent&
Call,
474 voidevalFreopen(
constFnDescription *Desc,
const CallEvent&
Call,
477 voidevalFclose(
constFnDescription *Desc,
const CallEvent&
Call,
480 voidpreRead(
constFnDescription *Desc,
const CallEvent&
Call,
483 voidpreWrite(
constFnDescription *Desc,
const CallEvent&
Call,
486 voidevalFreadFwrite(
constFnDescription *Desc,
const CallEvent&
Call,
489 voidevalFgetx(
constFnDescription *Desc,
const CallEvent&
Call,
492 voidevalFputx(
constFnDescription *Desc,
const CallEvent&
Call,
495 voidevalFprintf(
constFnDescription *Desc,
const CallEvent&
Call,
498 voidevalFscanf(
constFnDescription *Desc,
const CallEvent&
Call,
501 voidevalUngetc(
constFnDescription *Desc,
const CallEvent&
Call,
504 voidevalGetdelim(
constFnDescription *Desc,
const CallEvent&
Call,
507 voidpreFseek(
constFnDescription *Desc,
const CallEvent&
Call,
509 voidevalFseek(
constFnDescription *Desc,
const CallEvent&
Call,
512 voidevalFgetpos(
constFnDescription *Desc,
const CallEvent&
Call,
515 voidevalFsetpos(
constFnDescription *Desc,
const CallEvent&
Call,
518 voidevalFtell(
constFnDescription *Desc,
const CallEvent&
Call,
521 voidevalRewind(
constFnDescription *Desc,
const CallEvent&
Call,
524 voidpreDefault(
constFnDescription *Desc,
const CallEvent&
Call,
527 voidevalClearerr(
constFnDescription *Desc,
const CallEvent&
Call,
530 voidevalFeofFerror(
constFnDescription *Desc,
const CallEvent&
Call,
532 constStreamErrorState &ErrorKind)
const;
534 voidevalSetFeofFerror(
constFnDescription *Desc,
const CallEvent&
Call,
536 boolIndeterminate)
const;
538 voidpreFflush(
constFnDescription *Desc,
const CallEvent&
Call,
541 voidevalFflush(
constFnDescription *Desc,
const CallEvent&
Call,
544 voidevalFileno(
constFnDescription *Desc,
const CallEvent&
Call,
593 constFnDescription *lookupFn(
const CallEvent&
Call)
const{
596 for(
auto*
P:
Call.parameters()) {
599 T.getCanonicalType() != VaListType)
609 conststd::string &Message)
const{
610 return C.getNoteTag([
this, StreamSym,
627SeekSetVal = *OptInt;
629SeekEndVal = *OptInt;
631SeekCurVal = *OptInt;
641structStreamOperationEvaluator {
646 constStreamState *SS =
nullptr;
648StreamErrorState NewES;
651: SVB(
C.getSValBuilder()), ACtx(
C.getASTContext()) {
657StreamSym = getStreamArg(Desc,
Call).getAsSymbol();
660SS = State->get<StreamMap>(StreamSym);
663NewES = SS->ErrorState;
664CE = dyn_cast_or_null<CallExpr>(
Call.getOriginExpr());
668assertStreamStateOpened(SS);
673 boolisStreamEof()
const{
returnSS->ErrorState == ErrorFEof; }
680 constStreamState &NewSS) {
681NewES = NewSS.ErrorState;
682 returnState->set<StreamMap>(StreamSym, NewSS);
687 returnState->BindExpr(CE,
C.getLocationContext(), RetVal);
692 returnState->BindExpr(CE,
C.getLocationContext(),
698 returnState->BindExpr(CE,
C.getLocationContext(), Val);
703 returnState->BindExpr(CE,
C.getLocationContext(),
704 C.getSValBuilder().makeNullWithType(CE->
getType()));
714 returnState->assume(*Cond,
true);
720State = State->BindExpr(CE,
C.getLocationContext(), RetVal);
721 return C.getConstraintManager().assumeDual(State, RetVal);
725 boolSetFeof = NewES.FEof && !SS->ErrorState.FEof;
726 boolSetFerror = NewES.FError && !SS->ErrorState.FError;
727 if(SetFeof && !SetFerror)
728 returnCh->constructSetEofNoteTag(
C, StreamSym);
729 if(!SetFeof && SetFerror)
730 returnCh->constructSetErrorNoteTag(
C, StreamSym);
731 if(SetFeof && SetFerror)
732 returnCh->constructSetEofOrErrorNoteTag(
C, StreamSym);
751 boolisClosingCallAsWritten(
const CallExpr&
Call)
const{
752 const auto*StreamChk =
static_cast<constStreamChecker *
>(&
Checker);
753 returnStreamChk->FCloseDesc.matchesAsWritten(
Call);
758 const FunctionDecl*FD = dyn_cast<FunctionDecl>(Callee);
773 if(
const auto*
Call= Match.getNodeAs<
CallExpr>(
"call"))
774 if(isClosingCallAsWritten(*
Call))
784 returnCallEnterState->get<StreamMap>(
Sym) !=
785CallExitEndState->get<StreamMap>(Sym);
791N->
getState()->getStateManager().getContext().getSourceManager());
792 returnstd::make_shared<PathDiagnosticEventPiece>(
793L,
"Returning without closing stream object or storing it for later " 810 if(!State->get<StreamMap>(StreamSym))
816 if(!State->get<StreamMap>(StreamSym))
826 SValBuilder&SVB = State->getStateManager().getSValBuilder();
828 returnInt->tryExtValue();
837 unsignedBlockCount,
const SubRegion*Buffer,
838 QualTypeElemType, int64_t StartIndex,
839int64_t ElementCount) {
840 constexpr autoDoNotInvalidateSuperRegion =
841RegionAndSymbolInvalidationTraits::InvalidationKinds::
842TK_DoNotInvalidateSuperRegion;
845 const ASTContext&Ctx = State->getStateManager().getContext();
846 SValBuilder&SVB = State->getStateManager().getSValBuilder();
850EscapingVals.reserve(ElementCount);
853 for(
autoIdx : llvm::seq(StartIndex, StartIndex + ElementCount)) {
855 const auto*Element =
856RegionManager.getElementRegion(ElemType, Index, Buffer, Ctx);
858ITraits.
setTrait(Element, DoNotInvalidateSuperRegion);
860 returnState->invalidateRegions(
861EscapingVals,
Call.getOriginExpr(), BlockCount, LCtx,
863 nullptr, &
Call, &ITraits);
869 autoGetArgSVal = [&
Call](
intIdx) {
return Call.getArgSVal(Idx); };
870 autoEscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));
871State = State->invalidateRegions(EscapingVals,
Call.getOriginExpr(),
872 C.blockCount(),
C.getLocationContext(),
884 constFnDescription *Desc = lookupFn(
Call);
885 if(!Desc || !Desc->PreFn)
888Desc->PreFn(
this, Desc,
Call,
C);
892 constFnDescription *Desc = lookupFn(
Call);
893 if(!Desc && TestMode)
895 if(!Desc || !Desc->EvalFn)
898Desc->EvalFn(
this, Desc,
Call,
C);
900 return C.isDifferent();
909 const auto*LCtx =
C.getLocationContext();
910 auto&StoreMgr =
C.getStoreManager();
911 auto&SVB =
C.getSValBuilder();
912 SValVarValue = State->getSVal(StoreMgr.getLValueVar(Var, LCtx));
915.castAs<DefinedOrUnknownSVal>();
916 returnState->assume(NoAliasState,
true);
920State = assumeRetNE(State, StdinDecl);
921State = assumeRetNE(State, StdoutDecl);
922State = assumeRetNE(State, StderrDecl);
927voidStreamChecker::evalFopen(
constFnDescription *Desc,
const CallEvent&
Call,
930 const CallExpr*CE = dyn_cast_or_null<CallExpr>(
Call.getOriginExpr());
936assert(RetSym &&
"RetVal must be a symbol here.");
938State = State->BindExpr(CE,
C.getLocationContext(), RetVal);
943std::tie(StateNotNull, StateNull) =
944 C.getConstraintManager().assumeDual(State, RetVal);
947StateNotNull->set<StreamMap>(RetSym, StreamState::getOpened(Desc));
949StateNull->set<StreamMap>(RetSym, StreamState::getOpenFailed(Desc));
951StateNotNull = assumeNoAliasingWithStdStreams(StateNotNull, RetVal,
C);
953 C.addTransition(StateNotNull,
954constructLeakNoteTag(
C, RetSym,
"Stream opened here"));
955 C.addTransition(StateNull);
958voidStreamChecker::preFreopen(
constFnDescription *Desc,
const CallEvent&
Call,
962State = ensureStreamNonNull(getStreamArg(Desc,
Call),
963 Call.getArgExpr(Desc->StreamArgNo),
C, State);
967 C.addTransition(State);
970voidStreamChecker::evalFreopen(
constFnDescription *Desc,
975 auto*CE = dyn_cast_or_null<CallExpr>(
Call.getOriginExpr());
979std::optional<DefinedSVal> StreamVal =
984 SymbolRefStreamSym = StreamVal->getAsSymbol();
991 if(!State->get<StreamMap>(StreamSym))
999State->BindExpr(CE,
C.getLocationContext(), *StreamVal);
1003State->BindExpr(CE,
C.getLocationContext(),
1004 C.getSValBuilder().makeNullWithType(CE->
getType()));
1007StateRetNotNull->set<StreamMap>(StreamSym, StreamState::getOpened(Desc));
1009StateRetNull->set<StreamMap>(StreamSym, StreamState::getOpenFailed(Desc));
1011 C.addTransition(StateRetNotNull,
1012constructLeakNoteTag(
C, StreamSym,
"Stream reopened here"));
1013 C.addTransition(StateRetNull);
1016voidStreamChecker::evalFclose(
constFnDescription *Desc,
const CallEvent&
Call,
1019StreamOperationEvaluator
E(
C);
1020 if(!
E.Init(Desc,
Call,
C, State))
1026State =
E.setStreamState(State, StreamState::getClosed(Desc));
1029 C.addTransition(
E.bindReturnValue(State,
C, 0));
1030 C.addTransition(
E.bindReturnValue(State,
C, *EofVal));
1033voidStreamChecker::preRead(
constFnDescription *Desc,
const CallEvent&
Call,
1036 SValStreamVal = getStreamArg(Desc,
Call);
1037State = ensureStreamNonNull(StreamVal,
Call.getArgExpr(Desc->StreamArgNo),
C,
1041State = ensureStreamOpened(StreamVal,
C, State);
1044State = ensureNoFilePositionIndeterminate(StreamVal,
C, State);
1049 if(Sym && State->get<StreamMap>(Sym)) {
1050 constStreamState *SS = State->get<StreamMap>(Sym);
1051 if(SS->ErrorState & ErrorFEof)
1052reportFEofWarning(Sym,
C, State);
1054 C.addTransition(State);
1058voidStreamChecker::preWrite(
constFnDescription *Desc,
const CallEvent&
Call,
1061 SValStreamVal = getStreamArg(Desc,
Call);
1062State = ensureStreamNonNull(StreamVal,
Call.getArgExpr(Desc->StreamArgNo),
C,
1066State = ensureStreamOpened(StreamVal,
C, State);
1069State = ensureNoFilePositionIndeterminate(StreamVal,
C, State);
1073 C.addTransition(State);
1079 if(
const auto*ER = dyn_cast<ElementRegion>(R))
1080 returnER->getElementType();
1081 if(
const auto*TR = dyn_cast<TypedValueRegion>(R))
1082 returnTR->getValueType();
1083 if(
const auto*SR = dyn_cast<SymbolicRegion>(R))
1084 returnSR->getPointeeStaticType();
1091 returnstd::nullopt;
1093 autoZero = [&SVB] {
1098 if(
const auto*ER = dyn_cast<ElementRegion>(R))
1099 returnER->getIndex();
1100 if(isa<TypedValueRegion>(R))
1102 if(isa<SymbolicRegion>(R))
1104 returnstd::nullopt;
1112 const auto*Buffer =
1113dyn_cast_or_null<SubRegion>(
Call.getArgSVal(0).getAsRegion());
1117std::optional<SVal> StartElementIndex =
1121 if(
const auto*ER = dyn_cast_or_null<ElementRegion>(Buffer))
1122Buffer = dyn_cast<SubRegion>(ER->getSuperRegion());
1124std::optional<int64_t> CountVal =
getKnownValue(State, NMembVal);
1125std::optional<int64_t> Size =
getKnownValue(State, SizeVal);
1126std::optional<int64_t> StartIndexVal =
1129 if(!ElemTy.
isNull() && CountVal && Size && StartIndexVal) {
1130int64_t NumBytesRead = Size.value() * CountVal.value();
1132 if(ElemSizeInChars == 0 || NumBytesRead < 0)
1135 boolIncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0;
1136int64_t NumCompleteOrIncompleteElementsRead =
1137NumBytesRead / ElemSizeInChars + IncompleteLastElement;
1139 constexpr intMaxInvalidatedElementsLimit = 64;
1140 if(NumCompleteOrIncompleteElementsRead <= MaxInvalidatedElementsLimit) {
1142ElemTy, *StartIndexVal,
1143NumCompleteOrIncompleteElementsRead);
1149voidStreamChecker::evalFreadFwrite(
constFnDescription *Desc,
1151 boolIsFread)
const{
1153StreamOperationEvaluator
E(
C);
1154 if(!
E.Init(Desc,
Call,
C, State))
1157std::optional<NonLoc> SizeVal =
Call.getArgSVal(1).getAs<
NonLoc>();
1160std::optional<NonLoc> NMembVal =
Call.getArgSVal(2).getAs<
NonLoc>();
1169 if(State->isNull(*SizeVal).isConstrainedTrue() ||
1170State->isNull(*NMembVal).isConstrainedTrue()) {
1173 C.addTransition(
E.bindReturnValue(State,
C, 0));
1179 if(IsFread && !
E.isStreamEof()) {
1183State,
C,
Call, *SizeVal, *NMembVal);
1185InvalidatedState ? InvalidatedState :
escapeArgs(State,
C,
Call, {0});
1190 if(!IsFread || !
E.isStreamEof()) {
1192State->BindExpr(
E.CE,
C.getLocationContext(), *NMembVal);
1194 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1195 C.addTransition(StateNotFailed);
1200 if(!IsFread && !PedanticMode)
1205State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1206StateFailed =
E.assumeBinOpNN(StateFailed, BO_LT, RetVal, *NMembVal);
1210StreamErrorState NewES;
1212NewES =
E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;
1214NewES = ErrorFError;
1217StateFailed =
E.setStreamState(
1218StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
1219 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1222voidStreamChecker::evalFgetx(
constFnDescription *Desc,
const CallEvent&
Call,
1228StreamOperationEvaluator
E(
C);
1229 if(!
E.Init(Desc,
Call,
C, State))
1232 if(!
E.isStreamEof()) {
1240State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1243StateNotFailed = StateNotFailed->assumeInclusiveRange(
1245 E.SVB.getBasicValueFactory().getValue(0,
E.ACtx.UnsignedCharTy),
1246 E.SVB.getBasicValueFactory().getMaxValue(
E.ACtx.UnsignedCharTy),
1248 if(!StateNotFailed)
1250 C.addTransition(StateNotFailed);
1253std::optional<DefinedSVal> GetBuf =
1258State->BindExpr(
E.CE,
C.getLocationContext(), *GetBuf);
1260 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1261 C.addTransition(StateNotFailed);
1268StateFailed =
E.bindReturnValue(State,
C, *EofVal);
1270StateFailed =
E.bindNullReturnValue(State,
C);
1274StreamErrorState NewES =
1275 E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;
1276StateFailed =
E.setStreamState(
1277StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
1278 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1281voidStreamChecker::evalFputx(
constFnDescription *Desc,
const CallEvent&
Call,
1287StreamOperationEvaluator
E(
C);
1288 if(!
E.Init(Desc,
Call,
C, State))
1293std::optional<NonLoc> PutVal =
Call.getArgSVal(0).getAs<
NonLoc>();
1297State->BindExpr(
E.CE,
C.getLocationContext(), *PutVal);
1299 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1300 C.addTransition(StateNotFailed);
1305State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1307 E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal,
E.getZeroVal(
Call));
1308 if(!StateNotFailed)
1311 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1312 C.addTransition(StateNotFailed);
1321StateFailed =
E.setStreamState(
1322StateFailed, StreamState::getOpened(Desc, ErrorFError,
true));
1323 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1326voidStreamChecker::evalFprintf(
constFnDescription *Desc,
1329 if(
Call.getNumArgs() < 2)
1333StreamOperationEvaluator
E(
C);
1334 if(!
E.Init(Desc,
Call,
C, State))
1338State = State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1341.evalBinOp(State, BO_GE, RetVal,
E.SVB.makeZeroVal(
E.ACtx.IntTy),
1342 E.SVB.getConditionType())
1343.getAs<DefinedOrUnknownSVal>();
1347std::tie(StateNotFailed, StateFailed) = State->assume(*Cond);
1350 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1351 C.addTransition(StateNotFailed);
1358StateFailed =
E.setStreamState(
1359StateFailed, StreamState::getOpened(Desc, ErrorFError,
true));
1360 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1363voidStreamChecker::evalFscanf(
constFnDescription *Desc,
const CallEvent&
Call,
1365 if(
Call.getNumArgs() < 2)
1369StreamOperationEvaluator
E(
C);
1370 if(!
E.Init(Desc,
Call,
C, State))
1381 if(!
E.isStreamEof()) {
1384State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1386 E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal,
E.getZeroVal(
Call));
1387 if(!StateNotFailed)
1390 if(
auto const*Callee =
Call.getCalleeIdentifier();
1393 for(
autoEscArg : llvm::seq(2u,
Call.getNumArgs()))
1394EscArgs.push_back(EscArg);
1399 C.addTransition(StateNotFailed);
1409StreamErrorState NewES =
1410 E.isStreamEof() ? ErrorFEof : ErrorNone | ErrorFEof | ErrorFError;
1411StateFailed =
E.setStreamState(
1412StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
1413 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1416voidStreamChecker::evalUngetc(
constFnDescription *Desc,
const CallEvent&
Call,
1419StreamOperationEvaluator
E(
C);
1420 if(!
E.Init(Desc,
Call,
C, State))
1424std::optional<NonLoc> PutVal =
Call.getArgSVal(0).getAs<
NonLoc>();
1429 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1430 C.addTransition(StateNotFailed);
1439StateFailed =
E.setStreamState(StateFailed, StreamState::getOpened(Desc));
1440 C.addTransition(StateFailed);
1443voidStreamChecker::evalGetdelim(
constFnDescription *Desc,
1447StreamOperationEvaluator
E(
C);
1448 if(!
E.Init(Desc,
Call,
C, State))
1457 if(!
E.isStreamEof()) {
1466 E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal,
E.getZeroVal(
Call));
1470 if(NewLinePtr && isa<DefinedOrUnknownSVal>(*NewLinePtr))
1471StateNotFailed = StateNotFailed->assume(
1476 SValSizePtrSval =
Call.getArgSVal(1);
1478 if(NVal && isa<NonLoc>(*NVal)) {
1479StateNotFailed =
E.assumeBinOpNN(StateNotFailed, BO_GT,
1480NVal->castAs<
NonLoc>(), RetVal);
1481StateNotFailed =
E.bindReturnValue(StateNotFailed,
C, RetVal);
1483 if(!StateNotFailed)
1485 C.addTransition(StateNotFailed);
1492StreamErrorState NewES =
1493 E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;
1494StateFailed =
E.setStreamState(
1495StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
1498StateFailed = StateFailed->bindLoc(*NewLinePtr,
UndefinedVal(),
1499 C.getLocationContext());
1500 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1503voidStreamChecker::preFseek(
constFnDescription *Desc,
const CallEvent&
Call,
1506 SValStreamVal = getStreamArg(Desc,
Call);
1507State = ensureStreamNonNull(StreamVal,
Call.getArgExpr(Desc->StreamArgNo),
C,
1511State = ensureStreamOpened(StreamVal,
C, State);
1514State = ensureFseekWhenceCorrect(
Call.getArgSVal(2),
C, State);
1518 C.addTransition(State);
1521voidStreamChecker::evalFseek(
constFnDescription *Desc,
const CallEvent&
Call,
1524StreamOperationEvaluator
E(
C);
1525 if(!
E.Init(Desc,
Call,
C, State))
1532 E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
1533 C.addTransition(StateNotFailed);
1545StateFailed =
E.setStreamState(
1546StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError,
true));
1547 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1550voidStreamChecker::evalFgetpos(
constFnDescription *Desc,
1554StreamOperationEvaluator
E(
C);
1555 if(!
E.Init(Desc,
Call,
C, State))
1559std::tie(StateFailed, StateNotFailed) =
E.makeRetValAndAssumeDual(State,
C);
1565 C.addTransition(StateNotFailed);
1566 C.addTransition(StateFailed);
1569voidStreamChecker::evalFsetpos(
constFnDescription *Desc,
1573StreamOperationEvaluator
E(
C);
1574 if(!
E.Init(Desc,
Call,
C, State))
1578std::tie(StateFailed, StateNotFailed) =
E.makeRetValAndAssumeDual(State,
C);
1580StateNotFailed =
E.setStreamState(
1581StateNotFailed, StreamState::getOpened(Desc, ErrorNone,
false));
1582 C.addTransition(StateNotFailed);
1591StateFailed =
E.setStreamState(
1592StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError,
true));
1594 C.addTransition(StateFailed,
E.getFailureNoteTag(
this,
C));
1597voidStreamChecker::evalFtell(
constFnDescription *Desc,
const CallEvent&
Call,
1600StreamOperationEvaluator
E(
C);
1601 if(!
E.Init(Desc,
Call,
C, State))
1606State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1608 E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal,
E.getZeroVal(
Call));
1609 if(!StateNotFailed)
1617 C.addTransition(StateNotFailed);
1618 C.addTransition(StateFailed);
1621voidStreamChecker::evalRewind(
constFnDescription *Desc,
const CallEvent&
Call,
1624StreamOperationEvaluator
E(
C);
1625 if(!
E.Init(Desc,
Call,
C, State))
1629 E.setStreamState(State, StreamState::getOpened(Desc, ErrorNone,
false));
1630 C.addTransition(State);
1633voidStreamChecker::preFflush(
constFnDescription *Desc,
const CallEvent&
Call,
1636 SValStreamVal = getStreamArg(Desc,
Call);
1642std::tie(StateNotNull, StateNull) =
1643 C.getConstraintManager().assumeDual(State, *Stream);
1644 if(StateNotNull && !StateNull)
1645ensureStreamOpened(StreamVal,
C, StateNotNull);
1648voidStreamChecker::evalFflush(
constFnDescription *Desc,
const CallEvent&
Call,
1651 SValStreamVal = getStreamArg(Desc,
Call);
1658std::tie(StateNotNull, StateNull) =
1659 C.getConstraintManager().assumeDual(State, *Stream);
1660 if(StateNotNull && StateNull)
1662 if(StateNotNull && !StateNull)
1663State = StateNotNull;
1667 const CallExpr*CE = dyn_cast_or_null<CallExpr>(
Call.getOriginExpr());
1676 autoClearErrorInNotFailed = [&StateNotFailed, Desc](
SymbolRefSym,
1677 constStreamState *SS) {
1678 if(SS->ErrorState & ErrorFError) {
1679StreamErrorState NewES =
1680(SS->ErrorState & ErrorFEof) ? ErrorFEof : ErrorNone;
1681StreamState NewSS = StreamState::getOpened(Desc, NewES,
false);
1682StateNotFailed = StateNotFailed->set<StreamMap>(Sym, NewSS);
1686 if(StateNotNull && !StateNull) {
1689 constStreamState *SS = State->get<StreamMap>(StreamSym);
1691assert(SS->isOpened() &&
"Stream is expected to be opened");
1692ClearErrorInNotFailed(StreamSym, SS);
1698 constStreamMapTy &Map = StateNotFailed->get<StreamMap>();
1699 for(
const auto&I : Map) {
1701 constStreamState &SS = I.second;
1703ClearErrorInNotFailed(Sym, &SS);
1707 C.addTransition(StateNotFailed);
1708 C.addTransition(StateFailed);
1711voidStreamChecker::evalClearerr(
constFnDescription *Desc,
1715StreamOperationEvaluator
E(
C);
1716 if(!
E.Init(Desc,
Call,
C, State))
1720State =
E.setStreamState(
1722StreamState::getOpened(Desc, ErrorNone,
E.SS->FilePositionIndeterminate));
1723 C.addTransition(State);
1726voidStreamChecker::evalFeofFerror(
constFnDescription *Desc,
1728 constStreamErrorState &ErrorKind)
const{
1730StreamOperationEvaluator
E(
C);
1731 if(!
E.Init(Desc,
Call,
C, State))
1734 if(
E.SS->ErrorState & ErrorKind) {
1739 C.addTransition(
E.setStreamState(
1740TrueState, StreamState::getOpened(Desc, ErrorKind,
1741 E.SS->FilePositionIndeterminate &&
1742!ErrorKind.isFEof())));
1744 if(StreamErrorState NewES =
E.SS->ErrorState & (~ErrorKind)) {
1749 C.addTransition(
E.setStreamState(
1751StreamState::getOpened(
1752Desc, NewES,
E.SS->FilePositionIndeterminate && !NewES.isFEof())));
1756voidStreamChecker::evalFileno(
constFnDescription *Desc,
const CallEvent&
Call,
1768StreamOperationEvaluator
E(
C);
1769 if(!
E.Init(Desc,
Call,
C, State))
1773State = State->BindExpr(
E.CE,
C.getLocationContext(), RetVal);
1774State =
E.assumeBinOpNN(State, BO_GE, RetVal,
E.getZeroVal(
Call));
1778 C.addTransition(State);
1781voidStreamChecker::preDefault(
constFnDescription *Desc,
const CallEvent&
Call,
1784 SValStreamVal = getStreamArg(Desc,
Call);
1785State = ensureStreamNonNull(StreamVal,
Call.getArgExpr(Desc->StreamArgNo),
C,
1789State = ensureStreamOpened(StreamVal,
C, State);
1793 C.addTransition(State);
1796voidStreamChecker::evalSetFeofFerror(
constFnDescription *Desc,
1798 constStreamErrorState &ErrorKind,
1799 boolIndeterminate)
const{
1801 SymbolRefStreamSym = getStreamArg(Desc,
Call).getAsSymbol();
1802assert(StreamSym &&
"Operation not permitted on non-symbolic stream value.");
1803 constStreamState *SS = State->get<StreamMap>(StreamSym);
1804assert(SS &&
"Stream should be tracked by the checker.");
1805State = State->set<StreamMap>(
1807StreamState::getOpened(SS->LastOperation, ErrorKind, Indeterminate));
1808 C.addTransition(State);
1812StreamChecker::ensureStreamNonNull(
SValStreamVal,
const Expr*StreamE,
1822std::tie(StateNotNull, StateNull) = CM.
assumeDual(State, *Stream);
1824 if(!StateNotNull && StateNull) {
1826 autoR = std::make_unique<PathSensitiveBugReport>(
1827BT_FileNull,
"Stream pointer might be NULL.", N);
1830 C.emitReport(std::move(R));
1835 returnStateNotNull;
1841 boolSatisfied =
false;
1844 explicitStreamClosedVisitor(
SymbolRefStreamSym) : StreamSym(StreamSym) {}
1846 static void*getTag() {
1851 void Profile(llvm::FoldingSetNodeID &ID)
const override{
1852 ID.AddPointer(getTag());
1853 ID.AddPointer(StreamSym);
1861 constStreamState *PredSS =
1863 if(PredSS && PredSS->isClosed())
1872llvm::StringLiteral Msg =
"Stream is closed here";
1873 returnstd::make_shared<PathDiagnosticEventPiece>(Pos, Msg);
1885 constStreamState *SS = State->get<StreamMap>(Sym);
1889 if(SS->isClosed()) {
1893 autoR = std::make_unique<PathSensitiveBugReport>(
1894BT_UseAfterClose,
"Use of a stream that might be already closed", N);
1895R->addVisitor<StreamClosedVisitor>(Sym);
1896 C.emitReport(std::move(R));
1903 if(SS->isOpenFailed()) {
1910 C.emitReport(std::make_unique<PathSensitiveBugReport>(
1911BT_UseAfterOpenFailed,
1912 "Stream might be invalid after " 1913 "(re-)opening it has failed. " 1914 "Can cause undefined behaviour.",
1925 static const char*BugMessage =
1926 "File position of the stream might be 'indeterminate' " 1927 "after a failed operation. " 1928 "Can cause undefined behavior.";
1934 constStreamState *SS = State->get<StreamMap>(Sym);
1938assert(SS->isOpened() &&
"First ensure that stream is opened.");
1940 if(SS->FilePositionIndeterminate) {
1941 if(SS->ErrorState & ErrorFEof) {
1949 autoR = std::make_unique<PathSensitiveBugReport>(
1950BT_IndeterminatePosition, BugMessage, N);
1951R->markInteresting(Sym);
1952 C.emitReport(std::move(R));
1953 returnState->set<StreamMap>(
1954Sym, StreamState::getOpened(SS->LastOperation, ErrorFEof,
false));
1960 autoR = std::make_unique<PathSensitiveBugReport>(
1961BT_IndeterminatePosition, BugMessage, N);
1962R->markInteresting(Sym);
1963 C.emitReport(std::move(R));
1975std::optional<nonloc::ConcreteInt> CI =
1980 int64_t X= CI->getValue()->getSExtValue();
1981 if(
X== SeekSetVal ||
X== SeekCurVal ||
X== SeekEndVal)
1984 if(
ExplodedNode*N =
C.generateNonFatalErrorNode(State)) {
1985 C.emitReport(std::make_unique<PathSensitiveBugReport>(
1987 "The whence argument to fseek() should be " 1988 "SEEK_SET, SEEK_END, or SEEK_CUR.",
1998 if(
ExplodedNode*N =
C.generateNonFatalErrorNode(State)) {
1999 autoR = std::make_unique<PathSensitiveBugReport>(
2001 "Read function called when stream is in EOF state. " 2002 "Function has no effect.",
2004R->markInteresting(StreamSym);
2005 C.emitReport(std::move(R));
2008 C.addTransition(State);
2014 ExplodedNode*Err =
C.generateNonFatalErrorNode(
C.getState(), Pred);
2030 const ExplodedNode*StreamOpenNode = getAcquisitionSite(Err, LeakSym,
C);
2031assert(StreamOpenNode &&
"Could not find place of stream opening.");
2036StreamStmt,
C.getSourceManager(),
2039std::unique_ptr<PathSensitiveBugReport> R =
2040std::make_unique<PathSensitiveBugReport>(
2042 "Opened stream never closed. Potential resource leak.", Err,
2043LocUsedForUniqueing,
2045R->markInteresting(LeakSym);
2046R->addVisitor<NoStreamStateChangeVisitor>(LeakSym,
this);
2047 C.emitReport(std::move(R));
2053voidStreamChecker::checkDeadSymbols(
SymbolReaper&SymReaper,
2059 constStreamMapTy &Map = State->get<StreamMap>();
2060 for(
const auto&I : Map) {
2062 constStreamState &SS = I.second;
2063 if(!SymReaper.
isDead(Sym))
2066LeakedSyms.push_back(Sym);
2067State = State->remove<StreamMap>(Sym);
2071 if(!LeakedSyms.empty())
2072N = reportLeaks(LeakedSyms,
C, N);
2074 C.addTransition(State, N);
2094State = State->remove<StreamMap>(Sym);
2111 for(
const Decl*
D: LookupRes) {
2112 if(
auto*VD = dyn_cast_or_null<VarDecl>(
D)) {
2113 if(
SM.isInSystemHeader(VD->getLocation()) && VD->hasExternalStorage() &&
2114VD->getType().getCanonicalType() == FilePtrTy) {
2141boolento::shouldRegisterStreamChecker(
const CheckerManager&Mgr) {
2150boolento::shouldRegisterStreamTesterChecker(
const CheckerManager&Mgr) {
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
static const VarDecl * getGlobalStreamPointerByName(const TranslationUnitDecl *TU, StringRef VarName)
static ProgramStateRef tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C, const CallEvent &Call, NonLoc SizeVal, NonLoc NMembVal)
static QualType getPointeeType(const MemRegion *R)
static std::optional< int64_t > getKnownValue(ProgramStateRef State, SVal V)
static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C, const CallEvent &Call, ArrayRef< unsigned int > EscapingArgs)
static std::optional< NonLoc > getStartIndex(SValBuilder &SVB, const MemRegion *R)
static ProgramStateRef escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call, unsigned BlockCount, const SubRegion *Buffer, QualType ElemType, int64_t StartIndex, int64_t ElementCount)
Invalidate only the requested elements instead of the whole buffer.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
QualType getBuiltinVaListType() const
Retrieve the type of the __builtin_va_list type.
QualType getFILEType() const
Retrieve the C FILE type.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const
Interprets an option's string value as a boolean.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
Stmt - This represents one statement.
The top declaration context.
ASTContext & getASTContext() const
bool isPointerType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Represents a variable declaration or definition.
Maps string IDs to AST nodes matched by parts of a matcher.
Preprocessor & getPreprocessor() override
APSIntPtr getIntValue(uint64_t X, bool isUnsigned)
const BugType & getBugType() const
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
virtual void Profile(llvm::FoldingSetNodeID &ID) const =0
virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR)=0
Return a diagnostic piece which should be associated with the given node.
BugReporter is a utility class for generating PathDiagnostics for analysis.
An immutable map from CallDescriptions to arbitrary data.
const T * lookup(const CallEvent &Call) const
A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...
Represents an abstract call to a function or method along a particular path.
const AnalyzerOptions & getAnalyzerOptions() const
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
Returns a pair of states (StTrue, StFalse) where the given condition is assumed to be true or false,...
std::pair< ProgramStateRef, ProgramStateRef > ProgramStatePair
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const LocationContext * getLocationContext() const
ExplodedNode * getFirstPred()
MemRegion - The root abstract class for all memory regions.
virtual bool doesFnIntendToHandleOwnership(const Decl *Callee, ASTContext &ACtx)=0
Heuristically guess whether the callee intended to free the resource.
const CheckerBase & Checker
virtual PathDiagnosticPieceRef emitNote(const ExplodedNode *N)=0
virtual bool hasResourceStateChanged(ProgramStateRef CallEnterState, ProgramStateRef CallExitEndState)=0
The tag upon which the TagVisitor reacts.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
void markNotInteresting(SymbolRef sym)
bool isInteresting(SymbolRef sym) const
Information about invalidation for a particular region/symbol.
void setTrait(SymbolRef Sym, InvalidationKinds IK)
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
virtual const llvm::APSInt * getKnownValue(ProgramStateRef state, SVal val)=0
Evaluates a given SVal.
BasicValueFactory & getBasicValueFactory()
NonLoc makeArrayIndex(uint64_t idx)
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
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.
QualType getConditionType() const
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.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SubRegion - A region that subsets another larger region.
MemRegionManager & getMemRegionManager() const override
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
Value representing integer constant.
__inline void unsigned int _2
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< T > findAll(const internal::Matcher< T > &Matcher)
Matches if the node or any descendant matches.
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.
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
std::optional< SVal > getPointeeVal(SVal PtrSVal, ProgramStateRef State)
std::optional< int > tryExpandAsInteger(StringRef Macro, const Preprocessor &PP)
Try to parse the value of a defined preprocessor macro.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
DiagnosticLevelMask operator&(DiagnosticLevelMask LHS, DiagnosticLevelMask RHS)
DiagnosticLevelMask operator~(DiagnosticLevelMask M)
DiagnosticLevelMask operator|(DiagnosticLevelMask LHS, DiagnosticLevelMask RHS)
bool operator!=(CanQual< T > x, CanQual< U > y)
const FunctionProtoType * T
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4