A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://clang.llvm.org/doxygen/StreamChecker_8cpp_source.html below:

clang: lib/StaticAnalyzer/Checkers/StreamChecker.cpp Source File

27#include "llvm/ADT/Sequence.h" 31using namespace clang

;

33using namespace

std::placeholders;

49struct

StreamErrorState {

57 bool

isNoError()

const

{

return

NoError && !FEof && !FError; }

58 bool

isFEof()

const

{

return

!NoError && FEof && !FError; }

59 bool

isFError()

const

{

return

!NoError && !FEof && FError; }

61 bool operator==

(

const

StreamErrorState &ES)

const

{

62 return

NoError == ES.NoError && FEof == ES.FEof && FError == ES.FError;

65 bool operator!=

(

const

StreamErrorState &ES)

const

{

return

!(*

this

== ES); }

67

StreamErrorState

operator|

(

const

StreamErrorState &

E

)

const

{

68 return

{NoError ||

E

.NoError, FEof ||

E

.FEof, FError ||

E

.FError};

71

StreamErrorState

operator&

(

const

StreamErrorState &

E

)

const

{

72 return

{NoError &&

E

.NoError, FEof &&

E

.FEof, FError &&

E

.FError};

75

StreamErrorState

operator~

()

const

{

return

{!NoError, !FEof, !FError}; }

78 operator bool

()

const

{

return

NoError || FEof || FError; }

80

LLVM_DUMP_METHOD

void dump

()

const

{ dumpToStream(llvm::errs()); }

81

LLVM_DUMP_METHOD

void

dumpToStream(llvm::raw_ostream &os)

const

{

82

os <<

"NoError: "

<< NoError <<

", FEof: "

<< FEof

83

<<

", FError: "

<< FError;

86 void

Profile(llvm::FoldingSetNodeID &ID)

const

{

87 ID

.AddBoolean(NoError);

89 ID

.AddBoolean(FError);

93const

StreamErrorState ErrorNone{

true

,

false

,

false

};

94const

StreamErrorState ErrorFEof{

false

,

true

,

false

};

95const

StreamErrorState ErrorFError{

false

,

false

,

true

};

101 const

FnDescription *LastOperation;

110

StringRef getKindStr()

const

{

117 return "OpenFailed"

;

119

llvm_unreachable(

"Unknown StreamState!"

);

124

StreamErrorState

const

ErrorState;

134 bool const

FilePositionIndeterminate =

false

;

136

StreamState(

const

FnDescription *L, KindTy S,

const

StreamErrorState &ES,

137 bool

IsFilePositionIndeterminate)

138

: LastOperation(L), State(S), ErrorState(ES),

139

FilePositionIndeterminate(IsFilePositionIndeterminate) {

140

assert((!ES.isFEof() || !IsFilePositionIndeterminate) &&

141 "FilePositionIndeterminate should be false in FEof case."

);

142

assert((State == Opened || ErrorState.isNoError()) &&

143 "ErrorState should be None in non-opened stream state."

);

146 bool

isOpened()

const

{

return

State == Opened; }

147 bool

isClosed()

const

{

return

State ==

Closed

; }

148 bool

isOpenFailed()

const

{

return

State == OpenFailed; }

153 return

LastOperation ==

X

.LastOperation && State ==

X

.State &&

154

ErrorState ==

X

.ErrorState &&

155

FilePositionIndeterminate ==

X

.FilePositionIndeterminate;

158 static

StreamState getOpened(

const

FnDescription *L,

159 const

StreamErrorState &ES = ErrorNone,

160 bool

IsFilePositionIndeterminate =

false

) {

161 return

StreamState{L, Opened, ES, IsFilePositionIndeterminate};

163 static

StreamState getClosed(

const

FnDescription *L) {

164 return

StreamState{L,

Closed

, {},

false

};

166 static

StreamState getOpenFailed(

const

FnDescription *L) {

167 return

StreamState{L, OpenFailed, {},

false

};

170

LLVM_DUMP_METHOD

void dump

()

const

{ dumpToStream(llvm::errs()); }

171

LLVM_DUMP_METHOD

void

dumpToStream(llvm::raw_ostream &os)

const

;

173 void

Profile(llvm::FoldingSetNodeID &ID)

const

{

174 ID

.AddPointer(LastOperation);

175 ID

.AddInteger(State);

176

ErrorState.Profile(ID);

177 ID

.AddBoolean(FilePositionIndeterminate);

195using

FnCheck = std::function<void(

const

StreamChecker *,

const

FnDescription *,

198using

ArgNoTy =

unsigned int

;

199static const

ArgNoTy ArgNone = std::numeric_limits<ArgNoTy>::max();

201const char

*FeofNote =

"Assuming stream reaches end-of-file here"

;

202const char

*FerrorNote =

"Assuming this stream operation fails"

;

204struct

FnDescription {

210

LLVM_DUMP_METHOD

void

StreamState::dumpToStream(llvm::raw_ostream &os)

const

{

211

os <<

"{Kind: "

<< getKindStr() <<

", Last operation: "

<< LastOperation

212

<<

", ErrorState: "

;

213

ErrorState.dumpToStream(os);

214

os <<

", FilePos: "

<< (FilePositionIndeterminate ?

"Indeterminate"

:

"OK"

)

221

assert(Desc && Desc->StreamArgNo != ArgNone &&

222 "Try to get a non-existing stream argument."

);

223 return Call

.getArgSVal(Desc->StreamArgNo);

228

assert(CE &&

"Expecting a call expression."

);

231 return C

.getSValBuilder()

232

.conjureSymbolVal(

nullptr

, CE, LCtx,

C

.blockCount())

239

State = State->BindExpr(CE,

C

.getLocationContext(), RetVal);

240

State = State->assume(RetVal,

true

);

241

assert(State &&

"Assumption on new value should not fail."

);

247

State = State->BindExpr(CE,

C

.getLocationContext(),

252inline void

assertStreamStateOpened(

const

StreamState *SS) {

253

assert(SS->isOpened() &&

"Stream is expected to be opened"

);

256class

StreamChecker :

public Checker

<check::PreCall, eval::Call,

257

check::DeadSymbols, check::PointerEscape,

258

check::ASTDecl<TranslationUnitDecl>> {

259 BugType

BT_FileNull{

this

,

"NULL stream pointer"

,

"Stream handling error"

};

260 BugType

BT_UseAfterClose{

this

,

"Closed stream"

,

"Stream handling error"

};

261 BugType

BT_UseAfterOpenFailed{

this

,

"Invalid stream"

,

262 "Stream handling error"

};

263 BugType

BT_IndeterminatePosition{

this

,

"Invalid stream state"

,

264 "Stream handling error"

};

265 BugType

BT_IllegalWhence{

this

,

"Illegal whence argument"

,

266 "Stream handling error"

};

267 BugType

BT_StreamEof{

this

,

"Stream already in EOF"

,

"Stream handling error"

};

268 BugType

BT_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())

328

BR.markNotInteresting(StreamSym);

331 if

(&BR.

getBugType

() == this->getBT_IndeterminatePosition()) {

332

BR.markNotInteresting(StreamSym);

341 bool

TestMode =

false

;

344 bool

PedanticMode =

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,

361

std::bind(&StreamChecker::evalFreadFwrite, _1,

_2

, _3, _4,

true

), 3}},

362

{{CDM::CLibrary, {

"fwrite"

}, 4},

363

{&StreamChecker::preWrite,

364

std::bind(&StreamChecker::evalFreadFwrite, _1,

_2

, _3, _4,

false

), 3}},

365

{{CDM::CLibrary, {

"fgetc"

}, 1},

366

{&StreamChecker::preRead,

367

std::bind(&StreamChecker::evalFgetx, _1,

_2

, _3, _4,

true

), 0}},

368

{{CDM::CLibrary, {

"fgets"

}, 3},

369

{&StreamChecker::preRead,

370

std::bind(&StreamChecker::evalFgetx, _1,

_2

, _3, _4,

false

), 2}},

371

{{CDM::CLibrary, {

"getc"

}, 1},

372

{&StreamChecker::preRead,

373

std::bind(&StreamChecker::evalFgetx, _1,

_2

, _3, _4,

true

), 0}},

374

{{CDM::CLibrary, {

"fputc"

}, 2},

375

{&StreamChecker::preWrite,

376

std::bind(&StreamChecker::evalFputx, _1,

_2

, _3, _4,

true

), 1}},

377

{{CDM::CLibrary, {

"fputs"

}, 2},

378

{&StreamChecker::preWrite,

379

std::bind(&StreamChecker::evalFputx, _1,

_2

, _3, _4,

false

), 1}},

380

{{CDM::CLibrary, {

"putc"

}, 2},

381

{&StreamChecker::preWrite,

382

std::bind(&StreamChecker::evalFputx, _1,

_2

, _3, _4,

true

), 1}},

383

{{CDM::CLibrary, {

"fprintf"

}},

384

{&StreamChecker::preWrite,

385

std::bind(&StreamChecker::evalFprintf, _1,

_2

, _3, _4), 0}},

386

{{CDM::CLibrary, {

"vfprintf"

}, 3},

387

{&StreamChecker::preWrite,

388

std::bind(&StreamChecker::evalFprintf, _1,

_2

, _3, _4), 0}},

389

{{CDM::CLibrary, {

"fscanf"

}},

390

{&StreamChecker::preRead,

391

std::bind(&StreamChecker::evalFscanf, _1,

_2

, _3, _4), 0}},

392

{{CDM::CLibrary, {

"vfscanf"

}, 3},

393

{&StreamChecker::preRead,

394

std::bind(&StreamChecker::evalFscanf, _1,

_2

, _3, _4), 0}},

395

{{CDM::CLibrary, {

"ungetc"

}, 2},

396

{&StreamChecker::preWrite,

397

std::bind(&StreamChecker::evalUngetc, _1,

_2

, _3, _4), 1}},

398

{{CDM::CLibrary, {

"getdelim"

}, 4},

399

{&StreamChecker::preRead,

400

std::bind(&StreamChecker::evalGetdelim, _1,

_2

, _3, _4), 3}},

401

{{CDM::CLibrary, {

"getline"

}, 3},

402

{&StreamChecker::preRead,

403

std::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,

424

std::bind(&StreamChecker::evalFeofFerror, _1,

_2

, _3, _4, ErrorFEof),

426

{{CDM::CLibrary, {

"ferror"

}, 1},

427

{&StreamChecker::preDefault,

428

std::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},

437

std::bind(&StreamChecker::evalSetFeofFerror, _1,

_2

, _3, _4, ErrorFEof,

440

{{CDM::SimpleFunc, {

"StreamTesterChecker_make_ferror_stream"

}, 1},

442

std::bind(&StreamChecker::evalSetFeofFerror, _1,

_2

, _3, _4,

443

ErrorFError,

false

),

446

{

"StreamTesterChecker_make_ferror_indeterminate_stream"

},

449

std::bind(&StreamChecker::evalSetFeofFerror, _1,

_2

, _3, _4,

455 mutable

std::optional<int> EofVal;

457 mutable int

SeekSetVal = 0;

459 mutable int

SeekCurVal = 1;

461 mutable int

SeekEndVal = 2;

465 mutable const VarDecl

*StdinDecl =

nullptr

;

466 mutable const VarDecl

*StdoutDecl =

nullptr

;

467 mutable const VarDecl

*StderrDecl =

nullptr

;

469 void

evalFopen(

const

FnDescription *Desc,

const CallEvent

&

Call

,

472 void

preFreopen(

const

FnDescription *Desc,

const CallEvent

&

Call

,

474 void

evalFreopen(

const

FnDescription *Desc,

const CallEvent

&

Call

,

477 void

evalFclose(

const

FnDescription *Desc,

const CallEvent

&

Call

,

480 void

preRead(

const

FnDescription *Desc,

const CallEvent

&

Call

,

483 void

preWrite(

const

FnDescription *Desc,

const CallEvent

&

Call

,

486 void

evalFreadFwrite(

const

FnDescription *Desc,

const CallEvent

&

Call

,

489 void

evalFgetx(

const

FnDescription *Desc,

const CallEvent

&

Call

,

492 void

evalFputx(

const

FnDescription *Desc,

const CallEvent

&

Call

,

495 void

evalFprintf(

const

FnDescription *Desc,

const CallEvent

&

Call

,

498 void

evalFscanf(

const

FnDescription *Desc,

const CallEvent

&

Call

,

501 void

evalUngetc(

const

FnDescription *Desc,

const CallEvent

&

Call

,

504 void

evalGetdelim(

const

FnDescription *Desc,

const CallEvent

&

Call

,

507 void

preFseek(

const

FnDescription *Desc,

const CallEvent

&

Call

,

509 void

evalFseek(

const

FnDescription *Desc,

const CallEvent

&

Call

,

512 void

evalFgetpos(

const

FnDescription *Desc,

const CallEvent

&

Call

,

515 void

evalFsetpos(

const

FnDescription *Desc,

const CallEvent

&

Call

,

518 void

evalFtell(

const

FnDescription *Desc,

const CallEvent

&

Call

,

521 void

evalRewind(

const

FnDescription *Desc,

const CallEvent

&

Call

,

524 void

preDefault(

const

FnDescription *Desc,

const CallEvent

&

Call

,

527 void

evalClearerr(

const

FnDescription *Desc,

const CallEvent

&

Call

,

530 void

evalFeofFerror(

const

FnDescription *Desc,

const CallEvent

&

Call

,

532 const

StreamErrorState &ErrorKind)

const

;

534 void

evalSetFeofFerror(

const

FnDescription *Desc,

const CallEvent

&

Call

,

536 bool

Indeterminate)

const

;

538 void

preFflush(

const

FnDescription *Desc,

const CallEvent

&

Call

,

541 void

evalFflush(

const

FnDescription *Desc,

const CallEvent

&

Call

,

544 void

evalFileno(

const

FnDescription *Desc,

const CallEvent

&

Call

,

593 const

FnDescription *lookupFn(

const CallEvent

&

Call

)

const

{

596 for

(

auto

*

P

:

Call

.parameters()) {

599 T

.getCanonicalType() != VaListType)

609 const

std::string &Message)

const

{

610 return C

.getNoteTag([

this

, StreamSym,

627

SeekSetVal = *OptInt;

629

SeekEndVal = *OptInt;

631

SeekCurVal = *OptInt;

641struct

StreamOperationEvaluator {

646 const

StreamState *SS =

nullptr

;

648

StreamErrorState NewES;

651

: SVB(

C

.getSValBuilder()), ACtx(

C

.getASTContext()) {

657

StreamSym = getStreamArg(Desc,

Call

).getAsSymbol();

660

SS = State->get<StreamMap>(StreamSym);

663

NewES = SS->ErrorState;

664

CE = dyn_cast_or_null<CallExpr>(

Call

.getOriginExpr());

668

assertStreamStateOpened(SS);

673 bool

isStreamEof()

const

{

return

SS->ErrorState == ErrorFEof; }

680 const

StreamState &NewSS) {

681

NewES = NewSS.ErrorState;

682 return

State->set<StreamMap>(StreamSym, NewSS);

687 return

State->BindExpr(CE,

C

.getLocationContext(), RetVal);

692 return

State->BindExpr(CE,

C

.getLocationContext(),

698 return

State->BindExpr(CE,

C

.getLocationContext(), Val);

703 return

State->BindExpr(CE,

C

.getLocationContext(),

704 C

.getSValBuilder().makeNullWithType(CE->

getType

()));

714 return

State->assume(*Cond,

true

);

720

State = State->BindExpr(CE,

C

.getLocationContext(), RetVal);

721 return C

.getConstraintManager().assumeDual(State, RetVal);

725 bool

SetFeof = NewES.FEof && !SS->ErrorState.FEof;

726 bool

SetFerror = NewES.FError && !SS->ErrorState.FError;

727 if

(SetFeof && !SetFerror)

728 return

Ch->constructSetEofNoteTag(

C

, StreamSym);

729 if

(!SetFeof && SetFerror)

730 return

Ch->constructSetErrorNoteTag(

C

, StreamSym);

731 if

(SetFeof && SetFerror)

732 return

Ch->constructSetEofOrErrorNoteTag(

C

, StreamSym);

751 bool

isClosingCallAsWritten(

const CallExpr

&

Call

)

const

{

752 const auto

*StreamChk =

static_cast<const

StreamChecker *

>

(&

Checker

);

753 return

StreamChk->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 return

CallEnterState->get<StreamMap>(

Sym

) !=

785

CallExitEndState->get<StreamMap>(Sym);

791

N->

getState

()->getStateManager().getContext().getSourceManager());

792 return

std::make_shared<PathDiagnosticEventPiece>(

793

L,

"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 return

Int->tryExtValue();

837 unsigned

BlockCount,

const SubRegion

*Buffer,

838 QualType

ElemType, int64_t StartIndex,

839

int64_t ElementCount) {

840 constexpr auto

DoNotInvalidateSuperRegion =

841

RegionAndSymbolInvalidationTraits::InvalidationKinds::

842

TK_DoNotInvalidateSuperRegion;

845 const ASTContext

&Ctx = State->getStateManager().getContext();

846 SValBuilder

&SVB = State->getStateManager().getSValBuilder();

850

EscapingVals.reserve(ElementCount);

853 for

(

auto

Idx : llvm::seq(StartIndex, StartIndex + ElementCount)) {

855 const auto

*Element =

856

RegionManager.getElementRegion(ElemType, Index, Buffer, Ctx);

858

ITraits.

setTrait

(Element, DoNotInvalidateSuperRegion);

860 return

State->invalidateRegions(

861

EscapingVals,

Call

.getOriginExpr(), BlockCount, LCtx,

863 nullptr

, &

Call

, &ITraits);

869 auto

GetArgSVal = [&

Call

](

int

Idx) {

return Call

.getArgSVal(Idx); };

870 auto

EscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));

871

State = State->invalidateRegions(EscapingVals,

Call

.getOriginExpr(),

872 C

.blockCount(),

C

.getLocationContext(),

884 const

FnDescription *Desc = lookupFn(

Call

);

885 if

(!Desc || !Desc->PreFn)

888

Desc->PreFn(

this

, Desc,

Call

,

C

);

892 const

FnDescription *Desc = lookupFn(

Call

);

893 if

(!Desc && TestMode)

895 if

(!Desc || !Desc->EvalFn)

898

Desc->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 SVal

VarValue = State->getSVal(StoreMgr.getLValueVar(Var, LCtx));

915

.castAs<DefinedOrUnknownSVal>();

916 return

State->assume(NoAliasState,

true

);

920

State = assumeRetNE(State, StdinDecl);

921

State = assumeRetNE(State, StdoutDecl);

922

State = assumeRetNE(State, StderrDecl);

927void

StreamChecker::evalFopen(

const

FnDescription *Desc,

const CallEvent

&

Call

,

930 const CallExpr

*CE = dyn_cast_or_null<CallExpr>(

Call

.getOriginExpr());

936

assert(RetSym &&

"RetVal must be a symbol here."

);

938

State = State->BindExpr(CE,

C

.getLocationContext(), RetVal);

943

std::tie(StateNotNull, StateNull) =

944 C

.getConstraintManager().assumeDual(State, RetVal);

947

StateNotNull->set<StreamMap>(RetSym, StreamState::getOpened(Desc));

949

StateNull->set<StreamMap>(RetSym, StreamState::getOpenFailed(Desc));

951

StateNotNull = assumeNoAliasingWithStdStreams(StateNotNull, RetVal,

C

);

953 C

.addTransition(StateNotNull,

954

constructLeakNoteTag(

C

, RetSym,

"Stream opened here"

));

955 C

.addTransition(StateNull);

958void

StreamChecker::preFreopen(

const

FnDescription *Desc,

const CallEvent

&

Call

,

962

State = ensureStreamNonNull(getStreamArg(Desc,

Call

),

963 Call

.getArgExpr(Desc->StreamArgNo),

C

, State);

967 C

.addTransition(State);

970void

StreamChecker::evalFreopen(

const

FnDescription *Desc,

975 auto

*CE = dyn_cast_or_null<CallExpr>(

Call

.getOriginExpr());

979

std::optional<DefinedSVal> StreamVal =

984 SymbolRef

StreamSym = StreamVal->getAsSymbol();

991 if

(!State->get<StreamMap>(StreamSym))

999

State->BindExpr(CE,

C

.getLocationContext(), *StreamVal);

1003

State->BindExpr(CE,

C

.getLocationContext(),

1004 C

.getSValBuilder().makeNullWithType(CE->

getType

()));

1007

StateRetNotNull->set<StreamMap>(StreamSym, StreamState::getOpened(Desc));

1009

StateRetNull->set<StreamMap>(StreamSym, StreamState::getOpenFailed(Desc));

1011 C

.addTransition(StateRetNotNull,

1012

constructLeakNoteTag(

C

, StreamSym,

"Stream reopened here"

));

1013 C

.addTransition(StateRetNull);

1016void

StreamChecker::evalFclose(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1019

StreamOperationEvaluator

E

(

C

);

1020 if

(!

E

.Init(Desc,

Call

,

C

, State))

1026

State =

E

.setStreamState(State, StreamState::getClosed(Desc));

1029 C

.addTransition(

E

.bindReturnValue(State,

C

, 0));

1030 C

.addTransition(

E

.bindReturnValue(State,

C

, *EofVal));

1033void

StreamChecker::preRead(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1036 SVal

StreamVal = getStreamArg(Desc,

Call

);

1037

State = ensureStreamNonNull(StreamVal,

Call

.getArgExpr(Desc->StreamArgNo),

C

,

1041

State = ensureStreamOpened(StreamVal,

C

, State);

1044

State = ensureNoFilePositionIndeterminate(StreamVal,

C

, State);

1049 if

(Sym && State->get<StreamMap>(Sym)) {

1050 const

StreamState *SS = State->get<StreamMap>(Sym);

1051 if

(SS->ErrorState & ErrorFEof)

1052

reportFEofWarning(Sym,

C

, State);

1054 C

.addTransition(State);

1058void

StreamChecker::preWrite(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1061 SVal

StreamVal = getStreamArg(Desc,

Call

);

1062

State = ensureStreamNonNull(StreamVal,

Call

.getArgExpr(Desc->StreamArgNo),

C

,

1066

State = ensureStreamOpened(StreamVal,

C

, State);

1069

State = ensureNoFilePositionIndeterminate(StreamVal,

C

, State);

1073 C

.addTransition(State);

1079 if

(

const auto

*ER = dyn_cast<ElementRegion>(R))

1080 return

ER->getElementType();

1081 if

(

const auto

*TR = dyn_cast<TypedValueRegion>(R))

1082 return

TR->getValueType();

1083 if

(

const auto

*SR = dyn_cast<SymbolicRegion>(R))

1084 return

SR->getPointeeStaticType();

1091 return

std::nullopt;

1093 auto

Zero = [&SVB] {

1098 if

(

const auto

*ER = dyn_cast<ElementRegion>(R))

1099 return

ER->getIndex();

1100 if

(isa<TypedValueRegion>(R))

1102 if

(isa<SymbolicRegion>(R))

1104 return

std::nullopt;

1112 const auto

*Buffer =

1113

dyn_cast_or_null<SubRegion>(

Call

.getArgSVal(0).getAsRegion());

1117

std::optional<SVal> StartElementIndex =

1121 if

(

const auto

*ER = dyn_cast_or_null<ElementRegion>(Buffer))

1122

Buffer = dyn_cast<SubRegion>(ER->getSuperRegion());

1124

std::optional<int64_t> CountVal =

getKnownValue

(State, NMembVal);

1125

std::optional<int64_t> Size =

getKnownValue

(State, SizeVal);

1126

std::optional<int64_t> StartIndexVal =

1129 if

(!ElemTy.

isNull

() && CountVal && Size && StartIndexVal) {

1130

int64_t NumBytesRead = Size.value() * CountVal.value();

1132 if

(ElemSizeInChars == 0 || NumBytesRead < 0)

1135 bool

IncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0;

1136

int64_t NumCompleteOrIncompleteElementsRead =

1137

NumBytesRead / ElemSizeInChars + IncompleteLastElement;

1139 constexpr int

MaxInvalidatedElementsLimit = 64;

1140 if

(NumCompleteOrIncompleteElementsRead <= MaxInvalidatedElementsLimit) {

1142

ElemTy, *StartIndexVal,

1143

NumCompleteOrIncompleteElementsRead);

1149void

StreamChecker::evalFreadFwrite(

const

FnDescription *Desc,

1151 bool

IsFread)

const

{

1153

StreamOperationEvaluator

E

(

C

);

1154 if

(!

E

.Init(Desc,

Call

,

C

, State))

1157

std::optional<NonLoc> SizeVal =

Call

.getArgSVal(1).getAs<

NonLoc

>();

1160

std::optional<NonLoc> NMembVal =

Call

.getArgSVal(2).getAs<

NonLoc

>();

1169 if

(State->isNull(*SizeVal).isConstrainedTrue() ||

1170

State->isNull(*NMembVal).isConstrainedTrue()) {

1173 C

.addTransition(

E

.bindReturnValue(State,

C

, 0));

1179 if

(IsFread && !

E

.isStreamEof()) {

1183

State,

C

,

Call

, *SizeVal, *NMembVal);

1185

InvalidatedState ? InvalidatedState :

escapeArgs

(State,

C

,

Call

, {0});

1190 if

(!IsFread || !

E

.isStreamEof()) {

1192

State->BindExpr(

E

.CE,

C

.getLocationContext(), *NMembVal);

1194 E

.setStreamState(StateNotFailed, StreamState::getOpened(Desc));

1195 C

.addTransition(StateNotFailed);

1200 if

(!IsFread && !PedanticMode)

1205

State->BindExpr(

E

.CE,

C

.getLocationContext(), RetVal);

1206

StateFailed =

E

.assumeBinOpNN(StateFailed, BO_LT, RetVal, *NMembVal);

1210

StreamErrorState NewES;

1212

NewES =

E

.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;

1214

NewES = ErrorFError;

1217

StateFailed =

E

.setStreamState(

1218

StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));

1219 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1222void

StreamChecker::evalFgetx(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1228

StreamOperationEvaluator

E

(

C

);

1229 if

(!

E

.Init(Desc,

Call

,

C

, State))

1232 if

(!

E

.isStreamEof()) {

1240

State->BindExpr(

E

.CE,

C

.getLocationContext(), RetVal);

1243

StateNotFailed = 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);

1253

std::optional<DefinedSVal> GetBuf =

1258

State->BindExpr(

E

.CE,

C

.getLocationContext(), *GetBuf);

1260 E

.setStreamState(StateNotFailed, StreamState::getOpened(Desc));

1261 C

.addTransition(StateNotFailed);

1268

StateFailed =

E

.bindReturnValue(State,

C

, *EofVal);

1270

StateFailed =

E

.bindNullReturnValue(State,

C

);

1274

StreamErrorState NewES =

1275 E

.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;

1276

StateFailed =

E

.setStreamState(

1277

StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));

1278 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1281void

StreamChecker::evalFputx(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1287

StreamOperationEvaluator

E

(

C

);

1288 if

(!

E

.Init(Desc,

Call

,

C

, State))

1293

std::optional<NonLoc> PutVal =

Call

.getArgSVal(0).getAs<

NonLoc

>();

1297

State->BindExpr(

E

.CE,

C

.getLocationContext(), *PutVal);

1299 E

.setStreamState(StateNotFailed, StreamState::getOpened(Desc));

1300 C

.addTransition(StateNotFailed);

1305

State->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);

1321

StateFailed =

E

.setStreamState(

1322

StateFailed, StreamState::getOpened(Desc, ErrorFError,

true

));

1323 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1326void

StreamChecker::evalFprintf(

const

FnDescription *Desc,

1329 if

(

Call

.getNumArgs() < 2)

1333

StreamOperationEvaluator

E

(

C

);

1334 if

(!

E

.Init(Desc,

Call

,

C

, State))

1338

State = 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>();

1347

std::tie(StateNotFailed, StateFailed) = State->assume(*Cond);

1350 E

.setStreamState(StateNotFailed, StreamState::getOpened(Desc));

1351 C

.addTransition(StateNotFailed);

1358

StateFailed =

E

.setStreamState(

1359

StateFailed, StreamState::getOpened(Desc, ErrorFError,

true

));

1360 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1363void

StreamChecker::evalFscanf(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1365 if

(

Call

.getNumArgs() < 2)

1369

StreamOperationEvaluator

E

(

C

);

1370 if

(!

E

.Init(Desc,

Call

,

C

, State))

1381 if

(!

E

.isStreamEof()) {

1384

State->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

(

auto

EscArg : llvm::seq(2u,

Call

.getNumArgs()))

1394

EscArgs.push_back(EscArg);

1399 C

.addTransition(StateNotFailed);

1409

StreamErrorState NewES =

1410 E

.isStreamEof() ? ErrorFEof : ErrorNone | ErrorFEof | ErrorFError;

1411

StateFailed =

E

.setStreamState(

1412

StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));

1413 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1416void

StreamChecker::evalUngetc(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1419

StreamOperationEvaluator

E

(

C

);

1420 if

(!

E

.Init(Desc,

Call

,

C

, State))

1424

std::optional<NonLoc> PutVal =

Call

.getArgSVal(0).getAs<

NonLoc

>();

1429 E

.setStreamState(StateNotFailed, StreamState::getOpened(Desc));

1430 C

.addTransition(StateNotFailed);

1439

StateFailed =

E

.setStreamState(StateFailed, StreamState::getOpened(Desc));

1440 C

.addTransition(StateFailed);

1443void

StreamChecker::evalGetdelim(

const

FnDescription *Desc,

1447

StreamOperationEvaluator

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))

1471

StateNotFailed = StateNotFailed->assume(

1476 SVal

SizePtrSval =

Call

.getArgSVal(1);

1478 if

(NVal && isa<NonLoc>(*NVal)) {

1479

StateNotFailed =

E

.assumeBinOpNN(StateNotFailed, BO_GT,

1480

NVal->castAs<

NonLoc

>(), RetVal);

1481

StateNotFailed =

E

.bindReturnValue(StateNotFailed,

C

, RetVal);

1483 if

(!StateNotFailed)

1485 C

.addTransition(StateNotFailed);

1492

StreamErrorState NewES =

1493 E

.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;

1494

StateFailed =

E

.setStreamState(

1495

StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));

1498

StateFailed = StateFailed->bindLoc(*NewLinePtr,

UndefinedVal

(),

1499 C

.getLocationContext());

1500 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1503void

StreamChecker::preFseek(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1506 SVal

StreamVal = getStreamArg(Desc,

Call

);

1507

State = ensureStreamNonNull(StreamVal,

Call

.getArgExpr(Desc->StreamArgNo),

C

,

1511

State = ensureStreamOpened(StreamVal,

C

, State);

1514

State = ensureFseekWhenceCorrect(

Call

.getArgSVal(2),

C

, State);

1518 C

.addTransition(State);

1521void

StreamChecker::evalFseek(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1524

StreamOperationEvaluator

E

(

C

);

1525 if

(!

E

.Init(Desc,

Call

,

C

, State))

1532 E

.setStreamState(StateNotFailed, StreamState::getOpened(Desc));

1533 C

.addTransition(StateNotFailed);

1545

StateFailed =

E

.setStreamState(

1546

StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError,

true

));

1547 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1550void

StreamChecker::evalFgetpos(

const

FnDescription *Desc,

1554

StreamOperationEvaluator

E

(

C

);

1555 if

(!

E

.Init(Desc,

Call

,

C

, State))

1559

std::tie(StateFailed, StateNotFailed) =

E

.makeRetValAndAssumeDual(State,

C

);

1565 C

.addTransition(StateNotFailed);

1566 C

.addTransition(StateFailed);

1569void

StreamChecker::evalFsetpos(

const

FnDescription *Desc,

1573

StreamOperationEvaluator

E

(

C

);

1574 if

(!

E

.Init(Desc,

Call

,

C

, State))

1578

std::tie(StateFailed, StateNotFailed) =

E

.makeRetValAndAssumeDual(State,

C

);

1580

StateNotFailed =

E

.setStreamState(

1581

StateNotFailed, StreamState::getOpened(Desc, ErrorNone,

false

));

1582 C

.addTransition(StateNotFailed);

1591

StateFailed =

E

.setStreamState(

1592

StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError,

true

));

1594 C

.addTransition(StateFailed,

E

.getFailureNoteTag(

this

,

C

));

1597void

StreamChecker::evalFtell(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1600

StreamOperationEvaluator

E

(

C

);

1601 if

(!

E

.Init(Desc,

Call

,

C

, State))

1606

State->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);

1621void

StreamChecker::evalRewind(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1624

StreamOperationEvaluator

E

(

C

);

1625 if

(!

E

.Init(Desc,

Call

,

C

, State))

1629 E

.setStreamState(State, StreamState::getOpened(Desc, ErrorNone,

false

));

1630 C

.addTransition(State);

1633void

StreamChecker::preFflush(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1636 SVal

StreamVal = getStreamArg(Desc,

Call

);

1642

std::tie(StateNotNull, StateNull) =

1643 C

.getConstraintManager().assumeDual(State, *Stream);

1644 if

(StateNotNull && !StateNull)

1645

ensureStreamOpened(StreamVal,

C

, StateNotNull);

1648void

StreamChecker::evalFflush(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1651 SVal

StreamVal = getStreamArg(Desc,

Call

);

1658

std::tie(StateNotNull, StateNull) =

1659 C

.getConstraintManager().assumeDual(State, *Stream);

1660 if

(StateNotNull && StateNull)

1662 if

(StateNotNull && !StateNull)

1663

State = StateNotNull;

1667 const CallExpr

*CE = dyn_cast_or_null<CallExpr>(

Call

.getOriginExpr());

1676 auto

ClearErrorInNotFailed = [&StateNotFailed, Desc](

SymbolRef

Sym,

1677 const

StreamState *SS) {

1678 if

(SS->ErrorState & ErrorFError) {

1679

StreamErrorState NewES =

1680

(SS->ErrorState & ErrorFEof) ? ErrorFEof : ErrorNone;

1681

StreamState NewSS = StreamState::getOpened(Desc, NewES,

false

);

1682

StateNotFailed = StateNotFailed->set<StreamMap>(Sym, NewSS);

1686 if

(StateNotNull && !StateNull) {

1689 const

StreamState *SS = State->get<StreamMap>(StreamSym);

1691

assert(SS->isOpened() &&

"Stream is expected to be opened"

);

1692

ClearErrorInNotFailed(StreamSym, SS);

1698 const

StreamMapTy &Map = StateNotFailed->get<StreamMap>();

1699 for

(

const auto

&I : Map) {

1701 const

StreamState &SS = I.second;

1703

ClearErrorInNotFailed(Sym, &SS);

1707 C

.addTransition(StateNotFailed);

1708 C

.addTransition(StateFailed);

1711void

StreamChecker::evalClearerr(

const

FnDescription *Desc,

1715

StreamOperationEvaluator

E

(

C

);

1716 if

(!

E

.Init(Desc,

Call

,

C

, State))

1720

State =

E

.setStreamState(

1722

StreamState::getOpened(Desc, ErrorNone,

E

.SS->FilePositionIndeterminate));

1723 C

.addTransition(State);

1726void

StreamChecker::evalFeofFerror(

const

FnDescription *Desc,

1728 const

StreamErrorState &ErrorKind)

const

{

1730

StreamOperationEvaluator

E

(

C

);

1731 if

(!

E

.Init(Desc,

Call

,

C

, State))

1734 if

(

E

.SS->ErrorState & ErrorKind) {

1739 C

.addTransition(

E

.setStreamState(

1740

TrueState, StreamState::getOpened(Desc, ErrorKind,

1741 E

.SS->FilePositionIndeterminate &&

1742

!ErrorKind.isFEof())));

1744 if

(StreamErrorState NewES =

E

.SS->ErrorState & (~ErrorKind)) {

1749 C

.addTransition(

E

.setStreamState(

1751

StreamState::getOpened(

1752

Desc, NewES,

E

.SS->FilePositionIndeterminate && !NewES.isFEof())));

1756void

StreamChecker::evalFileno(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1768

StreamOperationEvaluator

E

(

C

);

1769 if

(!

E

.Init(Desc,

Call

,

C

, State))

1773

State = State->BindExpr(

E

.CE,

C

.getLocationContext(), RetVal);

1774

State =

E

.assumeBinOpNN(State, BO_GE, RetVal,

E

.getZeroVal(

Call

));

1778 C

.addTransition(State);

1781void

StreamChecker::preDefault(

const

FnDescription *Desc,

const CallEvent

&

Call

,

1784 SVal

StreamVal = getStreamArg(Desc,

Call

);

1785

State = ensureStreamNonNull(StreamVal,

Call

.getArgExpr(Desc->StreamArgNo),

C

,

1789

State = ensureStreamOpened(StreamVal,

C

, State);

1793 C

.addTransition(State);

1796void

StreamChecker::evalSetFeofFerror(

const

FnDescription *Desc,

1798 const

StreamErrorState &ErrorKind,

1799 bool

Indeterminate)

const

{

1801 SymbolRef

StreamSym = getStreamArg(Desc,

Call

).getAsSymbol();

1802

assert(StreamSym &&

"Operation not permitted on non-symbolic stream value."

);

1803 const

StreamState *SS = State->get<StreamMap>(StreamSym);

1804

assert(SS &&

"Stream should be tracked by the checker."

);

1805

State = State->set<StreamMap>(

1807

StreamState::getOpened(SS->LastOperation, ErrorKind, Indeterminate));

1808 C

.addTransition(State);

1812

StreamChecker::ensureStreamNonNull(

SVal

StreamVal,

const Expr

*StreamE,

1822

std::tie(StateNotNull, StateNull) = CM.

assumeDual

(State, *Stream);

1824 if

(!StateNotNull && StateNull) {

1826 auto

R = std::make_unique<PathSensitiveBugReport>(

1827

BT_FileNull,

"Stream pointer might be NULL."

, N);

1830 C

.emitReport(std::move(R));

1835 return

StateNotNull;

1841 bool

Satisfied =

false

;

1844 explicit

StreamClosedVisitor(

SymbolRef

StreamSym) : StreamSym(StreamSym) {}

1846 static void

*getTag() {

1851 void Profile

(llvm::FoldingSetNodeID &ID)

const override

{

1852 ID

.AddPointer(getTag());

1853 ID

.AddPointer(StreamSym);

1861 const

StreamState *PredSS =

1863 if

(PredSS && PredSS->isClosed())

1872

llvm::StringLiteral Msg =

"Stream is closed here"

;

1873 return

std::make_shared<PathDiagnosticEventPiece>(Pos, Msg);

1885 const

StreamState *SS = State->get<StreamMap>(Sym);

1889 if

(SS->isClosed()) {

1893 auto

R = std::make_unique<PathSensitiveBugReport>(

1894

BT_UseAfterClose,

"Use of a stream that might be already closed"

, N);

1895

R->addVisitor<StreamClosedVisitor>(Sym);

1896 C

.emitReport(std::move(R));

1903 if

(SS->isOpenFailed()) {

1910 C

.emitReport(std::make_unique<PathSensitiveBugReport>(

1911

BT_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 const

StreamState *SS = State->get<StreamMap>(Sym);

1938

assert(SS->isOpened() &&

"First ensure that stream is opened."

);

1940 if

(SS->FilePositionIndeterminate) {

1941 if

(SS->ErrorState & ErrorFEof) {

1949 auto

R = std::make_unique<PathSensitiveBugReport>(

1950

BT_IndeterminatePosition, BugMessage, N);

1951

R->markInteresting(Sym);

1952 C

.emitReport(std::move(R));

1953 return

State->set<StreamMap>(

1954

Sym, StreamState::getOpened(SS->LastOperation, ErrorFEof,

false

));

1960 auto

R = std::make_unique<PathSensitiveBugReport>(

1961

BT_IndeterminatePosition, BugMessage, N);

1962

R->markInteresting(Sym);

1963 C

.emitReport(std::move(R));

1975

std::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 auto

R = std::make_unique<PathSensitiveBugReport>(

2001 "Read function called when stream is in EOF state. " 2002 "Function has no effect."

,

2004

R->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

);

2031

assert(StreamOpenNode &&

"Could not find place of stream opening."

);

2036

StreamStmt,

C

.getSourceManager(),

2039

std::unique_ptr<PathSensitiveBugReport> R =

2040

std::make_unique<PathSensitiveBugReport>(

2042 "Opened stream never closed. Potential resource leak."

, Err,

2043

LocUsedForUniqueing,

2045

R->markInteresting(LeakSym);

2046

R->addVisitor<NoStreamStateChangeVisitor>(LeakSym,

this

);

2047 C

.emitReport(std::move(R));

2053void

StreamChecker::checkDeadSymbols(

SymbolReaper

&SymReaper,

2059 const

StreamMapTy &Map = State->get<StreamMap>();

2060 for

(

const auto

&I : Map) {

2062 const

StreamState &SS = I.second;

2063 if

(!SymReaper.

isDead

(Sym))

2066

LeakedSyms.push_back(Sym);

2067

State = State->remove<StreamMap>(Sym);

2071 if

(!LeakedSyms.empty())

2072

N = reportLeaks(LeakedSyms,

C

, N);

2074 C

.addTransition(State, N);

2094

State = 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() &&

2114

VD->getType().getCanonicalType() == FilePtrTy) {

2141bool

ento::shouldRegisterStreamChecker(

const CheckerManager

&Mgr) {

2150bool

ento::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