Skip to content

Commit 67197c9

Browse files
eupharinaresistor
authored andcommitted
[CHERI_CSA] AllocationChecker: suppress for bounded suballocations
1 parent a38f36c commit 67197c9

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

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

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@ using EscapePair = std::pair<const MemRegion *, EscapeInfo>;
3737

3838
namespace {
3939
class AllocationChecker
40-
: public Checker<check::PostStmt<CastExpr>, check::PreCall, check::Bind,
41-
check::EndFunction> {
40+
: public Checker<check::PostStmt<CastExpr>, check::PreCall, check::PostCall,
41+
check::Bind, check::EndFunction> {
4242
BugType BT_Default{this, "Allocation partitioning", "CHERI portability"};
4343
BugType BT_KnownReg{this, "Heap or static allocation partitioning",
4444
"CHERI portability"};
4545

4646
const CallDescriptionSet IgnoreFnSet = {
47-
{{CDM::SimpleFunc, {"free"}, 1}},
47+
{CDM::SimpleFunc, {"free"}, 1},
48+
};
49+
50+
const CallDescriptionSet CheriBoundsFnSet = {
51+
{CDM::SimpleFunc, {"cheri_bounds_set"}, 2},
52+
{CDM::SimpleFunc, {"cheri_bounds_set_exact"}, 2},
4853
};
4954

5055
class AllocPartitionBugVisitor : public BugReporterVisitor {
@@ -72,6 +77,7 @@ class AllocationChecker
7277
public:
7378
void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
7479
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
80+
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
7581
void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
7682
void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
7783

@@ -87,6 +93,7 @@ class AllocationChecker
8793
REGISTER_MAP_WITH_PROGRAMSTATE(AllocMap, const MemRegion *, QualType)
8894
REGISTER_MAP_WITH_PROGRAMSTATE(ShiftMap, const MemRegion *, const MemRegion *)
8995
REGISTER_SET_WITH_PROGRAMSTATE(SuballocationSet, const MemRegion *)
96+
REGISTER_SET_WITH_PROGRAMSTATE(BoundedSet, const MemRegion *)
9097

9198
namespace {
9299
std::pair<const MemRegion *, bool> getAllocationStart(const ASTContext &ASTCtx,
@@ -198,21 +205,25 @@ void AllocationChecker::checkPostStmt(const CastExpr *CE,
198205
const MemRegion *MR = SrcVal.getAsRegion();
199206
if (!MR)
200207
return;
201-
const MemSpaceRegion *MemSpace = MR->getMemorySpace();
202-
if (!isa<HeapSpaceRegion, GlobalsSpaceRegion, StackSpaceRegion>(MemSpace))
208+
209+
ProgramStateRef State = C.getState();
210+
if (State->contains<BoundedSet>(MR))
203211
return;
204212

205213
const ASTContext &ASTCtx = C.getASTContext();
206-
ProgramStateRef State = C.getState();
207214
bool Updated = false;
208-
209215
std::pair<const MemRegion *, bool> StartPair =
210216
getAllocationStart(ASTCtx, MR, State);
217+
211218
const MemRegion *SR = StartPair.first;
212219
if (!isAllocation(SR))
213220
return;
214221
bool ZeroShift = StartPair.second;
215222

223+
const MemSpaceRegion *MemSpace = SR->getMemorySpace();
224+
if (!isa<HeapSpaceRegion, GlobalsSpaceRegion, StackSpaceRegion>(MemSpace))
225+
return;
226+
216227
SVal DstVal = C.getSVal(CE);
217228
const MemRegion *DMR = DstVal.getAsRegion();
218229
if (MR->getAs<ElementRegion>() && (!DMR || !DMR->getAs<ElementRegion>())) {
@@ -258,7 +269,7 @@ void AllocationChecker::checkPostStmt(const CastExpr *CE,
258269

259270
void AllocationChecker::checkPreCall(const CallEvent &Call,
260271
CheckerContext &C) const {
261-
if (IgnoreFnSet.contains(Call))
272+
if (IgnoreFnSet.contains(Call) || CheriBoundsFnSet.contains(Call))
262273
return;
263274

264275
ProgramStateRef State = C.getState();
@@ -303,6 +314,25 @@ void AllocationChecker::checkPreCall(const CallEvent &Call,
303314
C.addTransition(State, N ? N : C.getPredecessor());
304315
}
305316

317+
void AllocationChecker::checkPostCall(const CallEvent &Call,
318+
CheckerContext &C) const {
319+
if (!CheriBoundsFnSet.contains(Call))
320+
return;
321+
const MemRegion *MR = C.getSVal(Call.getArgExpr(0)).getAsRegion();
322+
const MemRegion *ResMR = C.getSVal(Call.getOriginExpr()).getAsRegion();
323+
if (!MR || !ResMR)
324+
return;
325+
326+
ProgramStateRef State = C.getState();
327+
if (!State->contains<SuballocationSet>(MR) ||
328+
!State->contains<SuballocationSet>(ResMR))
329+
return;
330+
331+
State = State->remove<SuballocationSet>(ResMR);
332+
State = State->add<BoundedSet>(ResMR);
333+
C.addTransition(State);
334+
}
335+
306336
void AllocationChecker::checkBind(SVal L, SVal V, const Stmt *S,
307337
CheckerContext &C) const {
308338
const MemRegion *Dst = L.getAsRegion();

clang/test/Analysis/Checkers/CHERI/allocation.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %cheri_purecap_cc1 -analyze -verify %s \
2-
// RUN: -analyzer-checker=core,unix,alpha.cheri.Allocation
2+
// RUN: -analyzer-checker=core,unix,alpha.cheri.Allocation,cheri.CheriAPIModelling
33

44
typedef __typeof__(sizeof(int)) size_t;
55
extern void * malloc(size_t);
@@ -81,3 +81,11 @@ void test_6(int n1, int n2) {
8181
struct S2 **p2 = (struct S2 **)(p1+n1);
8282
foo(p2); // no warn
8383
}
84+
85+
void *cheri_bounds_set(void *c, size_t x);
86+
void test_7(int n1, int n2) {
87+
struct S1 *p1 = malloc(sizeof(struct S1)*n1 + sizeof(struct S2)*n2);
88+
struct S2 *p2 = (struct S2 *)(p1+n1);
89+
struct S2 *p3 = cheri_bounds_set(p2, sizeof(struct S2)*n2);
90+
foo(p3); // no-warn
91+
}

0 commit comments

Comments
 (0)