Skip to content

Commit fdf3f22

Browse files
eupharinaresistor
authored andcommitted
[CHERI_CSA] SubObjectRepresentability: detailed message
1 parent cb452eb commit fdf3f22

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

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

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17+
#include "CHERIUtils.h"
1718
#include "clang/AST/StmtVisitor.h"
1819
#include "clang/ASTMatchers/ASTMatchFinder.h"
1920
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
@@ -31,6 +32,9 @@ using namespace ento;
3132
namespace {
3233
class SubObjectRepresentabilityChecker
3334
: public Checker<check::ASTDecl<RecordDecl>> {
35+
BugType BT_1{this, "Field with imprecise subobject bounds",
36+
"CHERI portability"};
37+
3438
public:
3539
void checkASTDecl(const RecordDecl *R, AnalysisManager &mgr,
3640
BugReporter &BR) const;
@@ -65,7 +69,8 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
6569
uint64_t ReqAlign = llvm::CompressedCapability::GetRequiredAlignment(
6670
Size, llvm::CompressedCapability::Cheri128)
6771
.value();
68-
if (1 << llvm::countr_zero(Offset) < ReqAlign) {
72+
uint64_t CurAlign = 1 << llvm::countr_zero(Offset);
73+
if (CurAlign < ReqAlign) {
6974
/* Emit warning */
7075
SmallString<1024> Err;
7176
llvm::raw_svector_ostream OS(Err);
@@ -76,14 +81,64 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
7681
OS << " (size " << Size << ")";
7782
OS << " requires " << ReqAlign << " byte alignment for precise bounds;";
7883
OS << " field offset is " << Offset;
84+
OS << " (aligned to " << CurAlign << ");";
85+
86+
#if 0
87+
// CHERIOT FIXME: Get rid of dependency on compressed-cap-lib
88+
using Handler = CompressedCap128;
89+
uint64_t ParentSize = ASTCtx.getTypeSize(R->getTypeForDecl())/8;
90+
Handler::addr_t InitLength = Handler ::representable_length(ParentSize);
91+
Handler::cap_t MockCap = Handler::make_max_perms_cap(0, 0, InitLength);
92+
bool exact = Handler::setbounds(&MockCap, Offset, Offset + Size);
93+
assert(!exact);
94+
auto Base = MockCap.base();
95+
Handler::addr_t Top = MockCap.top();
96+
OS << " Current bounds: " << Base << "-" << Top;
97+
#endif
98+
99+
PathDiagnosticLocation L =
100+
PathDiagnosticLocation::createBegin(D, BR.getSourceManager());
101+
auto Report = std::make_unique<BasicBugReport>(BT_1, OS.str(), L);
102+
Report->setDeclWithIssue(D);
103+
Report->addRange(D->getSourceRange());
104+
105+
#if 0
106+
// CHERIOT FIXME: Get rid of dependency on compressed-cap-lib
107+
auto FI = R->field_begin();
108+
while (FI != R->field_end() &&
109+
ASTCtx.getFieldOffset(*FI)/8
110+
+ ASTCtx.getTypeSize(FI->getType())/8 <= Base)
111+
FI++;
112+
113+
bool Before = true;
114+
while (FI != R->field_end() && ASTCtx.getFieldOffset(*FI)/8 < Top) {
115+
if (*FI != D) {
116+
SmallString<1024> Note;
117+
llvm::raw_svector_ostream OS2(Note);
118+
119+
uint64_t CurFieldOffset = ASTCtx.getFieldOffset(*FI)/8;
120+
uint64_t CurFieldSize = ASTCtx.getTypeSize(FI->getType())/8;
121+
uint64_t BytesExposed =
122+
Before ? std::min(CurFieldSize,
123+
CurFieldOffset + CurFieldSize - Base)
124+
: std::min(CurFieldSize, Top - CurFieldOffset);
125+
OS2 << BytesExposed << "/" << CurFieldSize << " bytes exposed";
126+
if (cheri::hasCapability(FI->getType(), ASTCtx))
127+
OS2 << " (may expose capability!)";
128+
129+
PathDiagnosticLocation LN =
130+
PathDiagnosticLocation::createBegin(*FI, BR.getSourceManager());
131+
Report->addNote(OS2.str(), LN);
132+
} else
133+
Before = false;
134+
FI++;
135+
}
136+
#endif
79137

80138
// Note that this will fire for every translation unit that uses this
81139
// class. This is suboptimal, but at least scan-build will merge
82140
// duplicate HTML reports.
83-
PathDiagnosticLocation L =
84-
PathDiagnosticLocation::createBegin(D, BR.getSourceManager());
85-
BR.EmitBasicReport(R, this, "Field with imprecise subobject bounds",
86-
"CHERI portability", OS.str(), L);
141+
BR.emitReport(std::move(Report));
87142
}
88143
}
89144
}

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

Lines changed: 14 additions & 1 deletion
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 {
@@ -20,3 +20,16 @@ struct R1 {
2020
} f3good __attribute__((aligned(8)));
2121
} s2;
2222
} s1;
23+
24+
struct S2 {
25+
int x[3];
26+
int *px;
27+
};
28+
29+
struct R2 {
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[0x8000]; // expected-warning{{Field 'a' of type 'char[32768]'}}
34+
char y[32]; // expected-note{{15/32}}
35+
};

0 commit comments

Comments
 (0)