xref: /llvm-project/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-array.cpp (revision 644ac2a018c9bf83c9ba256074e552ad7f1fe941)
1 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \
2 // RUN:            -fsafe-buffer-usage-suggestions \
3 // RUN:            -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
4 typedef int * Int_ptr_t;
5 typedef int Int_t;
6 
simple(unsigned idx)7 void simple(unsigned idx) {
8   int buffer[10];
9 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array<int, 10> buffer"
10   buffer[idx] = 0;
11 }
12 
array2d(unsigned idx)13 void array2d(unsigned idx) {
14   int buffer[10][10];
15 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
16   buffer[idx][idx] = 0;
17 }
18 
array2d_vla(unsigned sz,unsigned idx)19 void array2d_vla(unsigned sz, unsigned idx) {
20   int buffer1[10][sz];
21 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
22   int buffer2[sz][10];
23 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
24   buffer1[idx][idx] = 0;
25   buffer2[idx][idx] = 0;
26 }
27 
array2d_assign_from_elem(unsigned idx)28 void array2d_assign_from_elem(unsigned idx) {
29   int buffer[10][10];
30 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
31   int a = buffer[idx][idx];
32 }
33 
34 void array2d_use(int *);
array2d_call(unsigned idx)35 void array2d_call(unsigned idx) {
36   int buffer[10][10];
37 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
38   array2d_use(buffer[idx]);
39 }
array2d_call_vla(unsigned sz,unsigned idx)40 void array2d_call_vla(unsigned sz, unsigned idx) {
41   int buffer[10][sz];
42 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
43   array2d_use(buffer[idx]);
44 }
45 
array2d_typedef(unsigned idx)46 void array2d_typedef(unsigned idx) {
47   typedef int ten_ints_t[10];
48 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
49   ten_ints_t buffer[10];
50 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
51   buffer[idx][idx] = 0;
52 }
53 
whitespace_in_declaration(unsigned idx)54 void whitespace_in_declaration(unsigned idx) {
55   int      buffer_w   [       10 ];
56 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:35}:"std::array<int, 10> buffer_w"
57   buffer_w[idx] = 0;
58 }
59 
comments_in_declaration(unsigned idx)60 void comments_in_declaration(unsigned idx) {
61   int   /* [A] */   buffer_w  /* [B] */ [  /* [C] */ 10 /* [D] */  ] ;
62 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:69}:"std::array<int   /* [A] */, /* [C] */ 10 /* [D] */> buffer_w"
63   buffer_w[idx] = 0;
64 }
65 
initializer(unsigned idx)66 void initializer(unsigned idx) {
67   int buffer[3] = {0};
68 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:16}:"std::array<int, 3> buffer"
69 
70   int buffer2[3] = {0, 1, 2};
71 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array<int, 3> buffer2"
72 
73   buffer[idx] = 0;
74   buffer2[idx] = 0;
75 }
76 
auto_size(unsigned idx)77 void auto_size(unsigned idx) {
78   int buffer[] = {0, 1, 2};
79 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
80 // FIXME: implement support
81 
82   buffer[idx] = 0;
83 }
84 
universal_initialization(unsigned idx)85 void universal_initialization(unsigned idx) {
86   int buffer[] {0, 1, 2};
87 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
88 // FIXME: implement support
89 
90   buffer[idx] = 0;
91 }
92 
multi_decl1(unsigned idx)93 void multi_decl1(unsigned idx) {
94   int a, buffer[10];
95 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
96 // FIXME: implement support
97 
98   buffer[idx] = 0;
99 }
100 
multi_decl2(unsigned idx)101 void multi_decl2(unsigned idx) {
102   int buffer[10], b;
103 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
104 // FIXME: implement support
105 
106   buffer[idx] = 0;
107 }
108 
local_array_ptr_to_const(unsigned idx,const int * & a)109 void local_array_ptr_to_const(unsigned idx, const int*& a) {
110   const int * buffer[10] = {a};
111 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array<const int *, 10> buffer"
112   a = buffer[idx];
113 }
114 
local_array_const_ptr(unsigned idx,int * & a)115 void local_array_const_ptr(unsigned idx, int*& a) {
116   int * const buffer[10] = {a};
117 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array<int * const, 10> buffer"
118 
119   a = buffer[idx];
120 }
121 
local_array_const_ptr_via_typedef(unsigned idx,int * & a)122 void local_array_const_ptr_via_typedef(unsigned idx, int*& a) {
123   typedef int * const my_const_ptr;
124   my_const_ptr buffer[10] = {a};
125 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:26}:"std::array<my_const_ptr, 10> buffer"
126 
127   a = buffer[idx];
128 }
129 
local_array_const_ptr_to_const(unsigned idx,const int * & a)130 void local_array_const_ptr_to_const(unsigned idx, const int*& a) {
131   const int * const buffer[10] = {a};
132 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:31}:"std::array<const int * const, 10> buffer"
133 
134   a = buffer[idx];
135 
136 }
137 
138 template<typename T>
unsupported_local_array_in_template(unsigned idx)139 void unsupported_local_array_in_template(unsigned idx) {
140   T buffer[10];
141 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
142   buffer[idx] = 0;
143 }
144 // Instantiate the template function to force its analysis.
145 template void unsupported_local_array_in_template<int>(unsigned);
146 
147 typedef unsigned int my_uint;
typedef_as_elem_type(unsigned idx)148 void typedef_as_elem_type(unsigned idx) {
149   my_uint buffer[10];
150 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:21}:"std::array<my_uint, 10> buffer"
151   buffer[idx] = 0;
152 }
153 
decltype_as_elem_type(unsigned idx)154 void decltype_as_elem_type(unsigned idx) {
155   int a;
156   decltype(a) buffer[10];
157 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array<decltype(a), 10> buffer"
158   buffer[idx] = 0;
159 }
160 
macro_as_elem_type(unsigned idx)161 void macro_as_elem_type(unsigned idx) {
162 #define MY_INT int
163   MY_INT buffer[10];
164 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
165 // FIXME: implement support
166 
167   buffer[idx] = 0;
168 #undef MY_INT
169 }
170 
macro_as_identifier(unsigned idx)171 void macro_as_identifier(unsigned idx) {
172 #define MY_BUFFER buffer
173   int MY_BUFFER[10];
174 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:20}:"std::array<int, 10> MY_BUFFER"
175   MY_BUFFER[idx] = 0;
176 #undef MY_BUFFER
177 }
178 
macro_as_size(unsigned idx)179 void macro_as_size(unsigned idx) {
180 #define MY_TEN 10
181   int buffer[MY_TEN];
182 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:21}:"std::array<int, MY_TEN> buffer"
183   buffer[idx] = 0;
184 #undef MY_TEN
185 }
186 
187 typedef unsigned int my_array[42];
188 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
typedef_as_array_type(unsigned idx)189 void typedef_as_array_type(unsigned idx) {
190   my_array buffer;
191 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
192   buffer[idx] = 0;
193 }
194 
decltype_as_array_type(unsigned idx)195 void decltype_as_array_type(unsigned idx) {
196   int buffer[42];
197 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
198   decltype(buffer) buffer2;
199 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*}
200   buffer2[idx] = 0;
201 }
202 
constant_as_size(unsigned idx)203 void constant_as_size(unsigned idx) {
204   const unsigned my_const = 10;
205   int buffer[my_const];
206 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:23}:"std::array<int, my_const> buffer"
207   buffer[idx] = 0;
208 }
209 
subscript_negative()210 void subscript_negative() {
211   int buffer[10];
212 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array<int, 10> buffer"
213 
214   // For constant-size arrays any negative index will lead to buffer underflow.
215   // std::array::operator[] has unsigned parameter so the value will be casted to unsigned.
216   // This will very likely be buffer overflow but hardened std::array catch these at runtime.
217   buffer[-5] = 0;
218 }
219 
subscript_signed(int signed_idx)220 void subscript_signed(int signed_idx) {
221   int buffer[10];
222 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array<int, 10> buffer"
223 
224   // For constant-size arrays any negative index will lead to buffer underflow.
225   // std::array::operator[] has unsigned parameter so the value will be casted to unsigned.
226   // This will very likely be buffer overflow but hardened std::array catches these at runtime.
227   buffer[signed_idx] = 0;
228 }
229