Skip to content

Commit 1b21a2e

Browse files
author
MalavikaSamak
committed
[-Wunsafe-buffer-usage] Suppress warning when 2-D constant arrays are indexed
Do not warn about unsafe buffer access, when 2-D constant arrays are accessed and the indices are within the bounds of the buffer. Warning in such cases is a false postive. Such a suppression aleady exists for 1-d arrays and it is now extended to 2-D arrays. (rdar://137926311)
1 parent 7f19b1e commit 1b21a2e

File tree

5 files changed

+68
-40
lines changed

5 files changed

+68
-40
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -433,20 +433,56 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
433433
// already duplicated
434434
// - call both from Sema and from here
435435

436-
const auto *BaseDRE =
436+
auto CheckBounds = [](const ArraySubscriptExpr *ASE, uint64_t limit) -> bool {
437+
if (const auto *IdxLit = dyn_cast<IntegerLiteral>(ASE->getIdx())) {
438+
const APInt ArrIdx = IdxLit->getValue();
439+
if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < limit)
440+
return true;
441+
}
442+
return false;
443+
};
444+
445+
const auto *BaseASE =
446+
dyn_cast<ArraySubscriptExpr>(Node.getBase()->IgnoreParenImpCasts());
447+
uint64_t size = 0;
448+
449+
if (BaseASE) {
450+
const auto *DRE =
451+
dyn_cast<DeclRefExpr>(BaseASE->getBase()->IgnoreParenImpCasts());
452+
453+
if (!DRE)
454+
return false;
455+
456+
const auto *CATy = dyn_cast<ConstantArrayType>(
457+
DRE->getType()->getUnqualifiedDesugaredType());
458+
if (!CATy) {
459+
return false;
460+
}
461+
size = CATy->getLimitedSize();
462+
463+
if (!CheckBounds(BaseASE, size))
464+
return false;
465+
466+
CATy = Finder->getASTContext().getAsConstantArrayType(BaseASE->getType());
467+
if (!CATy) {
468+
return false;
469+
}
470+
471+
size = CATy->getLimitedSize();
472+
return CheckBounds(&Node, size);
473+
}
474+
475+
const DeclRefExpr *BaseDRE =
437476
dyn_cast<DeclRefExpr>(Node.getBase()->IgnoreParenImpCasts());
438477
const auto *SLiteral =
439478
dyn_cast<StringLiteral>(Node.getBase()->IgnoreParenImpCasts());
440-
uint64_t size;
441479

442480
if (!BaseDRE && !SLiteral)
443481
return false;
444482

445483
if (BaseDRE) {
446-
if (!BaseDRE->getDecl())
447-
return false;
448-
const auto *CATy = Finder->getASTContext().getAsConstantArrayType(
449-
BaseDRE->getDecl()->getType());
484+
const auto *CATy =
485+
Finder->getASTContext().getAsConstantArrayType(BaseDRE->getType());
450486
if (!CATy) {
451487
return false;
452488
}
@@ -455,15 +491,7 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
455491
size = SLiteral->getLength() + 1;
456492
}
457493

458-
if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx())) {
459-
const APInt ArrIdx = IdxLit->getValue();
460-
// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a
461-
// bug
462-
if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < size)
463-
return true;
464-
}
465-
466-
return false;
494+
return CheckBounds(&Node, size);
467495
}
468496

469497
AST_MATCHER_P(CallExpr, hasNumArgs, unsigned, Num) {
@@ -1172,6 +1200,12 @@ class ArraySubscriptGadget : public WarningGadget {
11721200
if (const auto *DRE =
11731201
dyn_cast<DeclRefExpr>(ASE->getBase()->IgnoreParenImpCasts())) {
11741202
return {DRE};
1203+
} else if (const auto *BaseASE = dyn_cast<ArraySubscriptExpr>(
1204+
ASE->getBase()->IgnoreParenImpCasts())) {
1205+
if (const auto *DRE = dyn_cast<DeclRefExpr>(
1206+
BaseASE->getBase()->IgnoreParenImpCasts())) {
1207+
return {DRE};
1208+
}
11751209
}
11761210

11771211
return {};

clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,9 @@ void constant_id_string(unsigned idx) {
5252
unsafe_char = ""[1]; //expected-warning{{unsafe buffer access}}
5353
unsafe_char = ""[idx]; //expected-warning{{unsafe buffer access}}
5454
}
55+
56+
typedef float Float4x4[4][4];
57+
58+
float multi_dimension_array(Float4x4& matrix) {
59+
return matrix[1][1];
60+
}

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-main.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@
88
// main function
99
int main(int argc, char *argv[]) { // expected-warning{{'argv' is an unsafe pointer used for buffer access}}
1010
char tmp;
11-
tmp = argv[5][5]; // expected-note{{used in buffer access here}} \
12-
expected-warning{{unsafe buffer access}}
11+
tmp = argv[5][5]; // expected-note2{{used in buffer access here}}
1312
}

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void isArrayDecayToPointerUPC(int a[][10], int (*b)[10]) {
118118
// expected-warning@-2{{'b' is an unsafe pointer used for buffer access}}
119119
int tmp;
120120

121-
tmp = a[5][5] + b[5][5]; // expected-warning2{{unsafe buffer access}} expected-note2{{used in buffer access here}}
121+
tmp = a[5][5] + b[5][5]; // expected-note4{{used in buffer access here}}
122122
}
123123

124124
// parameter having default values:

clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,9 @@ void testArraySubscripts(int idx, int *p, int **pp) {
4040
// expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
4141
// expected-warning@-2{{'pp' is an unsafe pointer used for buffer access}}
4242
foo(p[1], // expected-note{{used in buffer access here}}
43-
pp[1][1], // expected-note{{used in buffer access here}}
44-
// expected-warning@-1{{unsafe buffer access}}
45-
1[1[pp]], // expected-note{{used in buffer access here}}
46-
// expected-warning@-1{{unsafe buffer access}}
47-
1[pp][1] // expected-note{{used in buffer access here}}
48-
// expected-warning@-1{{unsafe buffer access}}
43+
pp[1][1], // expected-note2{{used in buffer access here}}
44+
1[1[pp]], // expected-note2{{used in buffer access here}}
45+
1[pp][1] // expected-note2{{used in buffer access here}}
4946
);
5047

5148
if (p[3]) { // expected-note{{used in buffer access here}}
@@ -65,13 +62,9 @@ void testArraySubscripts(int idx, int *p, int **pp) {
6562
int b[10][10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
6663

6764
foo(a[idx], idx[a], // expected-note2{{used in buffer access here}}
68-
b[idx][idx + 1], // expected-warning{{unsafe buffer access}}
69-
// expected-note@-1{{used in buffer access here}}
70-
(idx + 1)[b][idx],// expected-warning{{unsafe buffer access}}
71-
// expected-note@-1{{used in buffer access here}}
72-
(idx + 1)[idx[b]]);
73-
// expected-warning@-1{{unsafe buffer access}}
74-
// expected-note@-2{{used in buffer access here}}
65+
b[idx][idx + 1], // expected-note2{{used in buffer access here}}
66+
(idx + 1)[b][idx],// expected-note2{{used in buffer access here}}
67+
(idx + 1)[idx[b]]); // expected-note2{{used in buffer access here}}
7568

7669
// Not to warn when index is zero
7770
foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0],
@@ -108,8 +101,7 @@ void testQualifiedParameters(const int * p, const int * const q, const int a[10]
108101
foo(p[1], 1[p], p[-1], // expected-note3{{used in buffer access here}}
109102
q[1], 1[q], q[-1], // expected-note3{{used in buffer access here}}
110103
a[1], // expected-note{{used in buffer access here}} `a` is of pointer type
111-
b[1][2] // expected-note{{used in buffer access here}} `b[1]` is of array type
112-
// expected-warning@-1{{unsafe buffer access}}
104+
b[1][2] // expected-note2{{used in buffer access here}} `b[1]` is of array type
113105
);
114106
}
115107

@@ -223,10 +215,9 @@ template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) {
223215
// expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
224216
// expected-warning@-2{{'pt' is an unsafe pointer used for buffer access}}
225217
// expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}
226-
// expected-warning@-4{{'b' is an unsafe buffer that does not perform bounds checks}}
227218
foo(pt[1], // expected-note{{used in buffer access here}}
228219
a[1], // expected-note{{used in buffer access here}}
229-
b[1]); // expected-note{{used in buffer access here}}
220+
b[1]);
230221
return &t[1]; // expected-note{{used in buffer access here}}
231222
}
232223

@@ -366,17 +357,15 @@ int testArrayAccesses(int n, int idx) {
366357
// expected-warning@-1{{'cArr' is an unsafe buffer that does not perform bounds checks}}
367358
int d = cArr[0][0];
368359
foo(cArr[0][0]);
369-
foo(cArr[idx][idx + 1]); // expected-note{{used in buffer access here}}
370-
// expected-warning@-1{{unsafe buffer access}}
371-
auto cPtr = cArr[idx][idx * 2]; // expected-note{{used in buffer access here}}
372-
// expected-warning@-1{{unsafe buffer access}}
360+
foo(cArr[idx][idx + 1]); // expected-note2{{used in buffer access here}}
361+
auto cPtr = cArr[idx][idx * 2]; // expected-note2{{used in buffer access here}}
373362
foo(cPtr);
374363

375364
// Typdefs
376365
typedef int A[3];
377366
const A tArr = {4, 5, 6};
378367
foo(tArr[0], tArr[1]);
379-
return cArr[0][1]; // expected-warning{{unsafe buffer access}}
368+
return cArr[0][1];
380369
}
381370

382371
void testArrayPtrArithmetic(int x[]) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}

0 commit comments

Comments
 (0)