1 // RUN: %check_clang_tidy %s bugprone-sizeof-expression %t
2 
3 #define offsetof(type, member) __builtin_offsetof(type, member)
4 
5 typedef __SIZE_TYPE__ size_t;
6 typedef __WCHAR_TYPE__ wchar_t;
7 
8 extern void *memset(void *Dest, int Ch, size_t Count);
9 extern size_t strlen(const char *Str);
10 extern size_t wcslen(const wchar_t *Str);
11 extern char *strcpy(char *Dest, const char *Src);
12 extern wchar_t *wcscpy(wchar_t *Dest, const wchar_t *Src);
13 extern int scanf(const char *Format, ...);
14 extern int wscanf(const wchar_t *Format, ...);
15 
16 extern void sink(const void *P);
17 
18 enum { BufferSize = 1024 };
19 
20 void bad1a(void) {
21   int Buffer[BufferSize];
22 
23   int *P = &Buffer[0];
24   int *Q = P;
25   while (Q < P + sizeof(Buffer)) {
26     // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator [bugprone-sizeof-expression]
27     // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
28     *Q++ = 0;
29   }
30 }
31 
32 void bad1b(void) {
33   typedef int Integer;
34   Integer Buffer[BufferSize];
35 
36   Integer *P = &Buffer[0];
37   Integer *Q = P;
38   while (Q < P + sizeof(Buffer)) {
39     // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
40     // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(Integer)' == {{[0-9]+}}
41     *Q++ = 0;
42   }
43 }
44 
45 void good1(void) {
46   int Buffer[BufferSize];
47 
48   int *P = &Buffer[0];
49   int *Q = P;
50   while (Q < P + BufferSize) {
51     *Q++ = 0;
52   }
53 }
54 
55 void bad2(void) {
56   int Buffer[BufferSize];
57   int *P = Buffer;
58 
59   while (P < Buffer + sizeof(Buffer)) {
60     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
61     // CHECK-MESSAGES: :[[@LINE-2]]:21: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
62     *P++ = 0;
63   }
64 }
65 
66 void good2(void) {
67   int Buffer[BufferSize];
68   int *P = Buffer;
69 
70   while (P < Buffer + BufferSize) {
71     *P++ = 0;
72   }
73 }
74 
75 struct S {
76   long A, B, C;
77 };
78 
79 void bad3a(struct S *S) {
80   const size_t Offset = offsetof(struct S, B);
81   struct S *P = S;
82 
83   // This is not captureable by Tidy because the size/offset expression is
84   // not a direct child of the pointer arithmetics.
85   memset(P + Offset, 0, sizeof(struct S) - Offset);
86 }
87 
88 void good3a(struct S *S) {
89   const size_t Offset = offsetof(struct S, B);
90   char *P = (char*)S;
91 
92   // This is not captureable by Tidy because the size/offset expression is
93   // not a direct child of the pointer arithmetics.
94   memset(P + Offset, 0, sizeof(struct S) - Offset);
95 }
96 
97 void bad3b(struct S *S) {
98   memset(S + offsetof(struct S, B), 0,
99          sizeof(struct S) - offsetof(struct S, B));
100   // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: suspicious usage of 'offsetof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
101   // CHECK-MESSAGES: :[[@LINE-3]]:12: note: '+' in pointer arithmetic internally scales with 'sizeof(struct S)' == {{[0-9]+}}
102 }
103 
104 void good3b(struct S *S) {
105   char *P = (char*)S;
106   memset(P + offsetof(struct S, B), 0,
107          sizeof(struct S) - offsetof(struct S, B));
108 }
109 
110 void bad3c(void) {
111   struct S Buffer[BufferSize];
112 
113   struct S *P = &Buffer[0];
114   struct S *Q = P;
115   while (Q < P + sizeof(Buffer)) {
116     // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
117     // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(struct S)' == {{[0-9]+}}
118     sink(Q++);
119   }
120 }
121 
122 void bad4(void) {
123   int Buffer[BufferSize];
124 
125   int *P = &Buffer[0];
126   int *Q = P;
127   while (Q < P + BufferSize) {
128     *Q = 0;
129     Q += sizeof(*Q);
130     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+=' operator
131     // CHECK-MESSAGES: :[[@LINE-2]]:7: note: '+=' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
132   }
133 }
134 
135 void silenced4(void) {
136   char Buffer[BufferSize];
137 
138   char *P = &Buffer[0];
139   char *Q = P;
140   while (Q < P + BufferSize) {
141     *Q = 0;
142     Q += sizeof(*Q);
143   }
144 }
145 
146 void good4(void) {
147   char Buffer[BufferSize];
148 
149   char *P = &Buffer[0];
150   char *Q = P;
151   while (Q < P + BufferSize) {
152     *Q = 0;
153     Q += 1;
154   }
155 }
156 
157 void good5aa(void) {
158   int Buffer[BufferSize];
159 
160   int *P = &Buffer[0];
161   int *Q = P;
162   while (Q < P + BufferSize) {
163     *Q = 0;
164     Q += ( sizeof(Buffer) / sizeof(Buffer[0]) );
165   }
166 }
167 
168 void good5ab(void) {
169   int Buffer[BufferSize];
170 
171   int *P = &Buffer[0];
172   int *Q = P;
173   while (Q < P + BufferSize) {
174     *Q = 0;
175     Q = Q + ( sizeof(Buffer) / sizeof(Buffer[0]) );
176   }
177 }
178 
179 void good5ba(void) {
180   int Buffer[BufferSize];
181 
182   int *P = &Buffer[0];
183   int *Q = P;
184   while (Q < P + BufferSize) {
185     *Q = 0;
186     Q -= ( sizeof(Buffer) / sizeof(Buffer[0]) );
187   }
188 }
189 
190 void good5bb(void) {
191   int Buffer[BufferSize];
192 
193   int *P = &Buffer[0];
194   int *Q = P;
195   while (Q < P + BufferSize) {
196     *Q = 0;
197     Q = Q - ( sizeof(Buffer) / sizeof(Buffer[0]) );
198   }
199 }
200 
201 void bad6(void) {
202   int Buffer[BufferSize];
203 
204   int *P = &Buffer[0];
205   int *Q = P;
206   while (Q < P + BufferSize) {
207     *Q = 0;
208     Q = Q + sizeof(*Q);
209     // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
210     // CHECK-MESSAGES: :[[@LINE-2]]:11: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
211   }
212 }
213 
214 void silenced6(void) {
215   char Buffer[BufferSize];
216 
217   char *P = &Buffer[0];
218   char *Q = P;
219   while (Q < P + BufferSize) {
220     *Q = 0;
221     Q = Q + sizeof(*Q);
222   }
223 }
224 
225 void good6(void) {
226   char Buffer[BufferSize];
227 
228   char *P = &Buffer[0];
229   char *Q = P;
230   while (Q < P + BufferSize) {
231     *Q = 0;
232     Q = Q + 1;
233   }
234 }
235 
236 void silenced7(void) {
237   char Buffer[BufferSize];
238 
239   char *P = &Buffer[0];
240   const char *Q = P;
241   while (Q < P + BufferSize) {
242     sink(Q);
243     Q = Q + sizeof(*Q);
244   }
245 }
246 
247 void good7(void) {
248   char Buffer[BufferSize];
249 
250   char *P = &Buffer[0];
251   const char *Q = P;
252   while (Q < P + BufferSize) {
253     sink(Q);
254     Q = Q + 1;
255   }
256 }
257 
258 void bad8(void) {
259   int Buffer[BufferSize];
260 
261   int *P = &Buffer[0];
262   int *Q = P;
263   while (Q >= P) {
264     *Q = 0;
265     Q = Q - sizeof(*Q);
266     // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '-' operator
267     // CHECK-MESSAGES: :[[@LINE-2]]:11: note: '-' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
268   }
269 }
270 
271 void silenced8(void) {
272   char Buffer[BufferSize];
273 
274   char *P = &Buffer[0];
275   char *Q = P;
276   while (Q >= P) {
277     *Q = 0;
278     Q = Q - sizeof(*Q);
279   }
280 }
281 
282 void good8(void) {
283   char Buffer[BufferSize];
284 
285   char *P = &Buffer[0];
286   char *Q = P;
287   while (Q >= P) {
288     *Q = 0;
289     Q = Q - 1;
290   }
291 }
292 
293 void good9(void) {
294   int Buffer[BufferSize];
295 
296   int *P = &Buffer[0];
297   int *Q = P + BufferSize;
298   int N = Q - P;
299   while (N >= 0) {
300     Q[N] = 0;
301     N = N - 1;
302   }
303 }
304 
305 void good10(void) {
306   int Buffer[BufferSize];
307 
308   int *P = &Buffer[0];
309   int *Q = Buffer + BufferSize;
310   int I = sizeof(*P) - sizeof(*Q);
311 
312   sink(&I);
313 }
314 
315 void good11(void) {
316   int Buffer[BufferSize];
317 
318   int *P = &Buffer[0];
319   int *Q = Buffer + BufferSize;
320   int I = sizeof(Q) - sizeof(*P);
321 
322   sink(&I);
323 }
324 
325 void bad12(void) {
326   wchar_t Message[BufferSize];
327   wcscpy(Message, L"Message: ");
328   wscanf(L"%s", Message + wcslen(Message) * sizeof(wchar_t));
329   // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
330   // CHECK-MESSAGES: :[[@LINE-2]]:25: note: '+' in pointer arithmetic internally scales with 'sizeof(wchar_t)' == {{[0-9]+}}
331 }
332 
333 void silenced12(void) {
334   char Message[BufferSize];
335   strcpy(Message, "Message: ");
336   scanf("%s", Message + strlen(Message) * sizeof(char));
337 }
338 
339 void nomatch12(void) {
340   char Message[BufferSize];
341   strcpy(Message, "Message: ");
342   scanf("%s", Message + strlen(Message));
343 }
344 
345 void good12(void) {
346   wchar_t Message[BufferSize];
347   wcscpy(Message, L"Message: ");
348   wscanf(L"%s", Message + wcslen(Message));
349 }
350 
351 void good13(void) {
352   int Buffer[BufferSize];
353 
354   int *P = &Buffer[0];
355   while (P < Buffer + sizeof(Buffer) / sizeof(int)) {
356     // NO-WARNING: Calculating the element count of the buffer here, which is
357     // safe with this idiom (as long as the types don't change).
358     ++P;
359   }
360 
361   while (P < Buffer + sizeof(Buffer) / sizeof(Buffer[0])) {
362     // NO-WARNING: Calculating the element count of the buffer here, which is
363     // safe with this idiom.
364     ++P;
365   }
366 
367   while (P < Buffer + sizeof(Buffer) / sizeof(*P)) {
368     // NO-WARNING: Calculating the element count of the buffer here, which is
369     // safe with this idiom.
370     ++P;
371   }
372 }
373 
374 void situational14(int *Buffer, size_t BufferSize) {
375   int *P = &Buffer[0];
376   while (P < Buffer + BufferSize / sizeof(*Buffer)) {
377     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
378     // CHECK-MESSAGES: :[[@LINE-2]]:21: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
379     ++P;
380   }
381 }
382