Skip to content

Commit 7dcf131

Browse files
eupharinaresistor
authored andcommitted
[CHERI_CSA] Refactoring state cleanup for dead symbols & regions
1 parent ca354e7 commit 7dcf131

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

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

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

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

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

618+
void CapabilityCopyChecker::checkDeadSymbols(SymbolReaper &SymReaper,
619+
CheckerContext &C) const {
620+
if (!isPureCapMode(C.getASTContext()))
621+
return;
622+
623+
ProgramStateRef State = C.getState();
624+
bool Removed = false;
625+
626+
State = cleanDead<VoidPtrArgDeref>(State, SymReaper, Removed);
627+
State = cleanDead<UnalignedPtr>(State, SymReaper, Removed);
628+
State = cleanDead<CString>(State, SymReaper, Removed);
629+
State = cleanDead<WhileBoundVar>(State, SymReaper, Removed);
630+
631+
if (Removed)
632+
C.addTransition(State);
633+
}
634+
619635
void ento::registerCapabilityCopyChecker(CheckerManager &mgr) {
620636
auto *Checker = mgr.registerChecker<CapabilityCopyChecker>();
621637
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
@@ -918,17 +918,11 @@ void PointerAlignmentChecker::checkPostStmt(const BinaryOperator *BO,
918918

919919
void PointerAlignmentChecker::checkDeadSymbols(SymbolReaper &SymReaper,
920920
CheckerContext &C) const {
921-
bool Updated = false;
922921
ProgramStateRef State = C.getState();
922+
bool Updated = false;
923923

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

933927
if (Updated)
934928
C.addTransition(State);

0 commit comments

Comments
 (0)