@@ -30,6 +30,11 @@ using namespace clang;
3030using namespace ento ;
3131
3232namespace {
33+
34+ template <llvm::CompressedCapability::CapabilityFormat>
35+ std::unique_ptr<BugReport> checkFieldImpl (const FieldDecl *D, BugReporter &BR,
36+ const BugType &BT);
37+
3338class SubObjectRepresentabilityChecker
3439 : public Checker<check::ASTDecl<RecordDecl>, check::ASTCodeBody> {
3540 BugType BT_1{this , " Field with imprecise subobject bounds" ,
@@ -42,6 +47,23 @@ class SubObjectRepresentabilityChecker
4247 BugReporter &BR) const ;
4348 void checkASTCodeBody (const Decl *D, AnalysisManager &mgr,
4449 BugReporter &BR) const ;
50+
51+ private:
52+ using CheckFieldFn = std::function<std::unique_ptr<BugReport>(
53+ const FieldDecl *D, BugReporter &BR, const BugType &BT)>;
54+
55+ const std::map<llvm::Triple::ArchType, CheckFieldFn> CheckFieldFnMap = {
56+ // {llvm::Triple::aarch64, &checkFieldImpl<CompressedCap128m>},
57+ {llvm::Triple::mips,
58+ &checkFieldImpl<llvm::CompressedCapability::Cheri64>},
59+ {llvm::Triple::mips64,
60+ &checkFieldImpl<llvm::CompressedCapability::Cheri128>},
61+ {llvm::Triple::riscv32,
62+ &checkFieldImpl<llvm::CompressedCapability::Cheri64>},
63+ {llvm::Triple::riscv64,
64+ &checkFieldImpl<llvm::CompressedCapability::Cheri128>}};
65+
66+ CheckFieldFn getCheckFieldFn (ASTContext &ASTCtx) const ;
4567};
4668
4769} // namespace
@@ -112,9 +134,8 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D, BugReporter &BR,
112134 uint64_t Offset = ASTCtx.getFieldOffset (D) / 8 ;
113135 if (Offset > 0 ) {
114136 uint64_t Size = ASTCtx.getTypeSize (T) / 8 ;
115- uint64_t ReqAlign = llvm::CompressedCapability::GetRequiredAlignment (
116- Size, llvm::CompressedCapability::Cheri128)
117- .value ();
137+ uint64_t ReqAlign =
138+ llvm::CompressedCapability::GetRequiredAlignment (Size, Handler).value ();
118139 uint64_t CurAlign = 1 << llvm::countr_zero (Offset);
119140 if (CurAlign < ReqAlign) {
120141 /* Emit warning */
@@ -129,15 +150,14 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D, BugReporter &BR,
129150 OS << " field offset is " << Offset;
130151 OS << " (aligned to " << CurAlign << " );" ;
131152
132- # if 0
133- const RecordDecl *Parent = D->getParent() ;
134- uint64_t ParentSize = ASTCtx.getTypeSize(Parent->getTypeForDecl()) / 8 ;
135- typename Handler::cap_t MockCap =
136- getBoundedCap<Handler>(ParentSize, Offset, Size);
137- uint64_t Base = MockCap.base( );
138- uint64_t Top = MockCap.top() ;
153+ uint64_t OffsetToAlign = Offset % ReqAlign;
154+ uint64_t Base = Offset - OffsetToAlign ;
155+ uint64_t AlignedSize = Size + OffsetToAlign ;
156+ uint64_t TailPadding = static_cast < uint64_t >(
157+ llvm::CompressedCapability::GetRequiredTailPadding (AlignedSize,
158+ Handler) );
159+ uint64_t Top = Base + AlignedSize + TailPadding ;
139160 OS << " Current bounds: " << Base << " -" << Top;
140- #endif
141161
142162 // Note that this will fire for every translation unit that uses this
143163 // class. This is suboptimal, but at least scan-build will merge
@@ -148,51 +168,41 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D, BugReporter &BR,
148168 Report->setDeclWithIssue (D);
149169 Report->addRange (D->getSourceRange ());
150170
151- #if 0
152171 Report = reportExposedFields (D, ASTCtx, BR, Base, Top, std::move (Report));
153- #endif
154-
155172 return Report;
156173 }
157174 }
158175
159176 return nullptr ;
160177}
161178
162- std::unique_ptr<BugReport> checkField (const FieldDecl *D, BugReporter &BR,
163- const BugType &BT) {
164- // TODO: other targets
165- return checkFieldImpl<llvm::CompressedCapability::Cheri128>(D, BR, BT);
166- }
179+ } // namespace
167180
168- bool supportedTarget ( const ASTContext &C) {
169- const TargetInfo &TI = C. getTargetInfo ();
170- return TI. areAllPointersCapabilities () &&
171- TI.getTriple (). isAArch64 (); // morello
172- }
181+ SubObjectRepresentabilityChecker::CheckFieldFn
182+ SubObjectRepresentabilityChecker::getCheckFieldFn (ASTContext &ASTCtx) const {
183+ const TargetInfo &TI = ASTCtx. getTargetInfo ();
184+ if (! TI.areAllPointersCapabilities ())
185+ return nullptr ;
173186
174- } // namespace
187+ auto It = CheckFieldFnMap.find (TI.getTriple ().getArch ());
188+ if (It == CheckFieldFnMap.end ())
189+ return nullptr ;
190+ return It->second ;
191+ }
175192
176193void SubObjectRepresentabilityChecker::checkASTDecl (const RecordDecl *R,
177194 AnalysisManager &mgr,
178195 BugReporter &BR) const {
179- if (!supportedTarget (mgr.getASTContext ()))
180- return ;
196+ CheckFieldFn checkField = getCheckFieldFn (mgr.getASTContext ());
197+ if (!checkField)
198+ return ; // skip this target
181199
182200 if (!R->isCompleteDefinition () || R->isDependentType ())
183201 return ;
184202
185203 if (!R->getLocation ().isValid ())
186204 return ;
187205
188- /*
189- SrcMgr::CharacteristicKind Kind =
190- BR.getSourceManager().getFileCharacteristic(Location);
191- // Ignore records in system headers
192- if (Kind != SrcMgr::C_User)
193- return;
194- */
195-
196206 for (FieldDecl *D : R->fields ()) {
197207 auto Report = checkField (D, BR, BT_1);
198208 if (Report)
@@ -203,8 +213,9 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
203213void SubObjectRepresentabilityChecker::checkASTCodeBody (const Decl *D,
204214 AnalysisManager &mgr,
205215 BugReporter &BR) const {
206- if (!supportedTarget (mgr.getASTContext ()))
207- return ;
216+ CheckFieldFn checkField = getCheckFieldFn (mgr.getASTContext ());
217+ if (!checkField)
218+ return ; // skip this target
208219
209220 using namespace ast_matchers ;
210221 auto Member = memberExpr ().bind (" member" );
0 commit comments