Skip to content

Commit 46c91d7

Browse files
eupharinaresistor
authored andcommitted
[CHERI_CSA] SubObjectRepresentability: enable notes with updated cheri-compressed-cap
1 parent fa7d7c5 commit 46c91d7

File tree

2 files changed

+64
-39
lines changed

2 files changed

+64
-39
lines changed

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

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CHERIUtils.h"
18-
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
1918
#include "clang/AST/StmtVisitor.h"
2019
#include "clang/ASTMatchers/ASTMatchFinder.h"
20+
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
2121
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
2222
#include "clang/StaticAnalyzer/Core/Checker.h"
2323
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -44,12 +44,14 @@ class SubObjectRepresentabilityChecker
4444
BugReporter &BR) const;
4545
};
4646

47-
}
47+
} //namespace
4848

4949
namespace {
5050

51-
std::unique_ptr<BasicBugReport> reportExposedFields(const FieldDecl *D, ASTContext &ASTCtx, BugReporter &BR,
52-
uint64_t Base, uint64_t Top, std::unique_ptr<BasicBugReport> Report) {
51+
std::unique_ptr<BasicBugReport>
52+
reportExposedFields(const FieldDecl *D, ASTContext &ASTCtx, BugReporter &BR,
53+
uint64_t Base, uint64_t Top,
54+
std::unique_ptr<BasicBugReport> Report) {
5355
const RecordDecl *Parent = D->getParent();
5456
auto FI = Parent->field_begin();
5557
while (FI != Parent->field_end() &&
@@ -86,23 +88,28 @@ std::unique_ptr<BasicBugReport> reportExposedFields(const FieldDecl *D, ASTConte
8688
}
8789

8890
#if 0
89-
// FIXME: CC_MORELLO is not set in cheri_compressed_cap
90-
// FIXME: other targets
91-
using Handler = CompressedCap128;
92-
Handler::cap_t getBoundedCap(uint64_t ParentSize, uint64_t Offset,
93-
uint64_t Size) {
94-
Handler::addr_t InitLength = Handler ::representable_length(ParentSize);
95-
Handler::cap_t MockCap = Handler::make_max_perms_cap(0, 0, InitLength);
96-
bool exact = Handler::setbounds(&MockCap, Offset, Offset + Size);
91+
template <typename Handler>
92+
typename Handler::cap_t getBoundedCap(uint64_t ParentSize, uint64_t Offset,
93+
uint64_t Size) {
94+
typename Handler::addr_t InitLength =
95+
Handler::representable_length(ParentSize);
96+
typename Handler::cap_t MockCap =
97+
Handler::make_max_perms_cap(0, Offset, InitLength);
98+
bool exact = Handler::setbounds(&MockCap, Size);
9799
assert(!exact);
98100
return MockCap;
99101
}
100102
#endif
101103

102-
} // namespace
104+
template<typename Handler>
105+
uint64_t getRepresentableAlignment(uint64_t Size) {
106+
return ~Handler::representable_mask(Size) + 1;
107+
}
103108

104-
std::unique_ptr<BugReport> checkField(const FieldDecl *D, AnalysisManager &mgr,
105-
BugReporter &BR, const BugType &BT) {
109+
template <llvm::CompressedCapability::CapabilityFormat Handler>
110+
std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D,
111+
BugReporter &BR,
112+
const BugType &BT) {
106113
QualType T = D->getType();
107114

108115
ASTContext &ASTCtx = BR.getContext();
@@ -125,17 +132,15 @@ std::unique_ptr<BugReport> checkField(const FieldDecl *D, AnalysisManager &mgr,
125132
OS << " field offset is " << Offset;
126133
OS << " (aligned to " << CurAlign << ");";
127134

128-
/*
129-
* Print current bounds
130-
* TODO: use cheri_compressed_cap correctly
131-
*
135+
#if 0
132136
const RecordDecl *Parent = D->getParent();
133137
uint64_t ParentSize = ASTCtx.getTypeSize(Parent->getTypeForDecl()) / 8;
134-
auto MockCap = getBoundedCap(ParentSize, Offset, Size);
138+
typename Handler::cap_t MockCap =
139+
getBoundedCap<Handler>(ParentSize, Offset, Size);
135140
uint64_t Base = MockCap.base();
136141
uint64_t Top = MockCap.top();
137142
OS << " Current bounds: " << Base << "-" << Top;
138-
*/
143+
#endif
139144

140145
// Note that this will fire for every translation unit that uses this
141146
// class. This is suboptimal, but at least scan-build will merge
@@ -146,11 +151,9 @@ std::unique_ptr<BugReport> checkField(const FieldDecl *D, AnalysisManager &mgr,
146151
Report->setDeclWithIssue(D);
147152
Report->addRange(D->getSourceRange());
148153

149-
/*
150-
* Add exposed fields as notes
151-
* TODO: use cheri_compressed_cap correctly
154+
#if 0
152155
Report = reportExposedFields(D, ASTCtx, BR, Base, Top, std::move(Report));
153-
*/
156+
#endif
154157

155158
return Report;
156159
}
@@ -159,10 +162,29 @@ std::unique_ptr<BugReport> checkField(const FieldDecl *D, AnalysisManager &mgr,
159162
return nullptr;
160163
}
161164

165+
std::unique_ptr<BugReport> checkField(const FieldDecl *D,
166+
BugReporter &BR,
167+
const BugType &BT) {
168+
// TODO: other targets
169+
return checkFieldImpl<llvm::CompressedCapability::Cheri128>(D, BR, BT);
170+
}
171+
172+
bool supportedTarget(const ASTContext &C) {
173+
const TargetInfo &TI = C.getTargetInfo();
174+
return TI.areAllPointersCapabilities()
175+
&& TI.getTriple().isAArch64(); // morello
176+
}
177+
178+
} // namespace
179+
180+
162181
void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
163182
AnalysisManager &mgr,
164183
BugReporter &BR) const {
165-
if (!R->isCompleteDefinition())
184+
if (!supportedTarget(mgr.getASTContext()))
185+
return;
186+
187+
if (!R->isCompleteDefinition() || R->isDependentType())
166188
return;
167189

168190
if (!R->getLocation().isValid())
@@ -177,16 +199,19 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
177199
*/
178200

179201
for (FieldDecl *D : R->fields()) {
180-
auto Report = checkField(D, mgr, BR, BT_1);
202+
auto Report = checkField(D, BR, BT_1);
181203
if (Report)
182204
BR.emitReport(std::move(Report));
183205
}
184206
}
185207

186-
void SubObjectRepresentabilityChecker::checkASTCodeBody(const Decl *D, AnalysisManager &mgr,
187-
BugReporter &BR) const {
188-
using namespace ast_matchers;
208+
void SubObjectRepresentabilityChecker::checkASTCodeBody(const Decl *D,
209+
AnalysisManager &mgr,
210+
BugReporter &BR) const {
211+
if (!supportedTarget(mgr.getASTContext()))
212+
return;
189213

214+
using namespace ast_matchers;
190215
auto Member = memberExpr().bind("member");
191216
auto Decay =
192217
castExpr(hasCastKind(CK_ArrayToPointerDecay), has(Member)).bind("decay");
@@ -202,7 +227,7 @@ void SubObjectRepresentabilityChecker::checkASTCodeBody(const Decl *D, AnalysisM
202227
if (const MemberExpr *ME = Match.getNodeAs<MemberExpr>("member")) {
203228
ValueDecl *VD = ME->getMemberDecl();
204229
if (FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
205-
auto Report = checkField(FD, mgr, BR, BT_2);
230+
auto Report = checkField(FD, BR, BT_2);
206231
if (Report) {
207232
PathDiagnosticLocation LN = PathDiagnosticLocation::createBegin(
208233
CE, BR.getSourceManager(), mgr.getAnalysisDeclContext(D));
@@ -216,7 +241,7 @@ void SubObjectRepresentabilityChecker::checkASTCodeBody(const Decl *D, AnalysisM
216241
if (const MemberExpr *ME = Match.getNodeAs<MemberExpr>("member")) {
217242
ValueDecl *VD = ME->getMemberDecl();
218243
if (FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
219-
auto Report = checkField(FD, mgr, BR, BT_2);
244+
auto Report = checkField(FD, BR, BT_2);
220245
if (Report) {
221246
PathDiagnosticLocation LN = PathDiagnosticLocation::createBegin(
222247
UO, BR.getSourceManager(), mgr.getAnalysisDeclContext(D));

clang/test/Analysis/Checkers/CHERI/subobject-representability-morello.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct R1 {
1111
char a[0x3FFF]; // no warn
1212
} f1good;
1313
struct {
14-
char c;
14+
char c; // expected-note{{}}
1515
char a[0x4000]; // expected-warning{{Field 'a' of type 'char[16384]' (size 16384) requires 8 byte alignment for precise bounds; field offset is 1}}
1616
} f2bad;
1717
struct {
@@ -27,9 +27,9 @@ struct S2 {
2727
};
2828

2929
struct R2 {
30-
char x[0x50];
31-
struct S2 s2;
32-
char c;
33-
char a[0x8000]; // expected-warning{{Field 'a' of type 'char[32768]'}}
34-
char y[32];
35-
};
30+
char x[0x50]; // expected-note{{16/80}}
31+
struct S2 s2; // expected-note{{32/32 bytes exposed (may expose capability!)}}
32+
char c; // expected-note{{1}}
33+
char a[0x20000]; // expected-warning{{Field 'a' of type 'char[131072]' (size 131072) requires 64 byte alignment for precise bounds; field offset is 113 (aligned to 1); Current bounds: 64-131200}}
34+
char y[32]; // expected-note{{15/32}}
35+
};

0 commit comments

Comments
 (0)