Skip to content

Commit 9c50182

Browse files
malavikasamakMalavikaSamak
andauthored
[-Wunsafe-buffer-usage] Suppress warning for multi-dimensional constant arrays (#118249)
Do not warn about unsafe buffer access, when multi-dimensional constant arrays are accessed and their indices are within the bounds of the buffer. Warning in such cases would be a false positive. Such a suppression already exists for 1-d arrays and it is now extended to multi-dimensional arrays. (rdar://137926311) (rdar://140320139) Co-authored-by: MalavikaSamak <[email protected]>
1 parent 9992b16 commit 9c50182

File tree

5 files changed

+77
-40
lines changed

5 files changed

+77
-40
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -439,36 +439,25 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
439439
// already duplicated
440440
// - call both from Sema and from here
441441

442-
const auto *BaseDRE =
443-
dyn_cast<DeclRefExpr>(Node.getBase()->IgnoreParenImpCasts());
444-
const auto *SLiteral =
445-
dyn_cast<StringLiteral>(Node.getBase()->IgnoreParenImpCasts());
446-
uint64_t size;
447-
448-
if (!BaseDRE && !SLiteral)
442+
uint64_t limit;
443+
if (const auto *CATy =
444+
dyn_cast<ConstantArrayType>(Node.getBase()
445+
->IgnoreParenImpCasts()
446+
->getType()
447+
->getUnqualifiedDesugaredType())) {
448+
limit = CATy->getLimitedSize();
449+
} else if (const auto *SLiteral = dyn_cast<StringLiteral>(
450+
Node.getBase()->IgnoreParenImpCasts())) {
451+
limit = SLiteral->getLength() + 1;
452+
} else {
449453
return false;
450-
451-
if (BaseDRE) {
452-
if (!BaseDRE->getDecl())
453-
return false;
454-
const auto *CATy = Finder->getASTContext().getAsConstantArrayType(
455-
BaseDRE->getDecl()->getType());
456-
if (!CATy) {
457-
return false;
458-
}
459-
size = CATy->getLimitedSize();
460-
} else if (SLiteral) {
461-
size = SLiteral->getLength() + 1;
462454
}
463455

464456
if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx())) {
465457
const APInt ArrIdx = IdxLit->getValue();
466-
// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a
467-
// bug
468-
if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < size)
458+
if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < limit)
469459
return true;
470460
}
471-
472461
return false;
473462
}
474463

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,43 @@ 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+
// expected-warning@+1 {{'matrix' is an unsafe buffer that does not perform bounds checks}}
59+
float two_dimension_array(Float4x4& matrix, unsigned idx) {
60+
// expected-warning@+1{{unsafe buffer access}}
61+
float a = matrix[0][4];
62+
63+
a = matrix[0][3];
64+
65+
// expected-note@+1{{used in buffer access here}}
66+
a = matrix[4][0];
67+
68+
a = matrix[idx][0]; // expected-note{{used in buffer access here}}
69+
70+
a = matrix[0][idx]; //expected-warning{{unsafe buffer access}}
71+
72+
a = matrix[idx][idx]; //expected-warning{{unsafe buffer access}} // expected-note{{used in buffer access here}}
73+
74+
return matrix[1][1];
75+
}
76+
77+
typedef float Float2x3x4[2][3][4];
78+
float multi_dimension_array(Float2x3x4& matrix) {
79+
float *f = matrix[0][2];
80+
return matrix[1][2][3];
81+
}
82+
83+
char array_strings[][11] = {
84+
"Apple", "Banana", "Cherry", "Date", "Elderberry"
85+
};
86+
87+
char array_string[] = "123456";
88+
89+
char access_strings() {
90+
char c = array_strings[0][4];
91+
c = array_strings[3][10];
92+
c = array_string[5];
93+
return c;
94+
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ void test_attribute_multiple_fields (D d) {
9696

9797
int v = d.buf[0]; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}
9898

99-
//expected-warning@+1{{unsafe buffer access}}
10099
v = d.buf[5]; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}
101100
}
102101

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-note2{{used in buffer access here}}
122122
}
123123

124124
// parameter having default values:

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

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ void testQualifiedParameters(const int * p, const int * const q, const int a[10]
109109
q[1], 1[q], q[-1], // expected-note3{{used in buffer access here}}
110110
a[1], // expected-note{{used in buffer access here}} `a` is of pointer type
111111
b[1][2] // expected-note{{used in buffer access here}} `b[1]` is of array type
112-
// expected-warning@-1{{unsafe buffer access}}
113112
);
114113
}
115114

@@ -128,29 +127,41 @@ T_t funRetT();
128127
T_t * funRetTStar();
129128

130129
void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) {
131-
foo(sp->a[1], // expected-warning{{unsafe buffer access}}
130+
foo(sp->a[1],
132131
sp->b[1], // expected-warning{{unsafe buffer access}}
133-
sp->c.a[1], // expected-warning{{unsafe buffer access}}
132+
sp->c.a[1],
134133
sp->c.b[1], // expected-warning{{unsafe buffer access}}
135-
s.a[1], // expected-warning{{unsafe buffer access}}
134+
s.a[1],
136135
s.b[1], // expected-warning{{unsafe buffer access}}
137-
s.c.a[1], // expected-warning{{unsafe buffer access}}
136+
s.c.a[1],
138137
s.c.b[1], // expected-warning{{unsafe buffer access}}
139-
sp2->a[1], // expected-warning{{unsafe buffer access}}
138+
sp2->a[1],
140139
sp2->b[1], // expected-warning{{unsafe buffer access}}
141-
sp2->c.a[1], // expected-warning{{unsafe buffer access}}
140+
sp2->c.a[1],
142141
sp2->c.b[1], // expected-warning{{unsafe buffer access}}
143-
s2.a[1], // expected-warning{{unsafe buffer access}}
142+
s2.a[1],
144143
s2.b[1], // expected-warning{{unsafe buffer access}}
145-
s2.c.a[1], // expected-warning{{unsafe buffer access}}
144+
s2.c.a[1],
146145
s2.c.b[1], // expected-warning{{unsafe buffer access}}
147-
funRetT().a[1], // expected-warning{{unsafe buffer access}}
146+
funRetT().a[1],
148147
funRetT().b[1], // expected-warning{{unsafe buffer access}}
149-
funRetTStar()->a[1], // expected-warning{{unsafe buffer access}}
148+
funRetTStar()->a[1],
150149
funRetTStar()->b[1] // expected-warning{{unsafe buffer access}}
151150
);
152151
}
153152

153+
union Foo {
154+
bool b;
155+
int arr[10];
156+
};
157+
158+
int testUnionMembers(Foo f) {
159+
int a = f.arr[0];
160+
a = f.arr[5];
161+
a = f.arr[10]; // expected-warning{{unsafe buffer access}}
162+
return a;
163+
}
164+
154165
int garray[10]; // expected-warning{{'garray' is an unsafe buffer that does not perform bounds checks}}
155166
int * gp = garray; // expected-warning{{'gp' is an unsafe pointer used for buffer access}}
156167
int gvar = gp[1]; // FIXME: file scope unsafe buffer access is not warned
@@ -213,7 +224,6 @@ void testTypedefs(T_ptr_t p) {
213224
// expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
214225
foo(p[1], // expected-note{{used in buffer access here}}
215226
p[1].a[1], // expected-note{{used in buffer access here}}
216-
// expected-warning@-1{{unsafe buffer access}}
217227
p[1].b[1] // expected-note{{used in buffer access here}}
218228
// expected-warning@-1{{unsafe buffer access}}
219229
);
@@ -223,10 +233,9 @@ template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) {
223233
// expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
224234
// expected-warning@-2{{'pt' is an unsafe pointer used for buffer access}}
225235
// 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}}
227236
foo(pt[1], // expected-note{{used in buffer access here}}
228237
a[1], // expected-note{{used in buffer access here}}
229-
b[1]); // expected-note{{used in buffer access here}}
238+
b[1]);
230239
return &t[1]; // expected-note{{used in buffer access here}}
231240
}
232241

@@ -376,7 +385,7 @@ int testArrayAccesses(int n, int idx) {
376385
typedef int A[3];
377386
const A tArr = {4, 5, 6};
378387
foo(tArr[0], tArr[1]);
379-
return cArr[0][1]; // expected-warning{{unsafe buffer access}}
388+
return cArr[0][1];
380389
}
381390

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

0 commit comments

Comments
 (0)