A RetroSearch Logo

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

Search Query:

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

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

103#include "llvm/ADT/StringExtras.h" 106using namespace clang

;

111static const

StringRef HandleTypeName =

"zx_handle_t"

;

112static const

StringRef ErrorTypeName =

"zx_status_t"

;

116 enum class Kind

{ MaybeAllocated, Allocated, Released, Escaped, Unowned } K;

118

HandleState(Kind K,

SymbolRef

ErrorSym) : K(K), ErrorSym(ErrorSym) {}

122 return

K ==

Other

.K && ErrorSym ==

Other

.ErrorSym;

124 bool

isAllocated()

const

{

return

K == Kind::Allocated; }

125 bool

maybeAllocated()

const

{

return

K == Kind::MaybeAllocated; }

126 bool isReleased

()

const

{

return

K == Kind::Released; }

127 bool

isEscaped()

const

{

return

K == Kind::Escaped; }

128 bool

isUnowned()

const

{

return

K == Kind::Unowned; }

130 static

HandleState getMaybeAllocated(

SymbolRef

ErrorSym) {

131 return

HandleState(Kind::MaybeAllocated, ErrorSym);

133 static

HandleState getAllocated(

ProgramStateRef

State, HandleState S) {

134

assert(S.maybeAllocated());

135

assert(State->getConstraintManager()

136

.isNull(State, S.getErrorSym())

138 return

HandleState(Kind::Allocated,

nullptr

);

140 static

HandleState getReleased() {

141 return

HandleState(Kind::Released,

nullptr

);

143 static

HandleState getEscaped() {

144 return

HandleState(Kind::Escaped,

nullptr

);

146 static

HandleState getUnowned() {

147 return

HandleState(Kind::Unowned,

nullptr

);

150 SymbolRef

getErrorSym()

const

{

return

ErrorSym; }

152 void

Profile(llvm::FoldingSetNodeID &ID)

const

{

153 ID

.AddInteger(

static_cast<int>

(K));

154 ID

.AddPointer(ErrorSym);

157

LLVM_DUMP_METHOD

void dump

(raw_ostream &OS)

const

{

163 CASE

(Kind::MaybeAllocated)

164 CASE

(Kind::Allocated)

165 CASE

(Kind::Released)

170

OS <<

" ErrorSym: "

;

175

LLVM_DUMP_METHOD

void dump

()

const

{

dump

(llvm::errs()); }

178template

<

typename

Attr>

static bool

hasFuchsiaAttr(

const Decl

*

D

) {

182template

<

typename

Attr>

static bool

hasFuchsiaUnownedAttr(

const Decl

*

D

) {

184 D

->

getAttr

<

Attr

>()->getHandleType() ==

"FuchsiaUnowned"

;

187class

FuchsiaHandleChecker

188

:

public Checker

<check::PostCall, check::PreCall, check::DeadSymbols,

189

check::PointerEscape, eval::Assume> {

190 BugType

LeakBugType{

this

,

"Fuchsia handle leak"

,

"Fuchsia Handle Error"

,

192 BugType

DoubleReleaseBugType{

this

,

"Fuchsia handle double release"

,

193 "Fuchsia Handle Error"

};

194 BugType

UseAfterReleaseBugType{

this

,

"Fuchsia handle use after release"

,

195 "Fuchsia Handle Error"

};

197 this

,

"Fuchsia handle release of unowned handle"

,

"Fuchsia Handle Error"

};

204 bool

Assumption)

const

;

224

StringRef Msg)

const

;

227 const char

*Sep)

const override

;

238 if

(!State->get<HStateMap>(Sym))

239

N = N->getFirstPred();

243

State = N->getState();

244 if

(!State->get<HStateMap>(Sym)) {

245 const

HandleState *HState = Pred->

getState

()->get<HStateMap>(Sym);

246 if

(HState && (HState->isAllocated() || HState->maybeAllocated()))

256class

FuchsiaHandleSymbolVisitor final :

public SymbolVisitor

{

259 if

(

const auto

*HandleType = S->getType()->getAs<

TypedefType

>())

260 if

(HandleType->getDecl()->getName() == HandleTypeName)

261

Symbols.push_back(S);

276 int

PtrToHandleLevel = 0;

284

FuchsiaHandleSymbolVisitor Visitor;

285

State->scanReachableSymbols(Arg, Visitor);

286 return

Visitor.GetSymbols();

289 if

(HandleType->getDecl()->getName() != HandleTypeName)

291 if

(PtrToHandleLevel > 1)

295 if

(PtrToHandleLevel == 0) {

303

assert(PtrToHandleLevel == 1);

304 if

(std::optional<Loc> ArgLoc = Arg.

getAs

<

Loc

>()) {

305 SymbolRef

Sym = State->getSVal(*ArgLoc).getAsSymbol();

317void

FuchsiaHandleChecker::checkPreCall(

const CallEvent

&

Call

,

320 const FunctionDecl

*FuncDecl = dyn_cast_or_null<FunctionDecl>(

Call

.getDecl());

324 for

(

unsigned

Arg = 0; Arg <

Call

.getNumArgs(); ++Arg) {

326

State = State->set<HStateMap>(Handle, HandleState::getEscaped());

328 C

.addTransition(State);

332 for

(

unsigned

Arg = 0; Arg <

Call

.getNumArgs(); ++Arg) {

340 if

(hasFuchsiaAttr<ReleaseHandleAttr>(PVD) ||

341

hasFuchsiaAttr<AcquireHandleAttr>(PVD))

345 const

HandleState *HState = State->get<HStateMap>(Handle);

346 if

(!HState || HState->isEscaped())

349 if

(hasFuchsiaAttr<UseHandleAttr>(PVD) ||

351 if

(HState->isReleased()) {

352

reportUseAfterFree(Handle,

Call

.getArgSourceRange(Arg),

C

);

358 C

.addTransition(State);

361void

FuchsiaHandleChecker::checkPostCall(

const CallEvent

&

Call

,

363 const FunctionDecl

*FuncDecl = dyn_cast_or_null<FunctionDecl>(

Call

.getDecl());

373

std::vector<std::function<std::string(

BugReport

& BR)>> Notes;

376 if

(TypeDefTy->getDecl()->getName() == ErrorTypeName)

377

ResultSymbol =

Call

.getReturnValue().getAsSymbol();

380 if

(hasFuchsiaAttr<AcquireHandleAttr>(FuncDecl)) {

382

Notes.push_back([RetSym, FuncDecl](

BugReport

&BR) -> std::string {

384 if

(PathBR->getInterestingnessKind(RetSym)) {

386

llvm::raw_string_ostream OS(SBuf);

388

<<

"' returns an open handle"

;

394

State->set<HStateMap>(RetSym, HandleState::getMaybeAllocated(

nullptr

));

395

}

else if

(hasFuchsiaUnownedAttr<AcquireHandleAttr>(FuncDecl)) {

398

Notes.push_back([RetSym, FuncDecl](

BugReport

&BR) -> std::string {

400 if

(PathBR->getInterestingnessKind(RetSym)) {

402

llvm::raw_string_ostream OS(SBuf);

404

<<

"' returns an unowned handle"

;

409

State = State->set<HStateMap>(RetSym, HandleState::getUnowned());

412 for

(

unsigned

Arg = 0; Arg <

Call

.getNumArgs(); ++Arg) {

421 const

HandleState *HState = State->get<HStateMap>(Handle);

422 if

(HState && HState->isEscaped())

424 if

(hasFuchsiaAttr<ReleaseHandleAttr>(PVD)) {

425 if

(HState && HState->isReleased()) {

426

reportDoubleRelease(Handle,

Call

.getArgSourceRange(Arg),

C

);

428

}

else if

(HState && HState->isUnowned()) {

429

reportUnownedRelease(Handle,

Call

.getArgSourceRange(Arg),

C

);

432

Notes.push_back([Handle, ParamDiagIdx](

BugReport

&BR) -> std::string {

434 if

(PathBR->getInterestingnessKind(Handle)) {

436

llvm::raw_string_ostream OS(SBuf);

437

OS <<

"Handle released through "

<< ParamDiagIdx

438

<< llvm::getOrdinalSuffix(ParamDiagIdx) <<

" parameter"

;

443

State = State->set<HStateMap>(Handle, HandleState::getReleased());

445

}

else if

(hasFuchsiaAttr<AcquireHandleAttr>(PVD)) {

446

Notes.push_back([Handle, ParamDiagIdx](

BugReport

&BR) -> std::string {

448 if

(PathBR->getInterestingnessKind(Handle)) {

450

llvm::raw_string_ostream OS(SBuf);

451

OS <<

"Handle allocated through "

<< ParamDiagIdx

452

<< llvm::getOrdinalSuffix(ParamDiagIdx) <<

" parameter"

;

457

State = State->set<HStateMap>(

458

Handle, HandleState::getMaybeAllocated(ResultSymbol));

459

}

else if

(hasFuchsiaUnownedAttr<AcquireHandleAttr>(PVD)) {

460

Notes.push_back([Handle, ParamDiagIdx](

BugReport

&BR) -> std::string {

462 if

(PathBR->getInterestingnessKind(Handle)) {

464

llvm::raw_string_ostream OS(SBuf);

465

OS <<

"Unowned handle allocated through "

<< ParamDiagIdx

466

<< llvm::getOrdinalSuffix(ParamDiagIdx) <<

" parameter"

;

471

State = State->set<HStateMap>(Handle, HandleState::getUnowned());

472

}

else if

(!hasFuchsiaAttr<UseHandleAttr>(PVD) &&

479

State = State->set<HStateMap>(Handle, HandleState::getEscaped());

484 if

(!Notes.empty()) {

485 T

=

C

.getNoteTag([

this

, Notes{std::move(Notes)}](

487 if

(&BR.

getBugType

() != &UseAfterReleaseBugType &&

489

&BR.

getBugType

() != &DoubleReleaseBugType &&

492 for

(

auto

&

Note

: Notes) {

500 C

.addTransition(State,

T

);

503void

FuchsiaHandleChecker::checkDeadSymbols(

SymbolReaper

&SymReaper,

507

HStateMapTy TrackedHandles = State->get<HStateMap>();

508 for

(

auto

&CurItem : TrackedHandles) {

509 SymbolRef

ErrorSym = CurItem.second.getErrorSym();

514 if

(!SymReaper.

isDead

(CurItem.first) ||

515

(ErrorSym && !SymReaper.

isDead

(ErrorSym)))

517 if

(CurItem.second.isAllocated() || CurItem.second.maybeAllocated())

518

LeakedSyms.push_back(CurItem.first);

519

State = State->remove<HStateMap>(CurItem.first);

523 if

(!LeakedSyms.empty())

524

N = reportLeaks(LeakedSyms,

C

, N);

526 C

.addTransition(State, N);

541 bool

Assumption)

const

{

544

HStateMapTy TrackedHandles = State->get<HStateMap>();

545 for

(

auto

&CurItem : TrackedHandles) {

549

State = State->remove<HStateMap>(CurItem.first);

551 SymbolRef

ErrorSym = CurItem.second.getErrorSym();

557 if

(CurItem.second.maybeAllocated())

558

State = State->set<HStateMap>(

559

CurItem.first, HandleState::getAllocated(State, CurItem.second));

562 if

(CurItem.second.maybeAllocated())

563

State = State->remove<HStateMap>(CurItem.first);

573 Call

? dyn_cast_or_null<FunctionDecl>(

Call

->getDecl()) : nullptr;

575

llvm::DenseSet<SymbolRef> UnEscaped;

580 for

(

unsigned

Arg = 0; Arg <

Call

->getNumArgs(); ++Arg) {

587 if

(hasFuchsiaAttr<UseHandleAttr>(PVD) ||

588

hasFuchsiaAttr<ReleaseHandleAttr>(PVD)) {

589

UnEscaped.insert(Handle);

597 for

(

auto

I : State->get<HStateMap>()) {

598 if

(Escaped.count(I.first) && !UnEscaped.count(I.first))

599

State = State->set<HStateMap>(I.first, HandleState::getEscaped());

600 if

(

const auto

*SD = dyn_cast<SymbolDerived>(I.first)) {

601 auto

ParentSym = SD->getParentSymbol();

602 if

(Escaped.count(ParentSym))

603

State = State->set<HStateMap>(I.first, HandleState::getEscaped());

613 ExplodedNode

*ErrNode =

C

.generateNonFatalErrorNode(

C

.getState(), Pred);

614 for

(

SymbolRef

LeakedHandle : LeakedHandles) {

615

reportBug(LeakedHandle, ErrNode,

C

,

nullptr

, LeakBugType,

616 "Potential leak of handle"

);

621void

FuchsiaHandleChecker::reportDoubleRelease(

SymbolRef

HandleSym,

625

reportBug(HandleSym, ErrNode,

C

, &

Range

, DoubleReleaseBugType,

626 "Releasing a previously released handle"

);

629void

FuchsiaHandleChecker::reportUnownedRelease(

SymbolRef

HandleSym,

633

reportBug(HandleSym, ErrNode,

C

, &

Range

, ReleaseUnownedBugType,

634 "Releasing an unowned handle"

);

637void

FuchsiaHandleChecker::reportUseAfterFree(

SymbolRef

HandleSym,

641

reportBug(HandleSym, ErrNode,

C

, &

Range

, UseAfterReleaseBugType,

642 "Using a previously released handle"

);

652

std::unique_ptr<PathSensitiveBugReport> R;

653 if

(

Type

.isSuppressOnSink()) {

657

assert(S &&

"Statement cannot be null."

);

662

R = std::make_unique<PathSensitiveBugReport>(

663 Type

, Msg, ErrorNode, LocUsedForUniqueing,

668

R = std::make_unique<PathSensitiveBugReport>(

Type

, Msg, ErrorNode);

670

R->addRange(*

Range

);

671

R->markInteresting(Sym);

672 C

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

679bool

ento::shouldRegisterFuchsiaHandleChecker(

const CheckerManager

&mgr) {

683void

FuchsiaHandleChecker::printState(raw_ostream &Out,

ProgramStateRef

State,

684 const char

*NL,

const char

*Sep)

const

{

686

HStateMapTy StateMap = State->get<HStateMap>();

688 if

(!StateMap.isEmpty()) {

689

Out << Sep <<

"FuchsiaHandleChecker :"

<< NL;

690 for

(

const auto

&[Sym, HandleState] : StateMap) {

693

HandleState.dump(Out);

static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)

static const ExplodedNode * getAcquireSite(const ExplodedNode *N, SymbolRef Sym, CheckerContext &Ctx)

static SmallVector< SymbolRef, 1024 > getFuchsiaHandleSymbols(QualType QT, SVal Arg, ProgramStateRef State)

Returns the symbols extracted from the argument or empty vector if it cannot be found.

static bool isReleased(SymbolRef Sym, CheckerContext &C)

Check if the memory associated with this symbol was released.

#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)

Declares an immutable map of type NameTy, suitable for placement into the ProgramState.

C Language Family Type Representation.

Attr - This represents one attribute.

Decl - This represents one declaration (or definition), e.g.

Represents a function declaration or definition.

const ParmVarDecl * getParamDecl(unsigned i) const

QualType getReturnType() const

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

const Decl * getDecl() const

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

Represents a parameter to a function.

unsigned getFunctionScopeIndex() const

Returns the index of this parameter in its prototype or method scope.

A (possibly-)qualified type.

A trivial tuple used to represent a source range.

Stmt - This represents one statement.

The base class of the type hierarchy.

bool isStructureType() const

bool isIntegerType() const

isIntegerType() does not include complex integers (a GCC extension).

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isAnyPointerType() const

const T * getAs() const

Member-template getAs<specific type>'.

This class provides an interface through which checkers can create individual bug reports.

const BugType & getBugType() const

Represents an abstract call to a function or method along a particular path.

virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const

See CheckerManager::runCheckersForPrintState.

CHECKER * registerChecker(AT &&... Args)

Used to register checkers.

bool isConstrainedFalse() const

Return true if the constraint is perfectly constrained to 'false'.

bool isConstrainedTrue() const

Return true if the constraint is perfectly constrained to 'true'.

ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)

Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...

const ProgramStateRef & getState() const

const Stmt * getStmtForDiagnostics() const

If the node's program point corresponds to a statement, retrieve that statement.

const LocationContext * getLocationContext() const

ExplodedNode * getFirstPred()

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.

A Range represents the closed range [from, to].

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.

virtual void dumpToStream(raw_ostream &os) const

A class responsible for cleaning up unused symbols.

bool isDead(SymbolRef sym)

Returns whether or not a symbol has been confirmed dead.

virtual bool VisitSymbol(SymbolRef sym)=0

A visitor method invoked by ProgramStateManager::scanReachableSymbols.

PointerEscapeKind

Describes the different reasons a pointer escapes during analysis.

@ PSK_DirectEscapeOnCall

The pointer has been passed to a function call directly.

@ PSK_IndirectEscapeOnCall

The pointer has been passed to a function indirectly.

@ PSK_EscapeOutParameters

Escape for a new symbol that was generated into a region that the analyzer cannot follow during a con...

llvm::DenseSet< SymbolRef > InvalidatedSymbols

The JSON file list parser is used to communicate input to InstallAPI.

bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)

const FunctionProtoType * T

@ Other

Other implicit parameter.


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