Skip to content

Commit bbd2765

Browse files
committed
[CHERI_CSA] Refactoring state cleanup for dead symbols & regions
1 parent 54ace79 commit bbd2765

File tree

6 files changed

+103
-47
lines changed

6 files changed

+103
-47
lines changed

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
1515
#include "clang/StaticAnalyzer/Core/Checker.h"
1616
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
17+
#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>
1718
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
1819
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
1920
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
20-
#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>
2121

2222

2323
using namespace clang;
@@ -42,7 +42,8 @@ class AllocationChecker : public Checker<check::PostStmt<CastExpr>,
4242
check::PreCall,
4343
check::PostCall,
4444
check::Bind,
45-
check::EndFunction> {
45+
check::EndFunction,
46+
check::DeadSymbols> {
4647
BugType BT_Default{this, "Allocation partitioning", "CHERI portability"};
4748
BugType BT_UnknownReg{this, "Unknown allocation partitioning",
4849
"CHERI portability"};
@@ -86,6 +87,7 @@ class AllocationChecker : public Checker<check::PostStmt<CastExpr>,
8687
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
8788
void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
8889
void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
90+
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
8991

9092
bool ReportForUnknownAllocations;
9193

@@ -437,6 +439,22 @@ void AllocationChecker::checkEndFunction(const ReturnStmt *RS,
437439
}
438440
}
439441

442+
void AllocationChecker::checkDeadSymbols(SymbolReaper &SymReaper,
443+
CheckerContext &C) const {
444+
if (!isPureCapMode(C.getASTContext()))
445+
return;
446+
447+
ProgramStateRef State = C.getState();
448+
bool Removed = false;
449+
State = cleanDead<AllocMap>(State, SymReaper, Removed);
450+
State = cleanDead<ShiftMap>(State, SymReaper, Removed);
451+
State = cleanDead<SuballocationSet>(State, SymReaper, Removed);
452+
State = cleanDead<BoundedSet>(State, SymReaper, Removed);
453+
454+
if (Removed)
455+
C.addTransition(State);
456+
}
457+
440458
PathDiagnosticPieceRef AllocationChecker::AllocPartitionBugVisitor::VisitNode(
441459
const ExplodedNode *N, BugReporterContext &BRC,
442460
PathSensitiveBugReport &BR) {

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

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

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

1115
namespace clang {
1216
namespace ento {
@@ -54,8 +58,7 @@ bool hasCapability(const QualType OrigTy, ASTContext &Ctx) {
5458

5559
namespace {
5660

57-
void printType(raw_ostream &OS, const QualType &Ty,
58-
const PrintingPolicy &PP) {
61+
void printType(raw_ostream &OS, const QualType &Ty, const PrintingPolicy &PP) {
5962
std::string TyStr = Ty.getAsString(PP);
6063
OS << "'" << TyStr << "'";
6164
std::string CanTyStr = Ty.getCanonicalType().getAsString(PP);
@@ -67,7 +70,7 @@ void printType(raw_ostream &OS, const QualType &Ty,
6770
} // namespace
6871

6972
void describeCast(raw_ostream &OS, const CastExpr *CE,
70-
const LangOptions &LangOpts) {
73+
const LangOptions &LangOpts) {
7174
const PrintingPolicy &PP = PrintingPolicy(LangOpts);
7275
OS << (dyn_cast<ImplicitCastExpr>(CE) ? "implicit" : "explicit");
7376
OS << " cast from ";
@@ -84,7 +87,6 @@ const DeclRegion *getAllocationDecl(const MemRegion *MR) {
8487
return nullptr;
8588
}
8689

87-
88-
} // end of namespace: cheri
89-
} // end of namespace: ento
90-
} // end of namespace: clang
90+
} // namespace cheri
91+
} // namespace ento
92+
} // namespace clang

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

Lines changed: 41 additions & 3 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/ProgramState.h>
14+
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
1315

1416
namespace clang {
1517
namespace ento {
@@ -32,8 +34,44 @@ void describeCast(raw_ostream &OS, const CastExpr *CE,
3234

3335
const DeclRegion *getAllocationDecl(const MemRegion *MR);
3436

35-
} // end of namespace: cheri
36-
} // end of namespace: ento
37-
} // end of namespace: clang
37+
} // 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+
74+
} // namespace ento
75+
} // namespace clang
3876

3977
#endif // LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_CHERI_CHERIUTILS_H

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

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
#include "CHERIUtils.h"
1515
#include "clang/ASTMatchers/ASTMatchFinder.h"
1616
#include "clang/ASTMatchers/ASTMatchers.h"
17+
#include <clang/ASTMatchers/ASTMatchersInternal.h>
1718
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
1819
#include "clang/StaticAnalyzer/Core/Checker.h"
1920
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
21+
#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>
2022
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
2123
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22-
#include <clang/ASTMatchers/ASTMatchersInternal.h>
23-
#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>
2424

2525
using namespace clang;
2626
using namespace ento;
@@ -57,7 +57,8 @@ class CapabilityCopyChecker :public Checker<check::Location, check::Bind,
5757
check::PostStmt<BinaryOperator>,
5858
check::PostStmt<ArraySubscriptExpr>,
5959
check::BranchCondition,
60-
check::PreCall> {
60+
check::PreCall,
61+
check::DeadSymbols> {
6162

6263
BugType UseCapAsNonCap{this,
6364
"Part of capability value used in binary operator",
@@ -83,6 +84,7 @@ class CapabilityCopyChecker :public Checker<check::Location, check::Bind,
8384
void checkPostStmt(const ArraySubscriptExpr *E, CheckerContext &C) const;
8485
void checkBranchCondition(const Stmt *Cond, CheckerContext &C) const;
8586
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
87+
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
8688

8789
bool ReportForCharPtr = false;
8890

@@ -95,7 +97,7 @@ class CapabilityCopyChecker :public Checker<check::Location, check::Bind,
9597
REGISTER_SET_WITH_PROGRAMSTATE(VoidPtrArgDeref, const MemRegion *)
9698
REGISTER_SET_WITH_PROGRAMSTATE(UnalignedPtr, const MemRegion *)
9799
REGISTER_SET_WITH_PROGRAMSTATE(CString, const MemRegion *)
98-
REGISTER_LIST_WITH_PROGRAMSTATE(WhileBoundVar, SymbolRef)
100+
REGISTER_SET_WITH_PROGRAMSTATE(WhileBoundVar, SymbolRef)
99101

100102
namespace {
101103

@@ -260,8 +262,8 @@ bool isInsideSmallConstantBoundLoop(const Stmt *S, CheckerContext &C, long N) {
260262
SValBuilder &SVB = C.getSValBuilder();
261263
const NonLoc &ItVal = SVB.makeIntVal(N, true);
262264

263-
auto BoundVarList = C.getState()->get<WhileBoundVar>();
264-
for (auto &&V : BoundVarList) {
265+
auto BoundVarSet = C.getState()->get<WhileBoundVar>();
266+
for (auto &&V : BoundVarSet) {
265267
auto SmallLoop =
266268
SVB.evalBinOpNN(C.getState(), clang::BO_GE, nonloc::SymbolVal(V), ItVal,
267269
SVB.getConditionType());
@@ -485,8 +487,6 @@ bool checkForWhileBoundVar(const Stmt *Condition, CheckerContext &C,
485487
if (SymbolRef ISym = C.getSVal(L).getAsSymbol()) {
486488
if (ThenSt)
487489
ThenSt = ThenSt->add<WhileBoundVar>(ISym);
488-
if (ElseSt)
489-
ElseSt = ElseSt->set<WhileBoundVar>(llvm::ImmutableList<SymbolRef>());
490490
} else
491491
return false;
492492
}
@@ -627,6 +627,23 @@ void CapabilityCopyChecker::checkPreCall(const CallEvent &Call,
627627
C.addTransition(State);
628628
}
629629

630+
void CapabilityCopyChecker::checkDeadSymbols(SymbolReaper &SymReaper,
631+
CheckerContext &C) const {
632+
if (!isPureCapMode(C.getASTContext()))
633+
return;
634+
635+
ProgramStateRef State = C.getState();
636+
bool Removed = false;
637+
638+
State = cleanDead<VoidPtrArgDeref>(State, SymReaper, Removed);
639+
State = cleanDead<UnalignedPtr>(State, SymReaper, Removed);
640+
State = cleanDead<CString>(State, SymReaper, Removed);
641+
State = cleanDead<WhileBoundVar>(State, SymReaper, Removed);
642+
643+
if (Removed)
644+
C.addTransition(State);
645+
}
646+
630647
void ento::registerCapabilityCopyChecker(CheckerManager &mgr) {
631648
auto *Checker = mgr.registerChecker<CapabilityCopyChecker>();
632649
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
@@ -515,23 +515,10 @@ void ProvenanceSourceChecker::checkDeadSymbols(SymbolReaper &SymReaper,
515515
return;
516516

517517
ProgramStateRef State = C.getState();
518-
519518
bool Removed = false;
520-
const InvalidCapTy &Set = State->get<InvalidCap>();
521-
for (const auto &Sym : Set) {
522-
if (!SymReaper.isDead(Sym))
523-
continue;
524-
State = State->remove<InvalidCap>(Sym);
525-
Removed = true;
526-
}
527-
528-
const AmbiguousProvenanceSymTy &Set2 = State->get<AmbiguousProvenanceSym>();
529-
for (const auto &Sym : Set2) {
530-
if (!SymReaper.isDead(Sym))
531-
continue;
532-
State = State->remove<AmbiguousProvenanceSym>(Sym);
533-
Removed = true;
534-
}
519+
State = cleanDead<InvalidCap>(State, SymReaper, Removed);
520+
State = cleanDead<AmbiguousProvenanceSym>(State, SymReaper, Removed);
521+
State = cleanDead<AmbiguousProvenanceReg>(State, SymReaper, Removed);
535522

536523
if (Removed)
537524
C.addTransition(State);

clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@
2929
//===----------------------------------------------------------------------===//
3030

3131
#include "CHERI/CHERIUtils.h"
32+
#include <clang/ASTMatchers/ASTMatchFinder.h>
3233
#include "clang/ASTMatchers/ASTMatchers.h"
3334
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
34-
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
35-
#include <clang/ASTMatchers/ASTMatchFinder.h>
3635
#include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
3736
#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>
3837
#include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h>
38+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
3939

4040
using namespace clang;
4141
using namespace ento;
@@ -914,17 +914,11 @@ void PointerAlignmentChecker::checkPostStmt(const BinaryOperator *BO,
914914

915915
void PointerAlignmentChecker::checkDeadSymbols(SymbolReaper &SymReaper,
916916
CheckerContext &C) const {
917-
bool Updated = false;
918917
ProgramStateRef State = C.getState();
918+
bool Updated = false;
919919

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

929923
if (Updated)
930924
C.addTransition(State);

0 commit comments

Comments
 (0)