Skip to content

Commit 75819ee

Browse files
eupharinaresistor
authored andcommitted
[CHERI_CSA] Refactoring state cleanup for dead symbols & regions
1 parent 389ce92 commit 75819ee

File tree

6 files changed

+90
-35
lines changed

6 files changed

+90
-35
lines changed

clang/lib/StaticAnalyzer/Checkers/CHERI/AllocationChecker.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ using EscapePair = std::pair<const MemRegion *, EscapeInfo>;
3838
namespace {
3939
class AllocationChecker
4040
: public Checker<check::PostStmt<CastExpr>, check::PreCall, check::PostCall,
41-
check::Bind, check::EndFunction> {
41+
check::Bind, check::EndFunction, check::DeadSymbols> {
4242
BugType BT_Default{this, "Allocation partitioning", "CHERI portability"};
4343
BugType BT_UnknownReg{this, "Unknown allocation partitioning",
4444
"CHERI portability"};
@@ -80,6 +80,7 @@ class AllocationChecker
8080
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
8181
void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
8282
void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
83+
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
8384

8485
bool ReportForUnknownAllocations;
8586

@@ -408,6 +409,22 @@ void AllocationChecker::checkEndFunction(const ReturnStmt *RS,
408409
}
409410
}
410411

412+
void AllocationChecker::checkDeadSymbols(SymbolReaper &SymReaper,
413+
CheckerContext &C) const {
414+
if (!isPureCapMode(C.getASTContext()))
415+
return;
416+
417+
ProgramStateRef State = C.getState();
418+
bool Removed = false;
419+
State = cleanDead<AllocMap>(State, SymReaper, Removed);
420+
State = cleanDead<ShiftMap>(State, SymReaper, Removed);
421+
State = cleanDead<SuballocationSet>(State, SymReaper, Removed);
422+
State = cleanDead<BoundedSet>(State, SymReaper, Removed);
423+
424+
if (Removed)
425+
C.addTransition(State);
426+
}
427+
411428
PathDiagnosticPieceRef AllocationChecker::AllocPartitionBugVisitor::VisitNode(
412429
const ExplodedNode *N, BugReporterContext &BRC,
413430
PathSensitiveBugReport &BR) {

clang/lib/StaticAnalyzer/Checkers/CHERI/CHERIUtils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "CHERIUtils.h"
10+
#include <clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h>
11+
12+
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
1013

1114
namespace clang {
1215
namespace ento {

clang/lib/StaticAnalyzer/Checkers/CHERI/CHERIUtils.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_CHERI_CHERIUTILS_H
1111

1212
#include "clang/StaticAnalyzer/Core/Checker.h"
13+
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
14+
#include <clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h>
1315

1416
namespace clang {
1517
namespace ento {
@@ -33,6 +35,42 @@ void describeCast(raw_ostream &OS, const CastExpr *CE,
3335
const DeclRegion *getAllocationDecl(const MemRegion *MR);
3436

3537
} // namespace cheri
38+
39+
template <typename C>
40+
inline typename ProgramStateTrait<C>::key_type
41+
getKey(const std::pair<typename ProgramStateTrait<C>::key_type,
42+
typename ProgramStateTrait<C>::value_type> &P) {
43+
return P.first;
44+
}
45+
46+
template <typename C>
47+
inline typename ProgramStateTrait<C>::key_type
48+
getKey(const typename ProgramStateTrait<C>::key_type &K) {
49+
return K;
50+
}
51+
52+
inline bool isLive(SymbolReaper &SymReaper, const MemRegion *MR) {
53+
return SymReaper.isLiveRegion(MR);
54+
}
55+
56+
inline bool isLive(SymbolReaper &SymReaper, SymbolRef Sym) {
57+
return SymReaper.isLive(Sym);
58+
}
59+
60+
template <typename M>
61+
ProgramStateRef cleanDead(ProgramStateRef State, SymbolReaper &SymReaper,
62+
bool &Removed) {
63+
const typename ProgramStateTrait<M>::data_type &Map = State->get<M>();
64+
for (const auto &E : Map) {
65+
const typename ProgramStateTrait<M>::key_type &K = getKey<M>(E);
66+
if (isLive(SymReaper, K))
67+
continue;
68+
State = State->remove<M>(K);
69+
Removed = true;
70+
}
71+
return State;
72+
}
73+
3674
} // namespace ento
3775
} // namespace clang
3876

clang/lib/StaticAnalyzer/Checkers/CHERI/CapabilityCopyChecker.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ struct CHERITagState {
4949
};
5050

5151
class CapabilityCopyChecker
52-
: public Checker<check::Location, check::Bind,
53-
check::PostStmt<BinaryOperator>,
54-
check::PostStmt<ArraySubscriptExpr>,
55-
check::BranchCondition, check::PreCall> {
52+
: public Checker<
53+
check::Location, check::Bind, check::PostStmt<BinaryOperator>,
54+
check::PostStmt<ArraySubscriptExpr>, check::BranchCondition,
55+
check::PreCall, check::DeadSymbols> {
5656

5757
BugType UseCapAsNonCap{this,
5858
"Part of capability value used in binary operator",
@@ -76,6 +76,7 @@ class CapabilityCopyChecker
7676
void checkPostStmt(const ArraySubscriptExpr *E, CheckerContext &C) const;
7777
void checkBranchCondition(const Stmt *Cond, CheckerContext &C) const;
7878
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
79+
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
7980

8081
bool ReportForCharPtr = false;
8182

@@ -87,7 +88,7 @@ class CapabilityCopyChecker
8788
REGISTER_SET_WITH_PROGRAMSTATE(VoidPtrArgDeref, const MemRegion *)
8889
REGISTER_SET_WITH_PROGRAMSTATE(UnalignedPtr, const MemRegion *)
8990
REGISTER_SET_WITH_PROGRAMSTATE(CString, const MemRegion *)
90-
REGISTER_LIST_WITH_PROGRAMSTATE(WhileBoundVar, SymbolRef)
91+
REGISTER_SET_WITH_PROGRAMSTATE(WhileBoundVar, SymbolRef)
9192

9293
namespace {
9394

@@ -250,8 +251,8 @@ bool isInsideSmallConstantBoundLoop(const Stmt *S, CheckerContext &C, long N) {
250251
SValBuilder &SVB = C.getSValBuilder();
251252
const NonLoc &ItVal = SVB.makeIntVal(N, true);
252253

253-
auto BoundVarList = C.getState()->get<WhileBoundVar>();
254-
for (auto &&V : BoundVarList) {
254+
auto BoundVarSet = C.getState()->get<WhileBoundVar>();
255+
for (auto &&V : BoundVarSet) {
255256
auto SmallLoop =
256257
SVB.evalBinOpNN(C.getState(), clang::BO_GE, nonloc::SymbolVal(V), ItVal,
257258
SVB.getConditionType());
@@ -472,8 +473,6 @@ bool checkForWhileBoundVar(const Stmt *Condition, CheckerContext &C,
472473
if (SymbolRef ISym = C.getSVal(L).getAsSymbol()) {
473474
if (ThenSt)
474475
ThenSt = ThenSt->add<WhileBoundVar>(ISym);
475-
if (ElseSt)
476-
ElseSt = ElseSt->set<WhileBoundVar>(llvm::ImmutableList<SymbolRef>());
477476
} else
478477
return false;
479478
}
@@ -615,6 +614,23 @@ void CapabilityCopyChecker::checkPreCall(const CallEvent &Call,
615614
C.addTransition(State);
616615
}
617616

617+
void CapabilityCopyChecker::checkDeadSymbols(SymbolReaper &SymReaper,
618+
CheckerContext &C) const {
619+
if (!isPureCapMode(C.getASTContext()))
620+
return;
621+
622+
ProgramStateRef State = C.getState();
623+
bool Removed = false;
624+
625+
State = cleanDead<VoidPtrArgDeref>(State, SymReaper, Removed);
626+
State = cleanDead<UnalignedPtr>(State, SymReaper, Removed);
627+
State = cleanDead<CString>(State, SymReaper, Removed);
628+
State = cleanDead<WhileBoundVar>(State, SymReaper, Removed);
629+
630+
if (Removed)
631+
C.addTransition(State);
632+
}
633+
618634
void ento::registerCapabilityCopyChecker(CheckerManager &mgr) {
619635
auto *Checker = mgr.registerChecker<CapabilityCopyChecker>();
620636
Checker->ReportForCharPtr = mgr.getAnalyzerOptions().getCheckerBooleanOption(

clang/lib/StaticAnalyzer/Checkers/CHERI/ProvenanceSourceChecker.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -510,23 +510,10 @@ void ProvenanceSourceChecker::checkDeadSymbols(SymbolReaper &SymReaper,
510510
return;
511511

512512
ProgramStateRef State = C.getState();
513-
514513
bool Removed = false;
515-
const InvalidCapTy &Set = State->get<InvalidCap>();
516-
for (const auto &Sym : Set) {
517-
if (!SymReaper.isDead(Sym))
518-
continue;
519-
State = State->remove<InvalidCap>(Sym);
520-
Removed = true;
521-
}
522-
523-
const AmbiguousProvenanceSymTy &Set2 = State->get<AmbiguousProvenanceSym>();
524-
for (const auto &Sym : Set2) {
525-
if (!SymReaper.isDead(Sym))
526-
continue;
527-
State = State->remove<AmbiguousProvenanceSym>(Sym);
528-
Removed = true;
529-
}
514+
State = cleanDead<InvalidCap>(State, SymReaper, Removed);
515+
State = cleanDead<AmbiguousProvenanceSym>(State, SymReaper, Removed);
516+
State = cleanDead<AmbiguousProvenanceReg>(State, SymReaper, Removed);
530517

531518
if (Removed)
532519
C.addTransition(State);

clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -916,17 +916,11 @@ void PointerAlignmentChecker::checkPostStmt(const BinaryOperator *BO,
916916

917917
void PointerAlignmentChecker::checkDeadSymbols(SymbolReaper &SymReaper,
918918
CheckerContext &C) const {
919-
bool Updated = false;
920919
ProgramStateRef State = C.getState();
920+
bool Updated = false;
921921

922-
TrailingZerosMapTy TZMap = State->get<TrailingZerosMap>();
923-
for (TrailingZerosMapTy::iterator I = TZMap.begin(), E = TZMap.end(); I != E;
924-
++I) {
925-
if (SymReaper.isDead(I->first)) {
926-
State = State->remove<TrailingZerosMap>(I->first);
927-
Updated = true;
928-
}
929-
}
922+
State = cleanDead<TrailingZerosMap>(State, SymReaper, Updated);
923+
State = cleanDead<CapStorageSet>(State, SymReaper, Updated);
930924

931925
if (Updated)
932926
C.addTransition(State);

0 commit comments

Comments
 (0)