@@ -30,6 +30,12 @@ using namespace clang;
3030using namespace ento ;
3131
3232namespace {
33+
34+ template <llvm::CompressedCapability::CapabilityFormat>
35+ std::unique_ptr<BugReport> checkFieldImpl (const FieldDecl *D,
36+ BugReporter &BR,
37+ const BugType &BT);
38+
3339class SubObjectRepresentabilityChecker
3440 : public Checker<check::ASTDecl<RecordDecl>, check::ASTCodeBody> {
3541 BugType BT_1{this , " Field with imprecise subobject bounds" ,
@@ -42,6 +48,21 @@ class SubObjectRepresentabilityChecker
4248 BugReporter &BR) const ;
4349 void checkASTCodeBody (const Decl *D, AnalysisManager &mgr,
4450 BugReporter &BR) const ;
51+
52+ private:
53+
54+ using CheckFieldFn = std::function<std::unique_ptr<BugReport>(
55+ const FieldDecl *D, BugReporter &BR, const BugType &BT)>;
56+
57+ const std::map<llvm::Triple::ArchType, CheckFieldFn> CheckFieldFnMap = {
58+ // {llvm::Triple::aarch64, &checkFieldImpl<CompressedCap128m>},
59+ {llvm::Triple::mips, &checkFieldImpl<llvm::CompressedCapability::Cheri64>},
60+ {llvm::Triple::mips64, &checkFieldImpl<llvm::CompressedCapability::Cheri128>},
61+ {llvm::Triple::riscv32, &checkFieldImpl<llvm::CompressedCapability::Cheri64>},
62+ {llvm::Triple::riscv64, &checkFieldImpl<llvm::CompressedCapability::Cheri128>}
63+ };
64+
65+ CheckFieldFn getCheckFieldFn (ASTContext &ASTCtx) const ;
4566};
4667
4768} // namespace
@@ -116,8 +137,8 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D,
116137 uint64_t Offset = ASTCtx.getFieldOffset (D) / 8 ;
117138 if (Offset > 0 ) {
118139 uint64_t Size = ASTCtx.getTypeSize (T) / 8 ;
119- uint64_t ReqAlign = llvm::CompressedCapability::GetRequiredAlignment (
120- Size, llvm::CompressedCapability::Cheri128 ).value ();
140+ uint64_t ReqAlign =
141+ llvm::CompressedCapability::GetRequiredAlignment (Size, Handler ).value ();
121142 uint64_t CurAlign = 1 << llvm::countr_zero (Offset);
122143 if (CurAlign < ReqAlign) {
123144 /* Emit warning */
@@ -132,15 +153,14 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D,
132153 OS << " field offset is " << Offset;
133154 OS << " (aligned to " << CurAlign << " );" ;
134155
135- # if 0
136- const RecordDecl *Parent = D->getParent() ;
137- uint64_t ParentSize = ASTCtx.getTypeSize(Parent->getTypeForDecl()) / 8 ;
138- typename Handler::cap_t MockCap =
139- getBoundedCap<Handler>(ParentSize, Offset, Size);
140- uint64_t Base = MockCap.base( );
141- uint64_t Top = MockCap.top() ;
156+ uint64_t OffsetToAlign = Offset % ReqAlign;
157+ uint64_t Base = Offset - OffsetToAlign ;
158+ uint64_t AlignedSize = Size + OffsetToAlign ;
159+ uint64_t TailPadding = static_cast < uint64_t >(
160+ llvm::CompressedCapability::GetRequiredTailPadding (AlignedSize,
161+ Handler) );
162+ uint64_t Top = Base + AlignedSize + TailPadding ;
142163 OS << " Current bounds: " << Base << " -" << Top;
143- #endif
144164
145165 // Note that this will fire for every translation unit that uses this
146166 // class. This is suboptimal, but at least scan-build will merge
@@ -151,53 +171,41 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D,
151171 Report->setDeclWithIssue (D);
152172 Report->addRange (D->getSourceRange ());
153173
154- #if 0
155174 Report = reportExposedFields (D, ASTCtx, BR, Base, Top, std::move (Report));
156- #endif
157-
158175 return Report;
159176 }
160177 }
161178
162179 return nullptr ;
163180}
164181
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-
178182} // namespace
179183
184+ SubObjectRepresentabilityChecker::CheckFieldFn
185+ SubObjectRepresentabilityChecker::getCheckFieldFn (ASTContext &ASTCtx) const {
186+ const TargetInfo &TI = ASTCtx.getTargetInfo ();
187+ if (!TI.areAllPointersCapabilities ())
188+ return nullptr ;
189+
190+ auto It = CheckFieldFnMap.find (TI.getTriple ().getArch ());
191+ if (It == CheckFieldFnMap.end ())
192+ return nullptr ;
193+ return It->second ;
194+ }
180195
181196void SubObjectRepresentabilityChecker::checkASTDecl (const RecordDecl *R,
182197 AnalysisManager &mgr,
183198 BugReporter &BR) const {
184- if (!supportedTarget (mgr.getASTContext ()))
185- return ;
199+ CheckFieldFn checkField = getCheckFieldFn (mgr.getASTContext ());
200+ if (!checkField)
201+ return ; // skip this target
186202
187203 if (!R->isCompleteDefinition () || R->isDependentType ())
188204 return ;
189205
190206 if (!R->getLocation ().isValid ())
191207 return ;
192-
193- /*
194- SrcMgr::CharacteristicKind Kind =
195- BR.getSourceManager().getFileCharacteristic(Location);
196- // Ignore records in system headers
197- if (Kind != SrcMgr::C_User)
198- return;
199- */
200-
208+
201209 for (FieldDecl *D : R->fields ()) {
202210 auto Report = checkField (D, BR, BT_1);
203211 if (Report)
@@ -208,8 +216,9 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
208216void SubObjectRepresentabilityChecker::checkASTCodeBody (const Decl *D,
209217 AnalysisManager &mgr,
210218 BugReporter &BR) const {
211- if (!supportedTarget (mgr.getASTContext ()))
212- return ;
219+ CheckFieldFn checkField = getCheckFieldFn (mgr.getASTContext ());
220+ if (!checkField)
221+ return ; // skip this target
213222
214223 using namespace ast_matchers ;
215224 auto Member = memberExpr ().bind (" member" );
0 commit comments