Skip to content

Commit 07ed382

Browse files
Fixing Bounds issue with Function Parameters (#582)
* Fixing Bounds issue with Function Parameters * Update clang/test/3C/func_parm_bounds.c Co-authored-by: Matt McCutchen (Correct Computation) <[email protected]> Co-authored-by: Matt McCutchen (Correct Computation) <[email protected]>
1 parent abc1f9c commit 07ed382

File tree

6 files changed

+102
-17
lines changed

6 files changed

+102
-17
lines changed

clang/include/clang/3C/ABounds.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,16 @@ class ABounds {
4141
protected:
4242
ABounds(BoundsKind K) : Kind(K) {}
4343
void addBoundsUsedKey(BoundsKey);
44+
// Get the variable name of the the given bounds key that corresponds
45+
// to the given declaration.
46+
static std::string getBoundsKeyStr(BoundsKey ,
47+
AVarBoundsInfo *,
48+
clang::Decl *);
4449

4550
public:
4651
virtual ~ABounds() {}
4752

48-
virtual std::string mkString(AVarBoundsInfo *) = 0;
53+
virtual std::string mkString(AVarBoundsInfo *, clang::Decl *D = nullptr) = 0;
4954
virtual bool areSame(ABounds *, AVarBoundsInfo *) = 0;
5055
virtual BoundsKey getBKey() = 0;
5156
virtual ABounds *makeCopy(BoundsKey NK) = 0;
@@ -67,7 +72,7 @@ class CountBound : public ABounds {
6772

6873
virtual ~CountBound() {}
6974

70-
std::string mkString(AVarBoundsInfo *ABI) override;
75+
std::string mkString(AVarBoundsInfo *ABI, clang::Decl *D = nullptr) override;
7176
bool areSame(ABounds *O, AVarBoundsInfo *ABI) override;
7277
BoundsKey getBKey() override;
7378
ABounds *makeCopy(BoundsKey NK) override;
@@ -90,7 +95,7 @@ class ByteBound : public ABounds {
9095

9196
virtual ~ByteBound() {}
9297

93-
std::string mkString(AVarBoundsInfo *ABI) override;
98+
std::string mkString(AVarBoundsInfo *ABI, clang::Decl *D = nullptr) override;
9499
bool areSame(ABounds *O, AVarBoundsInfo *ABI) override;
95100
BoundsKey getBKey() override;
96101
ABounds *makeCopy(BoundsKey NK) override;
@@ -113,7 +118,7 @@ class RangeBound : public ABounds {
113118

114119
virtual ~RangeBound() {}
115120

116-
std::string mkString(AVarBoundsInfo *ABI) override;
121+
std::string mkString(AVarBoundsInfo *ABI, clang::Decl *D = nullptr) override;
117122
bool areSame(ABounds *O, AVarBoundsInfo *ABI) override;
118123

119124
BoundsKey getBKey() override {

clang/include/clang/3C/AVarBoundsInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ class AVarBoundsInfo {
255255

256256
bool areSameProgramVar(BoundsKey B1, BoundsKey B2);
257257

258+
// Check if the provided BoundsKey is for a function param?
259+
// If yes, provide the index of the parameter.
260+
bool isFuncParamBoundsKey(BoundsKey BK, unsigned &PIdx);
261+
258262
private:
259263
friend class AvarBoundsInference;
260264
friend class CtxSensitiveBoundsKeyHandler;

clang/lib/3C/ABounds.cpp

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,29 @@ ABounds *ABounds::getBoundsInfo(AVarBoundsInfo *ABInfo, BoundsExpr *BExpr,
5656
return Ret;
5757
}
5858

59-
std::string CountBound::mkString(AVarBoundsInfo *ABI) {
60-
ProgramVar *PV = ABI->getProgramVar(CountVar);
59+
std::string ABounds::getBoundsKeyStr(BoundsKey BK,
60+
AVarBoundsInfo *ABI,
61+
Decl *D) {
62+
ProgramVar *PV = ABI->getProgramVar(BK);
6163
assert(PV != nullptr && "No Valid program var");
62-
return "count(" + PV->mkString() + ")";
64+
std::string BKStr = PV->mkString();
65+
unsigned PIdx = 0;
66+
auto *PVD = dyn_cast_or_null<ParmVarDecl>(D);
67+
// Does this belong to a function parameter?
68+
if (PVD && ABI->isFuncParamBoundsKey(BK, PIdx)) {
69+
// Then get the corresponding parameter in context of the given
70+
// Function and get its name.
71+
const FunctionDecl *FD = dyn_cast<FunctionDecl>(PVD->getDeclContext());
72+
if (FD->getNumParams() > PIdx) {
73+
auto *NewPVD = FD->getParamDecl(PIdx);
74+
BKStr = NewPVD->getNameAsString();
75+
}
76+
}
77+
return BKStr;
78+
}
79+
80+
std::string CountBound::mkString(AVarBoundsInfo *ABI, clang::Decl *D) {
81+
return "count(" + ABounds::getBoundsKeyStr(CountVar, ABI, D) + ")";
6382
}
6483

6584
bool CountBound::areSame(ABounds *O, AVarBoundsInfo *ABI) {
@@ -74,10 +93,8 @@ BoundsKey CountBound::getBKey() { return this->CountVar; }
7493

7594
ABounds *CountBound::makeCopy(BoundsKey NK) { return new CountBound(NK); }
7695

77-
std::string ByteBound::mkString(AVarBoundsInfo *ABI) {
78-
ProgramVar *PV = ABI->getProgramVar(ByteVar);
79-
assert(PV != nullptr && "No Valid program var");
80-
return "byte_count(" + PV->mkString() + ")";
96+
std::string ByteBound::mkString(AVarBoundsInfo *ABI, clang::Decl *D) {
97+
return "byte_count(" + ABounds::getBoundsKeyStr(ByteVar, ABI, D) + ")";
8198
}
8299

83100
bool ByteBound::areSame(ABounds *O, AVarBoundsInfo *ABI) {
@@ -93,11 +110,11 @@ BoundsKey ByteBound::getBKey() { return this->ByteVar; }
93110

94111
ABounds *ByteBound::makeCopy(BoundsKey NK) { return new ByteBound(NK); }
95112

96-
std::string RangeBound::mkString(AVarBoundsInfo *ABI) {
97-
ProgramVar *LBVar = ABI->getProgramVar(LB);
98-
ProgramVar *UBVar = ABI->getProgramVar(UB);
99-
assert(LBVar != nullptr && UBVar != nullptr && "No Valid program var");
100-
return "bounds(" + LBVar->mkString() + ", " + UBVar->mkString() + ")";
113+
114+
std::string RangeBound::mkString(AVarBoundsInfo *ABI, clang::Decl *D) {
115+
std::string LBStr = ABounds::getBoundsKeyStr(LB, ABI, D);
116+
std::string UBStr = ABounds::getBoundsKeyStr(UB, ABI, D);
117+
return "bounds(" + LBStr + ", " + UBStr + ")";
101118
}
102119

103120
bool RangeBound::areSame(ABounds *O, AVarBoundsInfo *ABI) {

clang/lib/3C/AVarBoundsInfo.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,16 @@ bool AVarBoundsInfo::areSameProgramVar(BoundsKey B1, BoundsKey B2) {
14031403
return B1 == B2;
14041404
}
14051405

1406+
bool AVarBoundsInfo::isFuncParamBoundsKey(BoundsKey BK, unsigned &PIdx) {
1407+
auto &ParmBkeyToPSL = ParamDeclVarMap.right();
1408+
if (ParmBkeyToPSL.find(BK) != ParmBkeyToPSL.end()) {
1409+
auto &ParmTup = ParmBkeyToPSL.at(BK);
1410+
PIdx = std::get<3>(ParmTup);
1411+
return true;
1412+
}
1413+
return false;
1414+
}
1415+
14061416
std::set<BoundsKey>
14071417
AVarBoundsInfo::getCtxSensFieldBoundsKey(Expr *E, ASTContext *C,
14081418
ProgramInfo &I) {

clang/lib/3C/RewriteUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ std::string ArrayBoundsRewriter::getBoundsString(const PVConstraint *PV,
597597
ABounds *ArrB = ABInfo.getBounds(DK);
598598
// Only we we have bounds and no pointer arithmetic on the variable.
599599
if (ArrB != nullptr && !ABInfo.hasPointerArithmetic(DK)) {
600-
BString = ArrB->mkString(&ABInfo);
600+
BString = ArrB->mkString(&ABInfo, D);
601601
if (!BString.empty())
602602
BString = Pfix + BString;
603603
}

clang/test/3C/func_parm_bounds.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
Test for parameter bounds with parameter with in the declaration.
3+
Issue: https://github.com/correctcomputation/checkedc-clang/issues/573
4+
**/
5+
6+
// RUN: rm -rf %t*
7+
// RUN: 3c -base-dir=%S -alltypes %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL" %s
8+
// RUN: 3c -base-dir=%S -alltypes %s -- | %clang -c -fcheckedc-extension -x c -o %t1.unusedl -
9+
// RUN: 3c -base-dir=%S %s -- | %clang -c -fcheckedc-extension -x c -o %t2.unused -
10+
11+
#include <stdlib.h>
12+
13+
int gsize;
14+
int *glob;
15+
//CHECK_ALL: _Array_ptr<int> glob : count(gsize) = ((void *)0);
16+
17+
int foo(int *c, int z);
18+
int foo(int *c, int l) {
19+
if (0 < l) return c[0];
20+
return 0;
21+
}
22+
//CHECK_ALL: int foo(_Array_ptr<int> c : count(z), int z);
23+
//CHECK_ALL: int foo(_Array_ptr<int> c : count(l), int l) {
24+
25+
int consfoo(int *c);
26+
int consfoo(int *c) {
27+
return c[0];
28+
}
29+
//CHECK_ALL: int consfoo(_Array_ptr<int> c : count(5));
30+
//CHECK_ALL: int consfoo(_Array_ptr<int> c : count(5)) {
31+
32+
int globalfoo(int *c);
33+
int globalfoo(int *c) {
34+
return c[0];
35+
}
36+
//CHECK_ALL: int globalfoo(_Array_ptr<int> c : count(gsize));
37+
//CHECK_ALL: int globalfoo(_Array_ptr<int> c : count(gsize)) {
38+
39+
int caller() {
40+
int arr[5];
41+
gsize = 100;
42+
glob = malloc(gsize*sizeof(int));
43+
glob[0] = 1;
44+
globalfoo(glob);
45+
consfoo(arr);
46+
return 0;
47+
}
48+
//CHECK_ALL: int arr _Checked[5];
49+
//CHECK_ALL: glob = _Assume_bounds_cast<_Array_ptr<int>>(malloc(gsize*sizeof(int)), byte_count(0));

0 commit comments

Comments
 (0)